Leaked source code of windows server 2003
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.

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