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.

847 lines
23 KiB

  1. /*++
  2. Microsoft Windows
  3. Copyright (C) Microsoft Corporation, 1981 - 1999
  4. Module Name:
  5. utils.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. 10/12/98 RahulTh
  13. Better error handling capabilities added : CError etc.
  14. --*/
  15. #include "precomp.hxx"
  16. #define VALIDATE_SEND_COOKIE(cookie) \
  17. { \
  18. __try \
  19. { \
  20. *pStatus = ERROR_INVALID_DATA; \
  21. if (MAGIC_ID != ((CSendProgress *)cookie)->m_dwMagicID) \
  22. return; \
  23. *pStatus = ERROR_SUCCESS; \
  24. } \
  25. __except (EXCEPTION_EXECUTE_HANDLER) \
  26. { \
  27. return; \
  28. } \
  29. }
  30. ////////////////////////////////////////////////////////////////////////
  31. //
  32. //RPC Functions
  33. //
  34. ///////////////////////////////////////////////////////////////////////
  35. void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t Size)
  36. {
  37. return new char[Size];
  38. }
  39. void __RPC_USER MIDL_user_free( void __RPC_FAR * buf)
  40. {
  41. delete [] buf;
  42. }
  43. //
  44. // wireless link specific errors
  45. //
  46. ERROR_TO_STRING_ID g_ErrorToStringId[] =
  47. {
  48. {ERROR_IRTRANP_OUT_OF_MEMORY, IDS_ERROR_NO_MEMORY},
  49. {ERROR_IRTRANP_DISK_FULL, IDS_ERROR_DISK_FULL},
  50. {ERROR_SCEP_CANT_CREATE_FILE, IDS_ERROR_DISK_FULL},
  51. {ERROR_SCEP_ABORT, IDS_ERROR_ABORTED},
  52. {ERROR_SCEP_INVALID_PROTOCOL, IDS_ERROR_PROTOCOL},
  53. {ERROR_SCEP_PDU_TOO_LARGE, IDS_ERROR_PROTOCOL},
  54. {ERROR_BFTP_INVALID_PROTOCOL, IDS_ERROR_PROTOCOL},
  55. {ERROR_BFTP_NO_MORE_FRAGMENTS, IDS_ERROR_PROTOCOL},
  56. {ERROR_SUCCESS, -1}
  57. };
  58. ////////////////////////////////////////////////////////////////////
  59. //
  60. //Miscellaneous useful functions
  61. //
  62. ///////////////////////////////////////////////////////////////////
  63. int ParseFileNames (TCHAR* pszInString, TCHAR* pszFilesList, int& iCharCount)
  64. {
  65. ASSERT(pszFilesList != NULL);
  66. ASSERT(pszInString != NULL);
  67. BOOL fInQuotes = FALSE;
  68. BOOL fIgnoreSpaces = FALSE;
  69. TCHAR* pszSource = pszInString;
  70. TCHAR* pszTarget = pszFilesList;
  71. int iFileCount = 0;
  72. TCHAR curr;
  73. //ignore leading whitespaces
  74. while(' ' == *pszSource || '\t' == *pszSource)
  75. pszSource++;
  76. iCharCount = 0;
  77. *pszTarget = '\0'; //precautionary measures
  78. if ('\0' == *pszSource) //special case : if this was an empty string, return 0
  79. return iFileCount;
  80. //parse the string to get filenames
  81. while(curr = *pszSource)
  82. {
  83. if('\"' == curr)
  84. {
  85. fInQuotes = fInQuotes?FALSE:TRUE;
  86. }
  87. else if(' ' == curr && !fInQuotes)
  88. {
  89. if(!fIgnoreSpaces)
  90. {
  91. *pszTarget++ = 0;
  92. iFileCount++;
  93. iCharCount++;
  94. fIgnoreSpaces = TRUE;
  95. }
  96. }
  97. else
  98. {
  99. *pszTarget++ = curr;
  100. iCharCount++;
  101. fIgnoreSpaces = FALSE;
  102. }
  103. pszSource++;
  104. }
  105. if(' ' != *(pszSource-1)) //if there was no trailing space
  106. {
  107. *pszTarget++ = '\0'; //then the last file was not accounted for.
  108. iCharCount++; //so we do it here
  109. iFileCount++;
  110. }
  111. *pszTarget++ = '\0'; //should have 2 terminating nulls
  112. iCharCount++;
  113. return iFileCount;
  114. }
  115. //+--------------------------------------------------------------------------
  116. //
  117. // Function: GetIRRegVal
  118. //
  119. // Synopsis: gets the specified registry value from the IR subtree in HKCU
  120. //
  121. // Arguments: [in] szValName : the name of the value.
  122. // [in] dwDefVal : the default value to be returned if the read
  123. // from the registry fails or if the value is
  124. // missing.
  125. //
  126. // Returns: the actual value stored in the registry or the default value
  127. // if the read fails.
  128. //
  129. // History: 10/27/1999 RahulTh created
  130. //
  131. // Notes:
  132. //
  133. //---------------------------------------------------------------------------
  134. DWORD GetIRRegVal (LPCTSTR szValName, DWORD dwDefVal)
  135. {
  136. HKEY hftKey = NULL;
  137. DWORD iSize = sizeof(DWORD);
  138. DWORD data = 0;
  139. DWORD Status;
  140. RegOpenKeyEx (HKEY_CURRENT_USER, TEXT("Control Panel\\Infrared\\File Transfer"),
  141. 0, KEY_READ, &hftKey);
  142. if (!hftKey)
  143. return dwDefVal;
  144. Status = RegQueryValueEx (hftKey, szValName, NULL, NULL,
  145. (LPBYTE)&data, &iSize);
  146. if (ERROR_SUCCESS != Status)
  147. data = dwDefVal;
  148. RegCloseKey (hftKey);
  149. return data;
  150. }
  151. TCHAR* GetFullPathnames (TCHAR* pszPath, //directory in which the files are located
  152. const TCHAR* pszFilesList, //NULL separated list of filenames
  153. int iFileCount, //number of files in pszFilesList
  154. int& iCharCount //number of characters in pszFilesList. also returns the number of chars in the return string
  155. )
  156. {
  157. int iChars;
  158. int iPathLen = lstrlen(pszPath);
  159. if (pszPath[iPathLen - 1] != '\\') //append a '\' character to the path if not already present
  160. {
  161. pszPath[iPathLen++] = '\\';
  162. pszPath[iPathLen] = '\0';
  163. }
  164. int iSize = (iChars = iFileCount*iPathLen + iCharCount);
  165. TCHAR* pszFilePathList = new TCHAR[iSize];
  166. TCHAR* pszTemp = pszFilePathList;
  167. int iLen;
  168. while(*pszFilesList)
  169. {
  170. lstrcpy(pszTemp, pszPath);
  171. pszTemp += iPathLen;
  172. lstrcpy(pszTemp, pszFilesList);
  173. iLen = lstrlen(pszFilesList);
  174. pszFilesList += iLen + 1;
  175. pszTemp += iLen + 1;
  176. }
  177. *pszTemp = '\0'; //should be terminated by 2 null characters
  178. iCharCount = (int)(pszTemp - pszFilePathList) + 1; //return the actual char count of this string
  179. return pszFilePathList;
  180. }
  181. TCHAR* ProcessOneFile (TCHAR* pszPath, //directory in which the files are located
  182. const TCHAR* pszFilesList, //NULL separated list of filenames
  183. int iFileCount, //number of files in pszFilesList
  184. int& iCharCount //number of characters in pszFilesList. also returns the number of characters in the return string
  185. )
  186. {
  187. int iFileLen, iPathLen;
  188. TCHAR* pszFullFileName;
  189. iFileLen = lstrlen (pszFilesList);
  190. iPathLen = lstrlen (pszPath);
  191. ASSERT (iFileLen);
  192. ASSERT (iPathLen);
  193. if(':' == pszFilesList[1] //this is an absolute path starting with the drive letter;
  194. || ('\\' == pszFilesList[0] && '\\' == pszFilesList[1]) //UNC path
  195. )
  196. {
  197. pszFullFileName = new TCHAR [iFileLen + 2];
  198. lstrcpy (pszFullFileName, pszFilesList);
  199. pszFullFileName[iFileLen + 1] = '\0'; //we need to have 2 terminating nulls
  200. iCharCount = iFileLen + 2;
  201. }
  202. else if('\\' == pszFilesList[0]) //path relative to the root
  203. {
  204. iCharCount = iFileLen + 2 /*drive letter and colon*/ + 2 /*terminating nulls*/;
  205. pszFullFileName = new TCHAR [iCharCount];
  206. pszFullFileName[0] = pszPath[0];
  207. pszFullFileName[1] = pszPath[1];
  208. lstrcpy (pszFullFileName + 2, pszFilesList);
  209. pszFullFileName[iCharCount - 1] = '\0'; //we need to have 2 terminating nulls
  210. }
  211. else //ordinary file name
  212. {
  213. iCharCount = iPathLen + iFileLen + 2; //2 terminating nulls
  214. iCharCount += ('\\' == pszPath[iPathLen - 1])?0:1; //sometimes the path does not have a \ at the end, so we need to add these ourselves
  215. pszFullFileName = new TCHAR [iCharCount];
  216. lstrcpy (pszFullFileName, pszPath);
  217. if('\\' != pszPath[iPathLen - 1]) //we need to add the \ ourselves
  218. {
  219. pszFullFileName[iPathLen] = '\\';
  220. lstrcpy(pszFullFileName + iPathLen + 1, pszFilesList);
  221. }
  222. else
  223. lstrcpy (pszFullFileName + iPathLen, pszFilesList);
  224. pszFullFileName[iCharCount - 1] = '\0'; //2 terminating nulls
  225. }
  226. return pszFullFileName;
  227. }
  228. //+--------------------------------------------------------------------------
  229. //
  230. // Function: GetPrimaryAppWindow
  231. //
  232. // Synopsis: gets the handle to the main window of an existing instance of
  233. // irftp
  234. //
  235. // Arguments: none.
  236. //
  237. // Returns: handle to the window if it finds one. otherwise NULL.
  238. //
  239. // History: 6/30/1999 RahulTh created
  240. //
  241. // Notes:
  242. //
  243. //---------------------------------------------------------------------------
  244. HWND GetPrimaryAppWindow (void)
  245. {
  246. HWND hwnd = NULL;
  247. int i = 1;
  248. //try to find the window for 5 seconds.
  249. do
  250. {
  251. hwnd = FindWindow (L"#32770", //the dialog class
  252. MAIN_WINDOW_TITLE);
  253. if (hwnd)
  254. break;
  255. Sleep (500);
  256. } while ( i++ <= 10 );
  257. return hwnd;
  258. }
  259. /////////////////////////////////////////////////////////////////////////
  260. // Initialize the RPC server
  261. ////////////////////////////////////////////////////////////////////////
  262. BOOL InitRPCServer (void)
  263. {
  264. DWORD Status;
  265. Status = RpcServerRegisterIf( _IrNotifications_v1_0_s_ifspec, 0, 0);
  266. if (Status)
  267. {
  268. return FALSE;
  269. }
  270. Status = RpcServerUseAllProtseqsIf( RPC_C_PROTSEQ_MAX_REQS_DEFAULT, _IrNotifications_v1_0_s_ifspec, 0);
  271. if (Status)
  272. {
  273. return FALSE;
  274. }
  275. Status = RpcServerListen( 1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
  276. if (Status)
  277. {
  278. return FALSE;
  279. }
  280. return TRUE;
  281. }
  282. //////////////////////////////////////////////////////////////////////////////////
  283. //Connect to the RPC server running on the first instance of the app
  284. //this function is called only if this is not the first instance of the app
  285. //////////////////////////////////////////////////////////////////////////////////
  286. RPC_BINDING_HANDLE GetRpcHandle (void)
  287. {
  288. DWORD Status;
  289. RPC_BINDING_HANDLE Binding;
  290. Status = RpcBindingFromStringBinding(L"ncalrpc:", &Binding);
  291. if (Status)
  292. return NULL;
  293. else
  294. return Binding;
  295. }
  296. ///////////////////////////////////////////////////////////////////////////////////////
  297. // RPC Server functions
  298. //////////////////////////////////////////////////////////////////////////////////////
  299. void _PopupUI (handle_t Binding)
  300. {
  301. int nResponse;
  302. appController->PostMessage(WM_APP_TRIGGER_UI);
  303. return;
  304. }
  305. void _InitiateFileTransfer (handle_t Binding, ULONG lSize, wchar_t __RPC_FAR lpszFilesList[])
  306. {
  307. COPYDATASTRUCT cStruct;
  308. cStruct.dwData = lSize;
  309. cStruct.cbData = lSize * sizeof(wchar_t);
  310. cStruct.lpData = (LPVOID)(lpszFilesList);
  311. appController->SendMessage(WM_COPYDATA, (WPARAM)NULL, (LPARAM)(&cStruct));
  312. }
  313. void _DisplaySettings (handle_t Binding)
  314. {
  315. appController->PostMessage(WM_APP_TRIGGER_SETTINGS);
  316. }
  317. void _UpdateSendProgress (
  318. handle_t RpcBinding,
  319. COOKIE Cookie,
  320. wchar_t CurrentFile[],
  321. __int64 BytesInTransfer,
  322. __int64 BytesTransferred,
  323. error_status_t* pStatus
  324. )
  325. {
  326. VALIDATE_SEND_COOKIE (Cookie)
  327. CSendProgress* progressDlg = (CSendProgress*)Cookie;
  328. int percentComplete;
  329. if (BytesInTransfer)
  330. {
  331. percentComplete = (int)((BytesTransferred*100.0)/BytesInTransfer);
  332. }
  333. else
  334. {
  335. percentComplete = 100;
  336. }
  337. progressDlg->PostMessage(WM_APP_UPDATE_PROGRESS, (WPARAM) 0, (LPARAM) percentComplete);
  338. if (100 > percentComplete)
  339. {
  340. progressDlg->SetCurrentFileName (CurrentFile);
  341. }
  342. *pStatus = 0;
  343. }
  344. void _OneSendFileFailed(
  345. handle_t RpcBinding,
  346. COOKIE Cookie,
  347. wchar_t FileName[],
  348. error_status_t ErrorCode,
  349. FAILURE_LOCATION Location,
  350. error_status_t * pStatus
  351. )
  352. {
  353. VALIDATE_SEND_COOKIE (Cookie)
  354. struct SEND_FAILURE_DATA Data;
  355. COPYDATASTRUCT cStruct;
  356. CWnd* progressDlg = (CWnd*)Cookie;
  357. lstrcpy(Data.FileName, FileName);
  358. Data.Location = Location;
  359. Data.Error = ErrorCode;
  360. cStruct.cbData = sizeof(SEND_FAILURE_DATA);
  361. cStruct.lpData = &Data;
  362. progressDlg->SendMessage(WM_COPYDATA, (WPARAM) 0, (LPARAM)(&cStruct));
  363. *pStatus = 0;
  364. }
  365. void _SendComplete(
  366. handle_t RpcBinding,
  367. COOKIE Cookie,
  368. __int64 BytesTransferred,
  369. error_status_t* pStatus
  370. )
  371. {
  372. VALIDATE_SEND_COOKIE (Cookie)
  373. CWnd* progressDlg = (CWnd*)Cookie;
  374. progressDlg->PostMessage(WM_APP_SEND_COMPLETE);
  375. *pStatus = 0;
  376. }
  377. error_status_t
  378. _ReceiveInProgress(
  379. handle_t RpcBinding,
  380. wchar_t MachineName[],
  381. COOKIE * pCookie,
  382. boolean bSuppressRecvConf
  383. )
  384. {
  385. struct MSG_RECEIVE_IN_PROGRESS msg;
  386. msg.MachineName = MachineName;
  387. msg.pCookie = pCookie;
  388. msg.bSuppressRecvConf = bSuppressRecvConf;
  389. msg.status = ~0UL;
  390. appController->SendMessage( WM_APP_RECV_IN_PROGRESS, (WPARAM) &msg );
  391. return msg.status;
  392. }
  393. error_status_t
  394. _GetPermission(
  395. handle_t RpcBinding,
  396. COOKIE Cookie,
  397. wchar_t Name[],
  398. boolean fDirectory
  399. )
  400. {
  401. struct MSG_GET_PERMISSION msg;
  402. msg.Cookie = Cookie;
  403. msg.Name = Name;
  404. msg.fDirectory = fDirectory;
  405. msg.status = ~0UL;
  406. appController->SendMessage( WM_APP_GET_PERMISSION, (WPARAM) &msg );
  407. return msg.status;
  408. }
  409. error_status_t
  410. _ReceiveFinished(
  411. handle_t RpcBinding,
  412. COOKIE Cookie,
  413. error_status_t Status
  414. )
  415. {
  416. struct MSG_RECEIVE_FINISHED msg;
  417. msg.Cookie = Cookie;
  418. msg.ReceiveStatus = Status;
  419. msg.status = ~0UL;
  420. appController->SendMessage( WM_APP_RECV_FINISHED, (WPARAM) &msg );
  421. return msg.status;
  422. }
  423. void _DeviceInRange(
  424. handle_t RpcBinding,
  425. POBEX_DEVICE_LIST device,
  426. error_status_t* pStatus
  427. )
  428. {
  429. appController->PostMessage (WM_APP_KILL_TIMER);
  430. BOOL fLinkOnDesktop = (0 != InterlockedIncrement(&g_lLinkOnDesktop));
  431. if(!fLinkOnDesktop)
  432. CreateLinks();
  433. else
  434. InterlockedDecrement(&g_lLinkOnDesktop); //don't allow the value to exceed 0
  435. g_deviceList = device;
  436. *pStatus = 0;
  437. }
  438. void _NoDeviceInRange(
  439. handle_t RpcBinding,
  440. error_status_t* pStatus
  441. )
  442. {
  443. RemoveLinks();
  444. InterlockedDecrement(&g_lLinkOnDesktop);
  445. g_deviceList = NULL;
  446. if (0 == g_lUIComponentCount)
  447. appController->PostMessage (WM_APP_START_TIMER);
  448. *pStatus = 0;
  449. }
  450. void _Message(
  451. handle_t RpcBinding,
  452. wchar_t String[]
  453. )
  454. {
  455. AFX_MANAGE_STATE (AfxGetStaticModuleState());
  456. CString szTitle;
  457. szTitle.LoadString (IDS_CAPTION);
  458. InterlockedIncrement (&g_lUIComponentCount);
  459. ::MessageBox (NULL, String, (LPCTSTR) szTitle, MB_OK);
  460. BOOL fNoUIComponents = (0 == InterlockedDecrement (&g_lUIComponentCount));
  461. if (appController && fNoUIComponents && ! g_deviceList.GetDeviceCount())
  462. {
  463. //there are no UI components displayed and there are no devices in
  464. //range. Start the timer. If the timer expires, the app. will quit.
  465. appController->PostMessage (WM_APP_START_TIMER);
  466. }
  467. }
  468. error_status_t
  469. _ShutdownUi(handle_t RpcBinding)
  470. {
  471. appController->PostMessage( WM_CLOSE );
  472. return 0;
  473. }
  474. error_status_t
  475. _ShutdownRequested(
  476. handle_t RpcBinding,
  477. boolean * pAnswer
  478. )
  479. {
  480. WCHAR pwszCaption [50];
  481. WCHAR pwszMessage [MAX_PATH];
  482. *pAnswer = TRUE;
  483. if (appController)
  484. {
  485. appController->PostMessage (WM_APP_KILL_TIMER);
  486. }
  487. if (! ::LoadString ( g_hInstance, IDS_CAPTION, pwszCaption, 50))
  488. {
  489. return ERROR_NOT_ENOUGH_MEMORY;
  490. }
  491. if (! ::LoadString ( g_hInstance, IDS_SHUTDOWN_MESSAGE, pwszMessage, MAX_PATH))
  492. {
  493. return ERROR_NOT_ENOUGH_MEMORY;
  494. }
  495. //display a message box with YES / NO buttons
  496. if (IDYES == ::MessageBox (appController->m_hWnd, pwszMessage, pwszCaption,
  497. MB_ICONEXCLAMATION | MB_YESNO | MB_SYSTEMMODAL | MB_SETFOREGROUND))
  498. {
  499. *pAnswer = TRUE;
  500. }
  501. else
  502. {
  503. *pAnswer = FALSE;
  504. }
  505. return 0;
  506. }
  507. //////////////////////////////////////////////////////////////////////////////
  508. //Create links on the desktop and in the Send To menu to this executable file
  509. void CreateLinks(void)
  510. {
  511. AFX_MANAGE_STATE (AfxGetStaticModuleState());
  512. TCHAR lpszFullExeName [MAX_PATH];
  513. TCHAR lpszShortcutName[MAX_PATH];
  514. CString szDesc;
  515. szDesc.LoadString (IDS_SHTCUT_DESC);
  516. //create the desktop link
  517. if (GetShortcutInfo(lpszShortcutName, lpszFullExeName))
  518. CreateShortcut (lpszFullExeName, lpszShortcutName, (LPCTSTR) szDesc);
  519. //create the send to link
  520. if (GetSendToInfo(lpszShortcutName, lpszFullExeName))
  521. CreateShortcut (lpszFullExeName, lpszShortcutName, (LPCTSTR) szDesc);
  522. }
  523. //////////////////////////////////////////////////////////////////////////////
  524. // CreateShortcut - uses the shell's IShellLink and IPersistFile interfaces
  525. // to create and store a shortcut to the specified object.
  526. HRESULT CreateShortcut (LPCTSTR lpszExe, LPCTSTR lpszLink, LPCTSTR lpszDesc)
  527. {
  528. HRESULT hres;
  529. IShellLink* psl;
  530. hres = CoInitialize(NULL);
  531. if (FAILED(hres))
  532. return hres;
  533. // Get a pointer to the IShellLink interface.
  534. hres = CoCreateInstance(CLSID_ShellLink, NULL,
  535. CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
  536. if (SUCCEEDED(hres)) {
  537. IPersistFile* ppf;
  538. // Set the path to the shortcut target and add the
  539. // description.
  540. psl->SetPath(lpszExe);
  541. psl->SetDescription(lpszDesc);
  542. // Query IShellLink for the IPersistFile interface for saving the
  543. // shortcut in persistent storage.
  544. hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
  545. if (SUCCEEDED(hres)) {
  546. // Save the link by calling IPersistFile::Save.
  547. hres = ppf->Save(lpszLink, TRUE);
  548. ppf->Release();
  549. }
  550. psl->Release();
  551. }
  552. return SUCCEEDED(hres)?S_OK:E_FAIL;
  553. }
  554. void RemoveLinks (void)
  555. {
  556. TCHAR lpszShortcutName[2 * MAX_PATH];
  557. TCHAR lpszFullExeName[2 * MAX_PATH];
  558. //delete the desktop shortcut
  559. if(GetShortcutInfo (lpszShortcutName, lpszFullExeName))
  560. DeleteFile (lpszShortcutName);
  561. //delete the send to shortcut
  562. if (GetSendToInfo (lpszShortcutName, lpszFullExeName))
  563. DeleteFile (lpszShortcutName);
  564. }
  565. BOOL GetShortcutInfo (LPTSTR lpszShortcutName, LPTSTR lpszFullExeName)
  566. {
  567. AFX_MANAGE_STATE (AfxGetStaticModuleState());
  568. *lpszShortcutName = '\0'; //precautionary measures
  569. *lpszFullExeName = '\0';
  570. CString szExe;
  571. CString szShtCut;
  572. int len;
  573. szExe.LoadString (IDS_EXE);
  574. szShtCut.LoadString (IDS_DESKTOP_SHTCUT);
  575. len = GetSystemDirectory (lpszFullExeName, MAX_PATH);
  576. if(0 == len)
  577. return FALSE;
  578. lstrcat(lpszFullExeName, LPCTSTR (szExe));
  579. if('\0' == g_lpszDesktopFolder[0]) //try once again if we had failed before, or maybe this is the first time
  580. {
  581. if (FAILED(SHGetSpecialFolderPath(NULL, g_lpszDesktopFolder,
  582. CSIDL_DESKTOPDIRECTORY, 0)))
  583. {
  584. g_lpszDesktopFolder[0] = '\0'; //we failed so give up.
  585. return FALSE;
  586. }
  587. }
  588. lstrcpy (lpszShortcutName, g_lpszDesktopFolder);
  589. lstrcat (lpszShortcutName, (LPCTSTR) szShtCut);
  590. return TRUE;
  591. }
  592. BOOL GetSendToInfo (LPTSTR lpszSendToName, LPTSTR lpszFullExeName)
  593. {
  594. AFX_MANAGE_STATE (AfxGetStaticModuleState());
  595. *lpszSendToName = '\0'; //precautionary measures
  596. *lpszFullExeName = '\0';
  597. CString szExe;
  598. CString szSendTo;
  599. int len;
  600. szExe.LoadString (IDS_EXE);
  601. szSendTo.LoadString (IDS_SENDTO_SHTCUT);
  602. len = GetSystemDirectory (lpszFullExeName, MAX_PATH);
  603. if (0 == len)
  604. return FALSE;
  605. lstrcat (lpszFullExeName, (LPCTSTR) szExe);
  606. if ('\0' == g_lpszSendToFolder[0]) //try once again if we had failed before, or maybe this is the first time
  607. {
  608. if (FAILED(SHGetSpecialFolderPath(NULL, g_lpszSendToFolder,
  609. CSIDL_SENDTO, 0)))
  610. {
  611. g_lpszSendToFolder[0] = '\0';
  612. return FALSE;
  613. }
  614. }
  615. lstrcpy (lpszSendToName, g_lpszSendToFolder);
  616. lstrcat (lpszSendToName, (LPCTSTR) szSendTo);
  617. return TRUE;
  618. }
  619. //+--------------------------------------------------------------------------
  620. //
  621. // Member: CError::ConstructMessage
  622. //
  623. // Synopsis: this is an internal helper function that constructs a message
  624. // from the available error codes it is called by both ShowMessage
  625. //
  626. // Arguments: [in] argList : the va_list of arguments
  627. // [out] szErrMsg : the formatted error message
  628. //
  629. // Returns: nothing
  630. //
  631. // History: 10/2/1998 RahulTh created
  632. //
  633. // Notes:
  634. //
  635. //---------------------------------------------------------------------------
  636. void CError::ConstructMessage (va_list argList, CString& szErrMsg)
  637. {
  638. AFX_MANAGE_STATE (AfxGetStaticModuleState());
  639. TCHAR lpszMessage[2048];
  640. szErrMsg.LoadString (m_msgID);
  641. wvsprintf (lpszMessage, (LPCTSTR) szErrMsg, argList);
  642. szErrMsg = lpszMessage;
  643. if (ERROR_SUCCESS != m_winErr)
  644. {
  645. LPVOID lpMsgBuf;
  646. DWORD dwRet;
  647. dwRet = ::FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
  648. FORMAT_MESSAGE_FROM_SYSTEM |
  649. FORMAT_MESSAGE_IGNORE_INSERTS,
  650. NULL,
  651. m_winErr,
  652. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  653. (LPTSTR) &lpMsgBuf,
  654. 0,
  655. NULL
  656. );
  657. if (dwRet)
  658. {
  659. szErrMsg += TEXT("\n\n");
  660. szErrMsg += (LPCTSTR) lpMsgBuf;
  661. LocalFree (lpMsgBuf);
  662. }
  663. }
  664. }
  665. //+--------------------------------------------------------------------------
  666. //
  667. // Member: CError::ShowMessage
  668. //
  669. // Synopsis: displays an error message in a message box based on the
  670. // members of the object
  671. //
  672. // Arguments: message id for the error + more
  673. //
  674. // Returns: the return value of the message box
  675. //
  676. // History: 10/1/1998 RahulTh created
  677. //
  678. // Notes: if the resultant message is longer than 2048 characters
  679. // then result is unpredictable and may also cause AVs.
  680. // but this is a limitation of wvsprintf. However, this is not
  681. // so bad since we can make sure that we do not have any error
  682. // message that exceed this self imposed limit
  683. //
  684. //---------------------------------------------------------------------------
  685. int CError::ShowMessage (UINT errID, ...)
  686. {
  687. AFX_MANAGE_STATE (AfxGetStaticModuleState());
  688. va_list argList;
  689. CString szErrMsg;
  690. CString szTitle;
  691. m_msgID = errID; //update the message ID with the new one
  692. szTitle.LoadString (m_titleID);
  693. va_start (argList, errID);
  694. ConstructMessage (argList, szErrMsg);
  695. va_end (argList);
  696. return ::MessageBox (m_hWndParent, (LPCTSTR)szErrMsg,
  697. (LPCTSTR) szTitle, m_nStyle);
  698. }