utils.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 41k
Category:

Windows Kernel

Development Platform:

Visual C++

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