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.

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