Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

487 lines
14 KiB

  1. /*++
  2. Microsoft Windows
  3. Copyright (C) Microsoft Corporation, 1981 - 1999
  4. Module Name:
  5. sendprogress.cpp
  6. Abstract:
  7. Author:
  8. Rahul Thombre (RahulTh) 4/30/1998
  9. Revision History:
  10. 4/30/1998 RahulTh
  11. Created this module.
  12. --*/
  13. // SendProgress.cpp : implementation file
  14. //
  15. #include "precomp.hxx"
  16. #include "winsock.h"
  17. #define MAX_FILENAME_DISPLAY 35
  18. #define DIALOG_DISPLAY_DURATION 800 //the minimum amount of time a dialog
  19. //should be displayed (in milliseconds)
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CSendProgress dialog
  27. CSendProgress::CSendProgress(LPTSTR lpszFileList /*=NULL*/, int iCharCount /*=0*/, CWnd* pParent /*=NULL*/)
  28. {
  29. m_dwMagicID = MAGIC_ID; //an id used to validate CSendProgress pointers
  30. //received over an RPC interface.
  31. m_lpszFileList = lpszFileList;
  32. m_iCharCount = iCharCount;
  33. m_lSelectedDeviceID = errIRFTP_SELECTIONCANCELLED;
  34. m_lpszSelectedDeviceName[0] = '\0';
  35. m_fSendDone = FALSE;
  36. m_fTimerExpired = FALSE;
  37. m_ptl = NULL;
  38. m_fCancelled = FALSE;
  39. appController->PostMessage (WM_APP_KILL_TIMER);
  40. InterlockedIncrement (&g_lUIComponentCount);
  41. Create(IDD, appController);
  42. //{{AFX_DATA_INIT(CSendProgress)
  43. // NOTE: the ClassWizard will add member initialization here
  44. //}}AFX_DATA_INIT
  45. }
  46. void CSendProgress::DoDataExchange(CDataExchange* pDX)
  47. {
  48. CDialog::DoDataExchange(pDX);
  49. //{{AFX_DATA_MAP(CSendProgress)
  50. DDX_Control(pDX, IDC_XFER_PERCENTAGE, m_xferPercentage);
  51. DDX_Control(pDX, IDC_CONNECTIONTEXT, m_connectedTo);
  52. DDX_Control(pDX, IDC_FILESEND_PROGRESS, m_transferProgress);
  53. DDX_Control(pDX, IDC_FILESEND_ANIM, m_transferAnim);
  54. DDX_Control(pDX, IDC_FILE_NAME, m_fileName);
  55. DDX_Control(pDX, IDC_SENDING_TITLE, m_sndTitle);
  56. DDX_Control(pDX, IDCANCEL, m_btnCancel);
  57. //}}AFX_DATA_MAP
  58. }
  59. BEGIN_MESSAGE_MAP(CSendProgress, CDialog)
  60. //{{AFX_MSG_MAP(CSendProgress)
  61. ON_WM_COPYDATA()
  62. ON_WM_TIMER()
  63. ON_MESSAGE(WM_APP_UPDATE_PROGRESS, OnUpdateProgress)
  64. ON_MESSAGE(WM_APP_SEND_COMPLETE, OnSendComplete)
  65. //}}AFX_MSG_MAP
  66. END_MESSAGE_MAP()
  67. /////////////////////////////////////////////////////////////////////////////
  68. // CSendProgress message handlers
  69. ULONG
  70. GetLocationDescription(
  71. FAILURE_LOCATION Location
  72. )
  73. {
  74. switch (Location)
  75. {
  76. case locStartup:
  77. return IDS_LOC_STARTUP;
  78. case locConnect:
  79. return IDS_LOC_CONNECT;
  80. case locFileOpen:
  81. return IDS_LOC_FILEOPEN;
  82. case locFileRead:
  83. return IDS_LOC_FILEREAD;
  84. case locFileSend:
  85. return IDS_LOC_FILESEND;
  86. case locFileRecv:
  87. return IDS_LOC_FILERECV;
  88. case locFileWrite:
  89. return IDS_LOC_FILEWRITE;
  90. case locUnknown:
  91. default:
  92. return IDS_LOC_UNKNOWN;
  93. }
  94. }
  95. BOOL CSendProgress::OnInitDialog()
  96. {
  97. TCHAR lpszConnectionInfo[100];
  98. TCHAR lpszDeviceName[50];
  99. TCHAR lpszConnecting[50];
  100. error_status_t err;
  101. error_status_t sendError;
  102. LONG lDeviceID;
  103. FAILURE_LOCATION location=locUnknown;
  104. CError error;
  105. CError xferError (this);
  106. CString szConnect;
  107. CString szErrorDesc;
  108. CString szLocDesc;
  109. HRESULT hr = E_FAIL;
  110. OBEX_DEVICE_TYPE DeviceType;
  111. CDialog::OnInitDialog();
  112. ::LoadString (g_hInstance, IDS_CONNECTEDTO, lpszConnectionInfo, 100);
  113. ::LoadString (g_hInstance, IDS_CONNECTING, lpszConnecting, 50);
  114. szConnect = lpszConnecting;
  115. m_transferProgress.SetPos(0);
  116. m_transferAnim.Open (IDR_TRANSFER_AVI);
  117. m_transferAnim.Play(0, -1, -1);
  118. m_fileName.SetWindowText (L"");
  119. m_connectedTo.SetWindowText ((LPCTSTR) szConnect);
  120. m_xferPercentage.SetWindowText(TEXT("0%"));
  121. if (!g_deviceList.GetDeviceCount())
  122. {
  123. error.ShowMessage (IDS_NODEVICES_ERROR);
  124. DestroyWindow();
  125. return TRUE;
  126. }
  127. lDeviceID = g_deviceList.SelectDevice(this, lpszDeviceName);
  128. switch(lDeviceID)
  129. {
  130. case errIRFTP_NODEVICE:
  131. error.ShowMessage (IDS_MISSING_RECIPIENT);
  132. case errIRFTP_SELECTIONCANCELLED:
  133. DestroyWindow();
  134. return TRUE;
  135. case errIRFTP_MULTDEVICES: //there were multiple devices in range, one of which was selected
  136. if (g_deviceList.GetDeviceType(m_lSelectedDeviceID,&DeviceType)) {
  137. SendFiles (g_hIrRpcHandle, (COOKIE)this, TEXT(""), m_lpszFileList, m_iCharCount, m_lSelectedDeviceID, DeviceType, &sendError, &location);
  138. lstrcat (lpszConnectionInfo, m_lpszSelectedDeviceName);
  139. m_connectedTo.SetWindowText(lpszConnectionInfo);
  140. } else {
  141. error.ShowMessage (IDS_MISSING_RECIPIENT);
  142. DestroyWindow();
  143. return TRUE;
  144. }
  145. break;
  146. default: //there was only one device in range
  147. if (g_deviceList.GetDeviceType(lDeviceID,&DeviceType)) {
  148. SendFiles (g_hIrRpcHandle, (COOKIE)this, TEXT(""), m_lpszFileList, m_iCharCount, lDeviceID, DeviceType, &sendError, &location);
  149. lstrcat (lpszConnectionInfo, lpszDeviceName);
  150. m_connectedTo.SetWindowText(lpszConnectionInfo);
  151. } else {
  152. error.ShowMessage (IDS_MISSING_RECIPIENT);
  153. DestroyWindow();
  154. return TRUE;
  155. }
  156. break;
  157. }
  158. if (sendError)
  159. {
  160. LPVOID lpMessageBuffer;
  161. TCHAR ErrDesc [ERROR_DESCRIPTION_LENGTH];
  162. CString ErrorDescription;
  163. if (!FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  164. FORMAT_MESSAGE_IGNORE_INSERTS |
  165. FORMAT_MESSAGE_FROM_SYSTEM,
  166. NULL, // ignored
  167. sendError,
  168. 0, // try default language ids
  169. (LPTSTR) &lpMessageBuffer,
  170. 0,
  171. NULL // ignored
  172. ))
  173. {
  174. wsprintf(ErrDesc, g_Strings.ErrorNoDescription, sendError);
  175. //using the overloaded CString assignment operator. It is
  176. //essentially a string copy, but MFC takes care of allocating
  177. //and freeing the destination buffer.
  178. ErrorDescription = ErrDesc;
  179. }
  180. else
  181. {
  182. //Note: this is not a pointer assignment. We are using the
  183. //overloaded CString assignment operator which essentially
  184. //does a string copy. (see comments above)
  185. ErrorDescription = (TCHAR *) lpMessageBuffer;
  186. LocalFree (lpMessageBuffer);
  187. }
  188. szLocDesc.LoadString (GetLocationDescription(location));
  189. xferError.ShowMessage (IDS_XFER_ERROR, (LPCTSTR) szLocDesc,
  190. (LPCTSTR) ErrorDescription);
  191. DestroyWindow();
  192. }
  193. //there were no errors.
  194. //first put up a taskbar button for the dialog
  195. //Initialize the taskbar list interface
  196. hr = CoInitialize(NULL);
  197. if (SUCCEEDED (hr))
  198. hr = CoCreateInstance(CLSID_TaskbarList,
  199. NULL,
  200. CLSCTX_INPROC_SERVER,
  201. IID_ITaskbarList,
  202. (LPVOID*)&m_ptl);
  203. if (SUCCEEDED(hr))
  204. {
  205. hr = m_ptl->HrInit();
  206. }
  207. else
  208. {
  209. m_ptl = NULL;
  210. }
  211. if (m_ptl)
  212. {
  213. if (SUCCEEDED(hr))
  214. m_ptl->AddTab(m_hWnd);
  215. else
  216. {
  217. m_ptl->Release();
  218. m_ptl = NULL;
  219. }
  220. }
  221. //Also set a timer to go off in half a second
  222. //this timer is used to ensure that this dialog is displayed for
  223. //at least half a second so that users can see that the file has been
  224. //sent
  225. //if we fail to get a timer, we simply treat this condition as if the
  226. //timer has expired
  227. m_fTimerExpired = SetTimer (1, DIALOG_DISPLAY_DURATION, NULL)?FALSE:TRUE;
  228. return TRUE; // return TRUE unless you set the focus to a control
  229. // EXCEPTION: OCX Property Pages should return FALSE
  230. }
  231. void CSendProgress::PostNcDestroy()
  232. {
  233. //do some cleanup
  234. if (m_lpszFileList)
  235. delete [] m_lpszFileList;
  236. BOOL fNoUIComponents = (0 == InterlockedDecrement (&g_lUIComponentCount));
  237. if (fNoUIComponents && ! g_deviceList.GetDeviceCount())
  238. {
  239. //there are no UI components displayed and there are no devices in
  240. //range. Start the timer. If the timer expires, the app. will quit.
  241. appController->PostMessage (WM_APP_START_TIMER);
  242. }
  243. delete this;
  244. }
  245. //removes the taskbar button if one had been put up
  246. BOOL CSendProgress::DestroyWindow()
  247. {
  248. //stop the animation and close the file.
  249. m_transferAnim.Stop();
  250. m_transferAnim.Close();
  251. //if a taskbar button had been put up, remove that first
  252. if (m_ptl)
  253. {
  254. m_ptl->DeleteTab(m_hWnd);
  255. m_ptl->Release();
  256. m_ptl = NULL;
  257. }
  258. //then destroy the window
  259. return CWnd::DestroyWindow();
  260. }
  261. void CSendProgress::OnCancel()
  262. {
  263. TCHAR lpszCancel[MAX_PATH];
  264. CancelSend(g_hIrRpcHandle, (COOKIE)this);
  265. //important: do not destroy the window here.
  266. //must wait until confirmation of the cancel
  267. //is received from the other machine. after that
  268. //irxfer will call sendcomplete. That is when the
  269. //window should get destroyed. otherwise, CWnd pointer
  270. //for this window might get reused and messages from
  271. //irxfer meant for this window will go to another window
  272. //which could cause it to get destroyed without the transmission
  273. //getting interrupted.
  274. //
  275. //but make the user aware that an attempt to cancel the send is being made
  276. m_fCancelled = TRUE;
  277. m_btnCancel.EnableWindow(FALSE);
  278. m_sndTitle.SetWindowText (TEXT(""));
  279. m_fileName.SetWindowText (TEXT(""));
  280. lpszCancel[0] = '\0';
  281. ::LoadString (g_hInstance, IDS_SENDCANCEL, lpszCancel, MAX_PATH);
  282. m_fileName.SetWindowText (lpszCancel);
  283. }
  284. void CSendProgress::OnTimer (UINT nTimerID)
  285. {
  286. m_fTimerExpired = TRUE;
  287. //we don't need the timer any more. it needs to go off only once
  288. KillTimer(1);
  289. //half a second has elapsed since we started
  290. //if the send is already complete, then it is this routine's
  291. //responsibility to destroy the window since the SEND_COMPLETE
  292. //notification has already been received
  293. if (m_fSendDone)
  294. DestroyWindow();
  295. }
  296. BOOL CSendProgress::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
  297. {
  298. AFX_MANAGE_STATE (AfxGetStaticModuleState());
  299. SEND_FAILURE_DATA * pData = (SEND_FAILURE_DATA *) (pCopyDataStruct->lpData);
  300. LPVOID lpMessageBuffer;
  301. TCHAR ErrDesc [ERROR_DESCRIPTION_LENGTH];
  302. CString ErrorDescription;
  303. CString szErrorDesc;
  304. CString szLocDesc;
  305. CError error (this);
  306. if (m_fCancelled)
  307. {
  308. return TRUE;
  309. }
  310. if (!FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  311. FORMAT_MESSAGE_IGNORE_INSERTS |
  312. FORMAT_MESSAGE_FROM_SYSTEM,
  313. NULL, // ignored
  314. pData->Error,
  315. 0, // try default language ids
  316. (LPTSTR) &lpMessageBuffer,
  317. 0,
  318. NULL // ignored
  319. ))
  320. {
  321. wsprintf(ErrDesc, g_Strings.ErrorNoDescription, pData->Error);
  322. //using the overloaded CString assignment operator. It is
  323. //essentially a string copy, but MFC takes care of allocating
  324. //and freeing the destination buffer.
  325. ErrorDescription = ErrDesc;
  326. }
  327. else
  328. {
  329. //Note: this is not a pointer assignment. We are using the
  330. //overloaded CString assignment operator which essentially
  331. //does a string copy. (see comments above)
  332. ErrorDescription = (TCHAR *) lpMessageBuffer;
  333. LocalFree (lpMessageBuffer);
  334. }
  335. szLocDesc.LoadString (GetLocationDescription(pData->Location));
  336. error.ShowMessage (IDS_SEND_FAILURE, pData->FileName, (LPCTSTR) szLocDesc,
  337. (LPCTSTR) ErrorDescription);
  338. return TRUE;
  339. }
  340. void CSendProgress::OnUpdateProgress (WPARAM wParam, LPARAM lParam)
  341. {
  342. TCHAR lpszXferPercentage [50];
  343. wsprintf(lpszXferPercentage, TEXT("%d%%"), (int)lParam);
  344. m_xferPercentage.SetWindowText (lpszXferPercentage);
  345. m_transferProgress.SetPos((int)lParam);
  346. }
  347. void CSendProgress::OnSendComplete (WPARAM wParam, LPARAM lParam)
  348. {
  349. m_fSendDone = TRUE;
  350. //make sure that the dialog is displayed for at least half a second
  351. if (m_fTimerExpired)
  352. DestroyWindow();
  353. }
  354. //+--------------------------------------------------------------------------
  355. //
  356. // Member: SetCurrentFileName
  357. //
  358. // Synopsis: displays on the progress dialog the name of the file that is
  359. // currently being transmitted
  360. //
  361. // Arguments: [in] pwszCurrFile : name of the file being transmitted
  362. //
  363. // Returns: nothing
  364. //
  365. // History: 12/14/1998 RahulTh created
  366. //
  367. // Notes:
  368. //
  369. //---------------------------------------------------------------------------
  370. void CSendProgress::SetCurrentFileName (wchar_t * pwszCurrFile)
  371. {
  372. WCHAR * pwszSource;
  373. WCHAR * pwszDest;
  374. WCHAR * pwszTemp;
  375. int len;
  376. int cbStart;
  377. int cbEnd;
  378. int i;
  379. const int cbCenter = 5;
  380. if (m_fCancelled)
  381. {
  382. //the user has already hit cancel on this dialog and we are just
  383. //waiting for confirmation from irxfer. Hence we do not change
  384. //the file name as that control is now being used to indicate
  385. //that we are trying to abort the file transfer
  386. return;
  387. }
  388. if (!pwszCurrFile)
  389. {
  390. m_fileName.SetWindowText (L"");
  391. return;
  392. }
  393. len = wcslen (pwszCurrFile);
  394. if (len > MAX_FILENAME_DISPLAY)
  395. {
  396. cbStart = MAX_FILENAME_DISPLAY/2 - cbCenter;
  397. cbEnd = MAX_FILENAME_DISPLAY - cbStart - cbCenter;
  398. pwszTemp = pwszCurrFile + cbStart;
  399. pwszTemp [0] = L' ';
  400. pwszTemp[1] = pwszTemp[2] = pwszTemp[3] = L'.';
  401. pwszTemp[4] = L' ';
  402. for (i = 0, pwszSource = pwszCurrFile + len - cbEnd, pwszDest = pwszTemp + cbCenter;
  403. i <= cbEnd; /*account for the terminating NULL too*/
  404. i++, pwszSource++, pwszDest++)
  405. *pwszDest = *pwszSource;
  406. }
  407. m_fileName.SetWindowText (pwszCurrFile);
  408. return;
  409. }