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.

1372 lines
38 KiB

  1. #include "private.h"
  2. #include "chanmgr.h"
  3. #include "chanmgrp.h"
  4. #include "shguidp.h"
  5. #include "resource.h"
  6. #define DECL_CRTFREE
  7. #include <crtfree.h>
  8. #include <mluisupp.h>
  9. #define TF_DUMPTRIGGER 0x80000000
  10. #define PtrDifference(x,y) ((LPBYTE)(x)-(LPBYTE)(y))
  11. // Invoke Command verb strings
  12. const CHAR c_szOpen[] = "open";
  13. const CHAR c_szDelete[] = "delete";
  14. const CHAR c_szProperties[] = "properties";
  15. const CHAR c_szCopy[] = "copy";
  16. const CHAR c_szRename[] = "rename";
  17. const CHAR c_szPaste[] = "paste";
  18. static TCHAR szNone[40] = {0};
  19. static TCHAR szUnknown[40] = {0};
  20. // For each notification handler CLSID in the registry, send a single CommandId and Cookie to each handler.
  21. void FireSubscriptionEvent(int nCmdID, const SUBSCRIPTIONCOOKIE UNALIGNED *pCookie_ua)
  22. {
  23. HKEY hkey;
  24. SUBSCRIPTIONCOOKIE cookie_buf;
  25. SUBSCRIPTIONCOOKIE *pCookie;
  26. ASSERT( pCookie_ua );
  27. if ( ! pCookie_ua )
  28. {
  29. TraceMsg(TF_ERROR, "FireSubscriptionEvent() - pCookie_ua is NULL!");
  30. return;
  31. }
  32. //
  33. // Make an aligned copy of pCookie_ua and set a pointer to it.
  34. //
  35. cookie_buf = *pCookie_ua;
  36. pCookie = &cookie_buf;
  37. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WEBCHECK_REGKEY_NOTF, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
  38. {
  39. LPOLESTR pszCookie;
  40. if (SUCCEEDED(StringFromCLSID(*pCookie, &pszCookie)))
  41. {
  42. VARIANT varCookie;
  43. varCookie.vt = VT_BSTR;
  44. varCookie.bstrVal = SysAllocString(pszCookie);
  45. if (varCookie.bstrVal)
  46. {
  47. for (int i = 0; ; i++)
  48. {
  49. TCHAR szClsid[GUIDSTR_MAX];
  50. DWORD cchClsid = ARRAYSIZE(szClsid);
  51. DWORD dwType;
  52. DWORD dwData;
  53. DWORD cbData = sizeof(dwData);
  54. int result = RegEnumValue(hkey, i, szClsid, &cchClsid, NULL, &dwType, (LPBYTE)&dwData, &cbData);
  55. if (ERROR_NO_MORE_ITEMS == result)
  56. {
  57. break;
  58. }
  59. if ((ERROR_SUCCESS == result) && (dwData & nCmdID))
  60. {
  61. WCHAR wszClsid[GUIDSTR_MAX];
  62. CLSID clsid;
  63. SHTCharToUnicode(szClsid, wszClsid, ARRAYSIZE(wszClsid));
  64. HRESULT hr = CLSIDFromString(wszClsid, &clsid);
  65. if (SUCCEEDED(hr))
  66. {
  67. IOleCommandTarget *pCmdTarget;
  68. hr = CoCreateInstance(*(&clsid), NULL, CLSCTX_ALL, IID_IOleCommandTarget, (void **)&pCmdTarget);
  69. if (SUCCEEDED(hr))
  70. {
  71. pCmdTarget->Exec(&CLSID_SubscriptionMgr, nCmdID, 0, &varCookie, NULL);
  72. pCmdTarget->Release();
  73. }
  74. }
  75. }
  76. }
  77. VariantClear(&varCookie);
  78. }
  79. CoTaskMemFree(pszCookie);
  80. }
  81. RegCloseKey( hkey );
  82. }
  83. }
  84. #ifdef UNICODE
  85. HRESULT IExtractIcon_GetIconLocationThunk(IExtractIconW *peiw, UINT uFlags, LPSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags)
  86. {
  87. HRESULT hr;
  88. WCHAR *pwszIconFile = new WCHAR[cchMax];
  89. if (NULL != pwszIconFile)
  90. {
  91. hr = peiw->GetIconLocation(uFlags, pwszIconFile, cchMax, piIndex, pwFlags);
  92. if (SUCCEEDED(hr))
  93. {
  94. WideCharToMultiByte(CP_ACP, 0, pwszIconFile, -1, szIconFile, cchMax, NULL, NULL);
  95. }
  96. delete [] pwszIconFile;
  97. }
  98. else
  99. {
  100. hr = E_OUTOFMEMORY;
  101. }
  102. return hr;
  103. }
  104. HRESULT IExtractIcon_ExtractThunk(IExtractIconW *peiw, LPCSTR pszFile, UINT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize)
  105. {
  106. HRESULT hr;
  107. int len = lstrlenA(pszFile) + 1;
  108. WCHAR *pwszFile = new WCHAR[len];
  109. if (NULL != pwszFile)
  110. {
  111. MultiByteToWideChar(CP_ACP, 0, pszFile, len, pwszFile, len);
  112. hr = peiw->Extract(pwszFile, nIconIndex, phiconLarge, phiconSmall, nIconSize);
  113. delete [] pwszFile;
  114. }
  115. else
  116. {
  117. hr = E_OUTOFMEMORY;
  118. }
  119. return hr;
  120. }
  121. #endif
  122. DWORD Random(DWORD nMax)
  123. {
  124. static DWORD dwSeed = GetTickCount();
  125. if (nMax)
  126. {
  127. return dwSeed = (dwSeed * 214013L + 2531011L) % nMax;
  128. }
  129. else
  130. {
  131. return 0;
  132. }
  133. }
  134. void CreateCookie(GUID UNALIGNED *pCookie_ua)
  135. {
  136. static DWORD dwCount = 0;
  137. union CUCookie
  138. {
  139. GUID guidCookie;
  140. struct XCookie {
  141. FILETIME ft;
  142. DWORD dwCount;
  143. DWORD dwRand;
  144. } x;
  145. };
  146. CUCookie uc;
  147. GetSystemTimeAsFileTime(&uc.x.ft);
  148. uc.x.dwCount = dwCount++;
  149. uc.x.dwRand = Random(0xffffffff);
  150. *pCookie_ua = uc.guidCookie;
  151. }
  152. void VariantTimeToFileTime(double dt, FILETIME& ft)
  153. {
  154. SYSTEMTIME st;
  155. VariantTimeToSystemTime(dt, &st);
  156. SystemTimeToFileTime(&st, &ft);
  157. }
  158. void FileTimeToVariantTime(FILETIME& ft, double *pdt)
  159. {
  160. SYSTEMTIME st;
  161. FileTimeToSystemTime(&ft, &st);
  162. SystemTimeToVariantTime(&st, pdt);
  163. }
  164. //////////////////////////////////////////////////////////////////////////
  165. //////////////////////////////////////////////////////////////////////////
  166. //
  167. // Cache helper functions
  168. //
  169. // Caller should MemFree *lpCacheConfigInfo when done. Should pass *lpCacheConfigInfo
  170. // into SetCacheSize
  171. HRESULT GetCacheInfo(
  172. LPINTERNET_CACHE_CONFIG_INFOA *lplpCacheConfigInfo,
  173. DWORD *pdwSizeInKB,
  174. DWORD *pdwPercent)
  175. {
  176. HRESULT hr = S_OK;
  177. LPINTERNET_CACHE_CONFIG_INFOA lpCCI = NULL;
  178. DWORD dwSize;
  179. dwSize = sizeof(INTERNET_CACHE_CONFIG_INFOA);
  180. lpCCI = (LPINTERNET_CACHE_CONFIG_INFOA)MemAlloc(LPTR, dwSize);
  181. if (!lpCCI)
  182. {
  183. hr = E_OUTOFMEMORY;
  184. goto cleanup;
  185. }
  186. lpCCI->dwStructSize = sizeof(INTERNET_CACHE_CONFIG_INFOA);
  187. if (!GetUrlCacheConfigInfoA(lpCCI, &dwSize, CACHE_CONFIG_CONTENT_PATHS_FC))
  188. {
  189. hr = E_FAIL; // HRESULT_FROM_WIN32(GetLastError());
  190. goto cleanup;
  191. }
  192. // there should be at least one cache path structure
  193. if (dwSize < sizeof(INTERNET_CACHE_CONFIG_INFOA) ||
  194. lpCCI->dwNumCachePaths != 1)
  195. {
  196. // something is messed up
  197. hr = E_FAIL;
  198. goto cleanup;
  199. }
  200. *lplpCacheConfigInfo = lpCCI;
  201. *pdwSizeInKB = lpCCI->dwQuota;
  202. *pdwPercent = 10; // good faith estimate
  203. ASSERT(*pdwSizeInKB); // Better not be 0...
  204. cleanup:
  205. if (FAILED(hr))
  206. {
  207. SAFELOCALFREE(lpCCI);
  208. }
  209. return hr;
  210. }
  211. HRESULT SetCacheSize(
  212. LPINTERNET_CACHE_CONFIG_INFOA lpCacheConfigInfo,
  213. DWORD dwSizeInKB)
  214. {
  215. // lpCacheConfigInfo->dwNumCachePaths = 1;
  216. // lpCacheConfigInfo->CachePaths[0].dwCacheSize = dwSizeInKB;
  217. lpCacheConfigInfo->dwContainer = 0; // CONTENT;
  218. lpCacheConfigInfo->dwQuota = dwSizeInKB;
  219. if (!SetUrlCacheConfigInfoA(lpCacheConfigInfo, CACHE_CONFIG_QUOTA_FC))
  220. {
  221. return E_FAIL; // HRESULT_FROM_WIN32(GetLastError());
  222. }
  223. return S_OK;
  224. }
  225. //////////////////////////////////////////////////////////////////////////
  226. //////////////////////////////////////////////////////////////////////////
  227. //
  228. // Registry helper functions
  229. //
  230. BOOL ReadRegValue(HKEY hkeyRoot, const TCHAR *pszKey, const TCHAR *pszValue,
  231. void *pData, DWORD dwBytes)
  232. {
  233. long lResult;
  234. HKEY hkey;
  235. DWORD dwType;
  236. lResult = RegOpenKey(hkeyRoot, pszKey, &hkey);
  237. if (lResult != ERROR_SUCCESS) {
  238. return FALSE;
  239. }
  240. lResult = RegQueryValueEx(hkey, pszValue, NULL, &dwType, (BYTE *)pData,
  241. &dwBytes);
  242. RegCloseKey(hkey);
  243. if (lResult != ERROR_SUCCESS)
  244. return FALSE;
  245. if(dwType == REG_SZ) {
  246. // null terminate string
  247. ((TCHAR *)pData)[dwBytes] = 0;
  248. }
  249. return TRUE;
  250. }
  251. BOOL WriteRegValue(HKEY hkeyRoot, const TCHAR *pszKey, const TCHAR *pszValue,
  252. void *pData, DWORD dwBytes, DWORD dwType)
  253. {
  254. HKEY hkey;
  255. long lResult;
  256. DWORD dwStatus;
  257. lResult = RegCreateKeyEx(hkeyRoot, pszKey, 0, NULL,
  258. REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, &dwStatus);
  259. if (lResult != ERROR_SUCCESS) {
  260. return FALSE;
  261. }
  262. lResult = RegSetValueEx(hkey, pszValue, 0, dwType, (BYTE *)pData, dwBytes);
  263. RegCloseKey(hkey);
  264. return (lResult == ERROR_SUCCESS) ? TRUE : FALSE;
  265. }
  266. DWORD ReadRegDWORD(HKEY hkeyRoot, const TCHAR *pszKey, const TCHAR *pszValue)
  267. {
  268. DWORD dwData;
  269. if (ReadRegValue(hkeyRoot, pszKey, pszValue, &dwData, sizeof(dwData)))
  270. return dwData;
  271. else
  272. return 0;
  273. }
  274. HRESULT CreateShellFolderPath(LPCTSTR pszPath, LPCTSTR pszGUID, BOOL bUICLSID)
  275. {
  276. if (!PathFileExists(pszPath))
  277. CreateDirectory(pszPath, NULL);
  278. // Mark the folder as a system directory
  279. if (SetFileAttributes(pszPath, FILE_ATTRIBUTE_READONLY))
  280. {
  281. TCHAR szDesktopIni[MAX_PATH];
  282. // Write in the desktop.ini the cache folder class ID
  283. PathCombine(szDesktopIni, pszPath, TEXT("desktop.ini"));
  284. // If the desktop.ini already exists, make sure it is writable
  285. if (PathFileExists(szDesktopIni))
  286. SetFileAttributes(szDesktopIni, FILE_ATTRIBUTE_NORMAL);
  287. // (First, flush the cache to make sure the desktop.ini
  288. // file is really created.)
  289. WritePrivateProfileString(NULL, NULL, NULL, szDesktopIni);
  290. WritePrivateProfileString(TEXT(".ShellClassInfo"), bUICLSID ? TEXT("UICLSID") : TEXT("CLSID"), pszGUID, szDesktopIni);
  291. WritePrivateProfileString(NULL, NULL, NULL, szDesktopIni);
  292. // Hide the desktop.ini since the shell does not selectively
  293. // hide it.
  294. SetFileAttributes(szDesktopIni, FILE_ATTRIBUTE_HIDDEN);
  295. return NOERROR;
  296. }
  297. else
  298. {
  299. DebugMsg(DM_TRACE, TEXT("Cannot make %s a system folder"), pszPath);
  300. return E_FAIL;
  301. }
  302. }
  303. void CleanupShellFolder(LPCTSTR pszPath)
  304. {
  305. if (PathFileExists(pszPath))
  306. {
  307. TCHAR szDesktopIni[MAX_PATH];
  308. // make the history a normal folder
  309. SetFileAttributes(pszPath, FILE_ATTRIBUTE_NORMAL);
  310. PathCombine(szDesktopIni, pszPath, TEXT("desktop.ini"));
  311. // If the desktop.ini already exists, make sure it is writable
  312. if (PathFileExists(szDesktopIni))
  313. {
  314. SetFileAttributes(szDesktopIni, FILE_ATTRIBUTE_NORMAL);
  315. DeleteFile(szDesktopIni);
  316. }
  317. // remove the history directory
  318. RemoveDirectory(pszPath);
  319. }
  320. }
  321. BOOL GetSubscriptionFolderPath(LPTSTR pszPath)
  322. {
  323. DWORD dwDummy;
  324. HKEY hk;
  325. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  326. REGSTR_PATH_SUBSCRIPTION,
  327. 0, TEXT(""),
  328. REG_OPTION_NON_VOLATILE,
  329. KEY_READ|KEY_WRITE, NULL, &hk, &dwDummy))
  330. {
  331. DWORD cbData = MAX_PATH * sizeof(TCHAR);
  332. if (ERROR_SUCCESS != RegQueryValueEx(hk, REGSTR_VAL_DIRECTORY , NULL, NULL, (LPBYTE)pszPath, &cbData))
  333. {
  334. TCHAR szWindows[MAX_PATH];
  335. GetWindowsDirectory(szWindows, ARRAYSIZE(szWindows));
  336. PathCombine(pszPath, szWindows, TEXT("Offline Web Pages"));
  337. }
  338. RegCloseKey(hk);
  339. return TRUE;
  340. }
  341. return FALSE;
  342. }
  343. HRESULT GetChannelPath(LPCTSTR pszURL, LPTSTR pszPath, int cch,
  344. IChannelMgrPriv** ppIChannelMgrPriv)
  345. {
  346. ASSERT(pszURL);
  347. ASSERT(pszPath || 0 == cch);
  348. ASSERT(ppIChannelMgrPriv);
  349. HRESULT hr;
  350. BOOL bCoinit = FALSE;
  351. hr = CoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER,
  352. IID_IChannelMgrPriv, (void**)ppIChannelMgrPriv);
  353. if ((hr == CO_E_NOTINITIALIZED || hr == REGDB_E_IIDNOTREG) &&
  354. SUCCEEDED(CoInitialize(NULL)))
  355. {
  356. bCoinit = TRUE;
  357. hr = CoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER,
  358. IID_IChannelMgrPriv, (void**)ppIChannelMgrPriv);
  359. }
  360. if (SUCCEEDED(hr))
  361. {
  362. ASSERT(*ppIChannelMgrPriv);
  363. IChannelMgr* pIChannelMgr;
  364. hr = (*ppIChannelMgrPriv)->QueryInterface(IID_IChannelMgr,
  365. (void**)&pIChannelMgr);
  366. if (SUCCEEDED(hr))
  367. {
  368. ASSERT(pIChannelMgr);
  369. WCHAR wszURL[INTERNET_MAX_URL_LENGTH];
  370. MyStrToOleStrN(wszURL, ARRAYSIZE(wszURL), pszURL);
  371. IEnumChannels* pIEnumChannels;
  372. hr = pIChannelMgr->EnumChannels(CHANENUM_ALLFOLDERS | CHANENUM_PATH,
  373. wszURL, &pIEnumChannels);
  374. if (SUCCEEDED(hr))
  375. {
  376. ASSERT(pIEnumChannels);
  377. CHANNELENUMINFO ci;
  378. if (S_OK == pIEnumChannels->Next(1, &ci, NULL))
  379. {
  380. MyOleStrToStrN(pszPath, cch, ci.pszPath);
  381. CoTaskMemFree(ci.pszPath);
  382. }
  383. else
  384. {
  385. hr = E_FAIL;
  386. }
  387. pIEnumChannels->Release();
  388. }
  389. pIChannelMgr->Release();
  390. }
  391. }
  392. if (bCoinit)
  393. CoUninitialize();
  394. ASSERT((SUCCEEDED(hr) && *ppIChannelMgrPriv) || FAILED(hr));
  395. return hr;
  396. }
  397. // Caller is responsible for calling ILFree on *ppidl.
  398. HRESULT ConvertPathToPidl(LPCTSTR path, LPITEMIDLIST * ppidl)
  399. {
  400. WCHAR wszPath[MAX_PATH];
  401. IShellFolder * pDesktopFolder;
  402. HRESULT hr;
  403. ASSERT(path && ppidl);
  404. * ppidl = NULL;
  405. MyStrToOleStrN(wszPath, MAX_PATH, path);
  406. hr = SHGetDesktopFolder(&pDesktopFolder);
  407. if (hr != NOERROR)
  408. return hr;
  409. ULONG uChEaten;
  410. hr = pDesktopFolder->ParseDisplayName(NULL, NULL, wszPath,
  411. &uChEaten, ppidl, NULL);
  412. SAFERELEASE(pDesktopFolder);
  413. return hr;
  414. }
  415. LPITEMIDLIST GetSubscriptionFolderPidl(void)
  416. {
  417. TCHAR szPath[MAX_PATH];
  418. static LPITEMIDLIST pidlFolder = NULL; // We leak here.
  419. if (!pidlFolder) {
  420. if (!(GetSubscriptionFolderPath(szPath)))
  421. return NULL;
  422. if (FAILED(ConvertPathToPidl(szPath, &pidlFolder)))
  423. return NULL;
  424. ASSERT(pidlFolder);
  425. }
  426. return (LPITEMIDLIST)pidlFolder;
  427. }
  428. STDAPI OfflineFolderRegisterServer(void)
  429. {
  430. TCHAR szOldSubscriptionPath[MAX_PATH];
  431. GetWindowsDirectory(szOldSubscriptionPath, ARRAYSIZE(szOldSubscriptionPath));
  432. PathCombine(szOldSubscriptionPath, szOldSubscriptionPath, TEXT("Subscriptions"));
  433. CleanupShellFolder(szOldSubscriptionPath);
  434. TCHAR szPath[MAX_PATH];
  435. if (!(GetSubscriptionFolderPath(szPath)))
  436. goto CleanUp;
  437. // we pass FALSE because history folder uses CLSID
  438. if (FAILED(CreateShellFolderPath(szPath, TEXT("{F5175861-2688-11d0-9C5E-00AA00A45957}"), FALSE)))
  439. goto CleanUp;
  440. return NOERROR;
  441. CleanUp: // cleanup stuff if any of our reg stuff fails
  442. return E_FAIL;
  443. }
  444. STDAPI OfflineFolderUnregisterServer(void)
  445. {
  446. TCHAR szPath[MAX_PATH];
  447. if (!(GetSubscriptionFolderPath(szPath)))
  448. goto CleanUp;
  449. // we pass FALSE because history folder uses CLSID
  450. CleanupShellFolder(szPath);
  451. return NOERROR;
  452. CleanUp: // cleanup stuff if any of our reg stuff fails
  453. return E_FAIL;
  454. }
  455. HMENU LoadPopupMenu(UINT id, UINT uSubOffset)
  456. {
  457. HMENU hmParent, hmPopup;
  458. hmParent = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(id));
  459. if (!hmParent)
  460. return NULL;
  461. hmPopup = GetSubMenu(hmParent, uSubOffset);
  462. RemoveMenu(hmParent, uSubOffset, MF_BYPOSITION);
  463. DestroyMenu(hmParent);
  464. return hmPopup;
  465. }
  466. UINT MergePopupMenu(HMENU *phMenu, UINT idResource, UINT uSubOffset, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast)
  467. {
  468. HMENU hmMerge;
  469. if (*phMenu == NULL)
  470. {
  471. *phMenu = CreatePopupMenu();
  472. if (*phMenu == NULL)
  473. return 0;
  474. indexMenu = 0; // at the bottom
  475. }
  476. hmMerge = LoadPopupMenu(idResource, uSubOffset);
  477. if (!hmMerge)
  478. return 0;
  479. idCmdLast = Shell_MergeMenus(*phMenu, hmMerge, indexMenu, idCmdFirst, idCmdLast, MM_ADDSEPARATOR);
  480. DestroyMenu(hmMerge);
  481. return idCmdLast;
  482. }
  483. HMENU GetMenuFromID(HMENU hmenu, UINT idm)
  484. {
  485. MENUITEMINFO mii = { sizeof(mii), MIIM_SUBMENU, 0, 0, 0, NULL, NULL, NULL, 0, NULL, 0 };
  486. GetMenuItemInfo(hmenu, idm, FALSE, &mii);
  487. return mii.hSubMenu;
  488. }
  489. UINT MergeMenuHierarchy(HMENU hmenuDst, HMENU hmenuSrc, UINT idcMin, UINT idcMax, BOOL bTop)
  490. {
  491. UINT idcMaxUsed = idcMin;
  492. int imi = GetMenuItemCount(hmenuSrc);
  493. while (--imi >= 0)
  494. {
  495. MENUITEMINFO mii = {
  496. sizeof(MENUITEMINFO),
  497. MIIM_ID | MIIM_SUBMENU,
  498. 0,/* fType */ 0,/* fState */ 0,/*wId*/ NULL,
  499. NULL, NULL, 0,
  500. NULL, 0 };
  501. if (GetMenuItemInfo(hmenuSrc, imi, TRUE, &mii))
  502. {
  503. UINT idcT = Shell_MergeMenus(
  504. GetMenuFromID(hmenuDst, mii.wID),
  505. mii.hSubMenu, (bTop)?0:1024, idcMin, idcMax,
  506. MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS);
  507. idcMaxUsed = max(idcMaxUsed, idcT);
  508. }
  509. }
  510. return idcMaxUsed;
  511. }
  512. ///////////////////////////////////////////////////////////////////////////////
  513. //
  514. // Helper Fuctions for item.cpp and folder.cpp
  515. //
  516. ///////////////////////////////////////////////////////////////////////////////
  517. int _CompareURL(LPMYPIDL pooi1, LPMYPIDL pooi2)
  518. {
  519. return UrlCompare(URL(&(pooi1->ooe)), URL(&(pooi2->ooe)), TRUE);
  520. }
  521. int _CompareShortName(LPMYPIDL pooi1, LPMYPIDL pooi2)
  522. {
  523. PCTSTR pszNameLocal1;
  524. PCTSTR pszNameLocal2;
  525. LPTSTR szNameUnaligned1 = NAME(&(pooi1->ooe));
  526. LPTSTR szNameUnaligned2 = NAME(&(pooi2->ooe));
  527. TSTR_ALIGNED_STACK_COPY( &pszNameLocal1, szNameUnaligned1 );
  528. TSTR_ALIGNED_STACK_COPY( &pszNameLocal2, szNameUnaligned2 );
  529. return StrCmp( pszNameLocal1, pszNameLocal2 );
  530. }
  531. int _CompareLastUpdate(LPMYPIDL pooi1, LPMYPIDL pooi2)
  532. {
  533. if (pooi1->ooe.m_LastUpdated - pooi2->ooe.m_LastUpdated > 0)
  534. return 1;
  535. return -1;
  536. }
  537. int _CompareCookie(REFCLSID cookie1, REFCLSID cookie2)
  538. {
  539. return memcmp(&cookie1, &cookie2, sizeof(CLSID));
  540. }
  541. int _CompareStatus(LPMYPIDL pooi1, LPMYPIDL pooi2)
  542. {
  543. return StrCmp(STATUS(&(pooi1->ooe)), STATUS(&(pooi2->ooe)));
  544. }
  545. int _CompareIdentities(LPMYPIDL pooi1, LPMYPIDL pooi2)
  546. {
  547. if (pooi1->ooe.clsidDest != pooi2->ooe.clsidDest)
  548. return -1;
  549. if (!IsNativeAgent(pooi1->ooe.clsidDest))
  550. return _CompareCookie(pooi1->ooe.m_Cookie, pooi2->ooe.m_Cookie);
  551. return _CompareURL(pooi1, pooi2);
  552. }
  553. BOOL _ValidateIDListArray(UINT cidl, LPCITEMIDLIST *ppidl)
  554. {
  555. UINT i;
  556. for (i = 0; i < cidl; i++)
  557. {
  558. if (!IS_VALID_MYPIDL(ppidl[i]))
  559. return FALSE;
  560. }
  561. return TRUE;
  562. }
  563. int _LaunchApp(HWND hwnd, LPCTSTR pszPath)
  564. {
  565. SHELLEXECUTEINFO ei = { 0 };
  566. ei.cbSize = sizeof(SHELLEXECUTEINFO);
  567. ei.hwnd = hwnd;
  568. ei.lpFile = pszPath;
  569. ei.nShow = SW_SHOWNORMAL;
  570. return ShellExecuteEx(&ei);
  571. }
  572. void _GenerateEvent(LONG lEventId, LPITEMIDLIST pidlIn, LPITEMIDLIST pidlNewIn, BOOL bRefresh)
  573. {
  574. LPITEMIDLIST pidlFolder = GetSubscriptionFolderPidl();
  575. if (!pidlFolder)
  576. return;
  577. LPITEMIDLIST pidl = ILCombine(pidlFolder, pidlIn);
  578. if (pidl)
  579. {
  580. if (pidlNewIn)
  581. {
  582. LPITEMIDLIST pidlNew = ILCombine(pidlFolder, pidlNewIn);
  583. if (pidlNew)
  584. {
  585. SHChangeNotify(lEventId, SHCNF_IDLIST, pidl, pidlNew);
  586. ILFree(pidlNew);
  587. }
  588. }
  589. else
  590. {
  591. SHChangeNotify(lEventId, SHCNF_IDLIST, pidl, NULL);
  592. }
  593. if (bRefresh)
  594. SHChangeNotifyHandleEvents();
  595. ILFree(pidl);
  596. }
  597. }
  598. BOOL _InitComCtl32()
  599. {
  600. static BOOL fInitialized = FALSE;
  601. if (!fInitialized)
  602. {
  603. INITCOMMONCONTROLSEX icc;
  604. icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
  605. icc.dwICC = ICC_NATIVEFNTCTL_CLASS | ICC_DATE_CLASSES;
  606. fInitialized = InitCommonControlsEx(&icc);
  607. }
  608. return fInitialized;
  609. }
  610. const struct {
  611. LPCSTR pszVerb;
  612. UINT idCmd;
  613. } rgcmds[] = {
  614. { c_szOpen, RSVIDM_OPEN },
  615. { c_szCopy, RSVIDM_COPY },
  616. { c_szRename, RSVIDM_RENAME},
  617. { c_szPaste, RSVIDM_PASTE},
  618. { c_szDelete, RSVIDM_DELETE },
  619. { c_szProperties, RSVIDM_PROPERTIES }
  620. };
  621. int _GetCmdID(LPCSTR pszCmd)
  622. {
  623. if (HIWORD(pszCmd))
  624. {
  625. int i;
  626. for (i = 0; i < ARRAYSIZE(rgcmds); i++)
  627. {
  628. if (lstrcmpiA(rgcmds[i].pszVerb, pszCmd) == 0)
  629. {
  630. return rgcmds[i].idCmd;
  631. }
  632. }
  633. return -1; // unknown
  634. }
  635. return (int)LOWORD(pszCmd);
  636. }
  637. BOOL CALLBACK _AddOnePropSheetPage(HPROPSHEETPAGE hpage, LPARAM lParam)
  638. {
  639. PROPSHEETHEADER * ppsh = (PROPSHEETHEADER *) lParam;
  640. if (ppsh->nPages < MAX_PROP_PAGES)
  641. {
  642. ppsh->phpage[ppsh->nPages++] = hpage;
  643. return TRUE;
  644. }
  645. return FALSE;
  646. }
  647. HRESULT _CreatePropSheet(HWND hwnd, POOEBuf pBuf)
  648. {
  649. ASSERT(pBuf);
  650. ISubscriptionMgr * pSub= NULL;
  651. HRESULT hr = CoInitialize(NULL);
  652. RETURN_ON_FAILURE(hr);
  653. hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  654. IID_ISubscriptionMgr, (void **)&pSub);
  655. CoUninitialize();
  656. RETURN_ON_FAILURE(hr);
  657. ASSERT(pSub);
  658. BSTR bstrURL = NULL;
  659. hr = CreateBSTRFromTSTR(&bstrURL, pBuf->m_URL);
  660. if (S_OK == hr)
  661. hr = pSub->ShowSubscriptionProperties(bstrURL, hwnd);
  662. SAFERELEASE(pSub);
  663. SAFEFREEBSTR(bstrURL);
  664. return hr;
  665. }
  666. // Note:
  667. // We return FALSE on illegal DATE data.
  668. BOOL DATE2DateTimeString(CFileTime& ft, LPTSTR pszText)
  669. {
  670. SYSTEMTIME st;
  671. if (ft == 0) {
  672. if (szUnknown[0] == 0)
  673. MLLoadString(IDS_UNKNOWN, szUnknown, ARRAYSIZE(szUnknown));
  674. StrCpy(pszText, szUnknown);
  675. return FALSE;
  676. }
  677. if (!FileTimeToSystemTime(&ft, &st))
  678. {
  679. if (szNone[0] == 0)
  680. MLLoadString(IDS_NONE, szNone, ARRAYSIZE(szNone));
  681. StrCpy(pszText, szNone);
  682. return FALSE;
  683. }
  684. GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, pszText, 64);
  685. pszText += lstrlen(pszText);
  686. *pszText++ = ' ';
  687. GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, pszText, 64);
  688. return TRUE;
  689. }
  690. BOOL Date2LocalDateString(SYSTEMTIME * st, LPTSTR dtStr, int size)
  691. {
  692. ASSERT(dtStr);
  693. return GetDateFormat(LOCALE_USER_DEFAULT, 0, st, NULL, dtStr, size);
  694. }
  695. void CopyToOOEBuf(POOEntry pooe, POOEBuf pBuf)
  696. {
  697. ASSERT(pooe);
  698. ASSERT(pBuf);
  699. pBuf->dwFlags = pooe->dwFlags;
  700. pBuf->m_LastUpdated = pooe->m_LastUpdated;
  701. pBuf->m_NextUpdate = pooe->m_NextUpdate;
  702. pBuf->m_SizeLimit = pooe->m_SizeLimit;
  703. pBuf->m_ActualSize = pooe->m_ActualSize;
  704. pBuf->m_RecurseLevels = pooe->m_RecurseLevels;
  705. pBuf->m_RecurseFlags = pooe->m_RecurseFlags;
  706. pBuf->m_Priority = pooe->m_Priority;
  707. pBuf->bDesktop = pooe->bDesktop;
  708. pBuf->bChannel = pooe->bChannel;
  709. pBuf->bMail = pooe->bMail;
  710. pBuf->bGleam = pooe->bGleam;
  711. pBuf->bChangesOnly = pooe->bChangesOnly;
  712. pBuf->fChannelFlags = pooe->fChannelFlags;
  713. pBuf->bNeedPassword = pooe->bNeedPassword;
  714. pBuf->m_Cookie = pooe->m_Cookie;
  715. pBuf->groupCookie = pooe->groupCookie;
  716. pBuf->grfTaskTrigger = pooe->grfTaskTrigger;
  717. pBuf->m_Trigger = pooe->m_Trigger;
  718. pBuf->clsidDest = pooe->clsidDest;
  719. pBuf->status = pooe->status;
  720. StrCpyN(pBuf->m_URL, URL(pooe), MAX_URL);
  721. StrCpyN(pBuf->m_Name, NAME(pooe), MAX_NAME);
  722. StrCpyN(pBuf->username, UNAME(pooe), MAX_USERNAME);
  723. StrCpyN(pBuf->password, PASSWD(pooe), MAX_PASSWORD);
  724. StrCpyN(pBuf->statusStr, STATUS(pooe), MAX_STATUS);
  725. }
  726. void CopyToMyPooe(POOEBuf pBuf, POOEntry pooe)
  727. {
  728. UINT offset = sizeof(OOEntry);
  729. UINT srcLen = lstrlen(pBuf->m_URL) + 1;
  730. ASSERT(pooe);
  731. ASSERT(pBuf);
  732. pooe->dwFlags = pBuf->dwFlags;
  733. pooe->m_LastUpdated = pBuf->m_LastUpdated;
  734. pooe->m_NextUpdate = pBuf->m_NextUpdate;
  735. pooe->m_SizeLimit = pBuf->m_SizeLimit;
  736. pooe->m_ActualSize = pBuf->m_ActualSize;
  737. pooe->m_RecurseLevels = pBuf->m_RecurseLevels;
  738. pooe->m_Priority = pBuf->m_Priority;
  739. pooe->m_RecurseFlags = pBuf->m_RecurseFlags;
  740. pooe->bDesktop = pBuf->bDesktop;
  741. pooe->bChannel = pBuf->bChannel;
  742. pooe->bMail = pBuf->bMail;
  743. pooe->bGleam = pBuf->bGleam;
  744. pooe->bChangesOnly = pBuf->bChangesOnly;
  745. pooe->fChannelFlags = pBuf->fChannelFlags;
  746. pooe->bNeedPassword = pBuf->bNeedPassword;
  747. pooe->m_Cookie = pBuf->m_Cookie;
  748. pooe->groupCookie = pBuf->groupCookie;
  749. pooe->m_Trigger = pBuf->m_Trigger;
  750. pooe->grfTaskTrigger = pBuf->grfTaskTrigger;
  751. pooe->clsidDest = pBuf->clsidDest;
  752. pooe->status = pBuf->status;
  753. pooe->m_URL = (LPTSTR)((LPBYTE)pooe + offset);
  754. srcLen = lstrlen(pBuf->m_URL) + 1;
  755. StrCpyN(pooe->m_URL, pBuf->m_URL, srcLen);
  756. offset += srcLen * sizeof (TCHAR);
  757. pooe->m_URL = (LPTSTR) PtrDifference(pooe->m_URL, pooe);
  758. pooe->m_Name = (LPTSTR)((LPBYTE)pooe + offset);
  759. srcLen = lstrlen(pBuf->m_Name) + 1;
  760. StrCpyN(pooe->m_Name, pBuf->m_Name, srcLen);
  761. offset += srcLen * sizeof (TCHAR);
  762. pooe->m_Name = (LPTSTR) PtrDifference(pooe->m_Name, pooe);
  763. pooe->username = (LPTSTR)((LPBYTE)pooe + offset);
  764. srcLen = lstrlen(pBuf->username) + 1;
  765. StrCpyN(pooe->username, pBuf->username, srcLen);
  766. offset += srcLen * sizeof (TCHAR);
  767. pooe->username = (LPTSTR) PtrDifference(pooe->username, pooe);
  768. pooe->password = (LPTSTR)((LPBYTE)pooe + offset);
  769. srcLen = lstrlen(pBuf->password) + 1;
  770. StrCpyN(pooe->password, pBuf->password, srcLen);
  771. offset += srcLen * sizeof (TCHAR);
  772. pooe->password = (LPTSTR) PtrDifference(pooe->password, pooe);
  773. pooe->statusStr = (LPTSTR)((LPBYTE)pooe + offset);
  774. srcLen = lstrlen(pBuf->statusStr) + 1;
  775. StrCpyN(pooe->statusStr, pBuf->statusStr, srcLen);
  776. offset += srcLen * sizeof (TCHAR);
  777. pooe->statusStr = (LPTSTR) PtrDifference(pooe->statusStr, pooe);
  778. pooe->dwSize = offset;
  779. }
  780. UINT BufferSize(POOEBuf pBuf)
  781. {
  782. UINT strLen = 0;
  783. ASSERT(pBuf);
  784. strLen += lstrlen(pBuf->m_URL) + 1;
  785. strLen += lstrlen(pBuf->m_Name) + 1;
  786. strLen += lstrlen(pBuf->username) + 1;
  787. strLen += lstrlen(pBuf->password) + 1;
  788. strLen += lstrlen(pBuf->statusStr) + 1;
  789. return strLen * sizeof(TCHAR);
  790. }
  791. typedef struct
  792. {
  793. int cItems;
  794. LPCTSTR pszName;
  795. LPCTSTR pszUrl;
  796. } DELETE_CONFIRM_INFO;
  797. INT_PTR CALLBACK ConfirmDeleteDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  798. {
  799. switch(message) {
  800. case WM_INITDIALOG:
  801. {
  802. DELETE_CONFIRM_INFO* pInfo = (DELETE_CONFIRM_INFO*)lParam;
  803. ASSERT (pInfo);
  804. ASSERT(pInfo->cItems == 1);
  805. SetListViewToString (GetDlgItem (hDlg, IDC_NAME), pInfo->pszName);
  806. SetListViewToString (GetDlgItem (hDlg, IDC_LOCATION), pInfo->pszUrl);
  807. }
  808. break;
  809. case WM_COMMAND:
  810. switch(LOWORD(wParam))
  811. {
  812. case IDYES:
  813. case IDNO:
  814. case IDCANCEL:
  815. EndDialog(hDlg, wParam);
  816. break;
  817. }
  818. break;
  819. case WM_NOTIFY:
  820. if (LOWORD(wParam) == IDC_LOCATION)
  821. {
  822. NM_LISTVIEW * pnmlv = (NM_LISTVIEW *)lParam;
  823. ASSERT(pnmlv);
  824. if (pnmlv->hdr.code == LVN_GETINFOTIP)
  825. {
  826. TCHAR szURL[MAX_URL];
  827. LV_ITEM lvi = {0};
  828. lvi.mask = LVIF_TEXT;
  829. lvi.pszText = szURL;
  830. lvi.cchTextMax = ARRAYSIZE(szURL);
  831. if (!ListView_GetItem (GetDlgItem (hDlg, IDC_LOCATION), &lvi))
  832. return FALSE;
  833. NMLVGETINFOTIP * pTip = (NMLVGETINFOTIP *)pnmlv;
  834. ASSERT(pTip->pszText);
  835. StrCpyN(pTip->pszText, szURL, pTip->cchTextMax);
  836. return TRUE;
  837. }
  838. }
  839. return FALSE;
  840. default:
  841. return FALSE;
  842. } // end of switch
  843. return TRUE;
  844. }
  845. BOOL ConfirmDelete(HWND hwnd, UINT cItems, LPMYPIDL * ppidl)
  846. {
  847. ASSERT(ppidl);
  848. INT_PTR iRet;
  849. // Check if the user is restricted from deleting URLs.
  850. // If they're deleting multiple, we'll fail if any can fail.
  851. UINT i;
  852. for (i = 0; i < cItems; i++)
  853. {
  854. if (ppidl[i]->ooe.bChannel)
  855. {
  856. if (SHRestricted2(REST_NoRemovingChannels, URL(&(ppidl[i]->ooe)), 0))
  857. {
  858. if (IsWindow(hwnd))
  859. SGMessageBox(hwnd, IDS_RESTRICTED, MB_OK);
  860. return FALSE;
  861. }
  862. }
  863. if (!ppidl[i]->ooe.bDesktop)
  864. {
  865. // FEATURE: What about desktop components?
  866. if (SHRestricted2(REST_NoRemovingSubscriptions, URL(&(ppidl[i]->ooe)), 0))
  867. {
  868. if (IsWindow(hwnd))
  869. SGMessageBox(hwnd, IDS_RESTRICTED, MB_OK);
  870. return FALSE;
  871. }
  872. }
  873. }
  874. if (IsWindow(hwnd)) {
  875. DELETE_CONFIRM_INFO dci = {0};
  876. dci.cItems = cItems;
  877. if (cItems == 1)
  878. {
  879. dci.pszName = NAME(&(ppidl[0]->ooe));
  880. dci.pszUrl = URL(&(ppidl[0]->ooe));
  881. iRet = DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_OBJECTDEL_WARNING),
  882. hwnd, ConfirmDeleteDlgProc, (LPARAM)&dci);
  883. }
  884. else
  885. {
  886. TCHAR szFormat[200];
  887. // Enough room for format string and int as string
  888. TCHAR szBuf[ARRAYSIZE(szFormat) + 11];
  889. MLLoadString(IDS_DEL_MULTIPLE_FMT, szFormat, ARRAYSIZE(szFormat));
  890. wnsprintf(szBuf, ARRAYSIZE(szBuf), szFormat, cItems);
  891. MLLoadString(IDS_DELETE_CAPTION, szFormat, ARRAYSIZE(szFormat));
  892. MSGBOXPARAMS mbp;
  893. mbp.cbSize = sizeof(MSGBOXPARAMS);
  894. mbp.hwndOwner = hwnd;
  895. mbp.hInstance = MLGetHinst();
  896. mbp.lpszText = szBuf;
  897. mbp.lpszCaption = szFormat;
  898. mbp.dwStyle = MB_YESNO | MB_USERICON;
  899. mbp.lpszIcon = MAKEINTRESOURCE(IDI_OBJECTDELETED);
  900. iRet = MessageBoxIndirect(&mbp);
  901. }
  902. if (iRet == IDYES)
  903. return TRUE;
  904. return FALSE;
  905. } else {
  906. return TRUE;
  907. }
  908. }
  909. BOOL IsHTTPPrefixed(LPCTSTR szURL)
  910. {
  911. TCHAR szCanonicalURL[MAX_URL];
  912. DWORD dwSize = MAX_URL;
  913. URL_COMPONENTS uc;
  914. memset(&uc, 0, sizeof(URL_COMPONENTS));
  915. uc.dwStructSize = sizeof(URL_COMPONENTS);
  916. // Note: We explicitly check for and allow the "about:home" URL to pass through here. This allows
  917. // the Active Desktop "My Current Home Page" component to specify that URL when creating and managing
  918. // it's subscription which is consistent with it's use of that form in the browser.
  919. if (!InternetCanonicalizeUrl(szURL, szCanonicalURL, &dwSize, ICU_DECODE) ||
  920. !InternetCrackUrl(szCanonicalURL, 0, 0, &uc) ||
  921. ((INTERNET_SCHEME_HTTP != uc.nScheme) && (INTERNET_SCHEME_HTTPS != uc.nScheme) && (0 != StrCmpI(TEXT("about:home"), szURL))))
  922. {
  923. return FALSE;
  924. }
  925. return TRUE;
  926. }
  927. // Checks if global state is offline
  928. BOOL IsGlobalOffline(void)
  929. {
  930. DWORD dwState = 0, dwSize = sizeof(DWORD);
  931. BOOL fRet = FALSE;
  932. HANDLE hModuleHandle = LoadLibraryA("wininet.dll");
  933. if(!hModuleHandle)
  934. return FALSE;
  935. if(InternetQueryOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &dwState,
  936. &dwSize))
  937. {
  938. if(dwState & INTERNET_STATE_DISCONNECTED_BY_USER)
  939. fRet = TRUE;
  940. }
  941. return fRet;
  942. }
  943. void SetGlobalOffline(BOOL fOffline)
  944. {
  945. INTERNET_CONNECTED_INFO ci;
  946. memset(&ci, 0, sizeof(ci));
  947. if(fOffline) {
  948. ci.dwConnectedState = INTERNET_STATE_DISCONNECTED_BY_USER;
  949. ci.dwFlags = ISO_FORCE_DISCONNECTED;
  950. } else {
  951. ci.dwConnectedState = INTERNET_STATE_CONNECTED;
  952. }
  953. InternetSetOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci));
  954. }
  955. //helper function to create one column in a ListView control, add one item to that column,
  956. //size the column to the width of the control, and color the control like a static...
  957. //basically, like SetWindowText for a ListView. Because we use a lot of ListViews to display
  958. //urls that would otherwise be truncated... the ListView gives us automatic ellipsis and ToolTip.
  959. void SetListViewToString (HWND hLV, LPCTSTR pszString)
  960. {
  961. ASSERT(hLV);
  962. LV_COLUMN lvc = {0};
  963. RECT lvRect;
  964. GetClientRect (hLV, &lvRect);
  965. lvc.mask = LVCF_WIDTH;
  966. lvc.cx = lvRect.right - lvRect.left;
  967. if (-1 == ListView_InsertColumn(hLV, 0, &lvc)) {
  968. ASSERT(0);
  969. }
  970. SendMessage(hLV, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_INFOTIP, LVS_EX_INFOTIP);
  971. LV_ITEM lvi = {0};
  972. lvi.iSubItem = 0;
  973. lvi.pszText = (LPTSTR)pszString;
  974. lvi.mask = LVIF_TEXT;
  975. ListView_InsertItem(hLV, &lvi);
  976. ListView_EnsureVisible(hLV, 0, TRUE);
  977. ListView_SetBkColor(hLV, GetSysColor(COLOR_BTNFACE));
  978. ListView_SetTextBkColor(hLV, GetSysColor(COLOR_BTNFACE));
  979. }
  980. int WCMessageBox(HWND hwnd, UINT idTextFmt, UINT idCaption, UINT uType, ...)
  981. {
  982. TCHAR szCaption[256];
  983. TCHAR szTextFmt[512];
  984. LPTSTR pszText;
  985. int result;
  986. va_list va;
  987. va_start(va, uType);
  988. szCaption[0] = 0;
  989. MLLoadString(idTextFmt, szTextFmt, ARRAYSIZE(szTextFmt));
  990. if (idCaption <= 0)
  991. {
  992. if (NULL != hwnd)
  993. {
  994. GetWindowText(hwnd, szCaption, ARRAYSIZE(szCaption));
  995. }
  996. // This handles GetWindowText failure and a NULL hwnd
  997. if (0 == szCaption[0])
  998. {
  999. #if IDS_DEFAULT_MSG_CAPTION < 1
  1000. #error IDS_DEFAULT_MSG_CAPTION is defined incorrectly
  1001. #endif
  1002. idCaption = IDS_DEFAULT_MSG_CAPTION;
  1003. }
  1004. }
  1005. if (idCaption > 0)
  1006. {
  1007. MLLoadString(idCaption, szCaption, ARRAYSIZE(szCaption));
  1008. }
  1009. ASSERT(0 != szCaption[0]);
  1010. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  1011. szTextFmt, 0, 0, (LPTSTR)&pszText, 0, &va);
  1012. result = MessageBox(hwnd, pszText, szCaption, uType);
  1013. LocalFree(pszText);
  1014. return result;
  1015. }
  1016. /////////////////////////////////////////////////////////////////////////////
  1017. // SGMessageBox
  1018. /////////////////////////////////////////////////////////////////////////////
  1019. int SGMessageBox
  1020. (
  1021. HWND hwndParent,
  1022. UINT idStringRes,
  1023. UINT uType
  1024. )
  1025. {
  1026. ASSERT(hwndParent != NULL);
  1027. ASSERT(IsWindow(hwndParent));
  1028. TCHAR szError[512];
  1029. if (!MLLoadString(idStringRes, szError, ARRAYSIZE(szError)))
  1030. return 0;
  1031. TCHAR szTitle[128];
  1032. szTitle[0] = 0;
  1033. if (hwndParent != NULL)
  1034. GetWindowText(hwndParent, szTitle, ARRAYSIZE(szTitle));
  1035. return MessageBox( hwndParent,
  1036. szError,
  1037. ((hwndParent != NULL) ? szTitle : NULL),
  1038. uType);
  1039. }
  1040. #ifdef DEBUG
  1041. /////////////////////////////////////////////////////////////////////////////
  1042. // DumpTaskTrigger
  1043. /////////////////////////////////////////////////////////////////////////////
  1044. void DumpTaskTrigger
  1045. (
  1046. TASK_TRIGGER * pTT
  1047. )
  1048. {
  1049. TraceMsg(TF_DUMPTRIGGER, "----- BEGIN DumpTaskTrigger -----");
  1050. TraceMsg(TF_DUMPTRIGGER, "cbTriggerSize = %d", pTT->cbTriggerSize);
  1051. TraceMsg(TF_DUMPTRIGGER, "Reserved1 = %d", pTT->Reserved1);
  1052. TraceMsg(TF_DUMPTRIGGER, "wBeginYear = %d", pTT->wBeginYear);
  1053. TraceMsg(TF_DUMPTRIGGER, "wBeginMonth = %d", pTT->wBeginMonth);
  1054. TraceMsg(TF_DUMPTRIGGER, "wBeginDay = %d", pTT->wBeginDay);
  1055. TraceMsg(TF_DUMPTRIGGER, "wEndYear = %d", pTT->wEndYear);
  1056. TraceMsg(TF_DUMPTRIGGER, "wEndMonth = %d", pTT->wEndMonth);
  1057. TraceMsg(TF_DUMPTRIGGER, "wEndDay = %d", pTT->wEndDay);
  1058. TraceMsg(TF_DUMPTRIGGER, "wStartHour = %d", pTT->wStartHour);
  1059. TraceMsg(TF_DUMPTRIGGER, "wStartMinute = %d", pTT->wStartMinute);
  1060. TraceMsg(TF_DUMPTRIGGER, "MinutesDuration = %d", pTT->MinutesDuration);
  1061. TraceMsg(TF_DUMPTRIGGER, "MinutesInterval = %d", pTT->MinutesInterval);
  1062. TraceMsg(TF_DUMPTRIGGER, "rgFlags = %d", pTT->rgFlags);
  1063. TraceMsg(TF_DUMPTRIGGER, "Reserved2 = %d", pTT->Reserved2);
  1064. TraceMsg(TF_DUMPTRIGGER, "wRandomMinutesInterval = %d", pTT->wRandomMinutesInterval);
  1065. switch (pTT->TriggerType)
  1066. {
  1067. case TASK_TIME_TRIGGER_DAILY:
  1068. {
  1069. TraceMsg(TF_DUMPTRIGGER, "DAILY");
  1070. TraceMsg(TF_DUMPTRIGGER, "DaysInterval = %d", pTT->Type.Daily.DaysInterval);
  1071. break;
  1072. }
  1073. case TASK_TIME_TRIGGER_WEEKLY:
  1074. {
  1075. TraceMsg(TF_DUMPTRIGGER, "WEEKLY");
  1076. TraceMsg(TF_DUMPTRIGGER, "WeeksInterval = %d", pTT->Type.Weekly.WeeksInterval);
  1077. TraceMsg(TF_DUMPTRIGGER, "rgfDaysOfTheWeek = %d", pTT->Type.Weekly.rgfDaysOfTheWeek);
  1078. break;
  1079. }
  1080. case TASK_TIME_TRIGGER_MONTHLYDATE:
  1081. {
  1082. TraceMsg(TF_DUMPTRIGGER, "MONTHLY DATE");
  1083. TraceMsg(TF_DUMPTRIGGER, "rgfDays = %d", pTT->Type.MonthlyDate.rgfDays);
  1084. TraceMsg(TF_DUMPTRIGGER, "rgfMonths = %d", pTT->Type.MonthlyDate.rgfMonths);
  1085. break;
  1086. }
  1087. case TASK_TIME_TRIGGER_MONTHLYDOW:
  1088. {
  1089. TraceMsg(TF_DUMPTRIGGER, "MONTHLY DOW");
  1090. TraceMsg(TF_DUMPTRIGGER, "wWhichWeek = %d", pTT->Type.MonthlyDOW.wWhichWeek);
  1091. TraceMsg(TF_DUMPTRIGGER, "rgfDaysOfTheWeek = %d", pTT->Type.MonthlyDOW.rgfDaysOfTheWeek);
  1092. TraceMsg(TF_DUMPTRIGGER, "rgfMonths = %d", pTT->Type.MonthlyDOW.rgfMonths);
  1093. break;
  1094. }
  1095. default:
  1096. {
  1097. ASSERT(FALSE);
  1098. break;
  1099. }
  1100. }
  1101. TraceMsg(TF_DUMPTRIGGER, "----- END DumpTaskTrigger -----");
  1102. }
  1103. #endif // DEBUG