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

Windows Kernel

Development Platform:

Visual C++

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. //#include "clsobj.h"
  4. //#include "resource.h"
  5. //#include "deskstat.h"
  6. //#include "deskhtml.h"
  7. //#include "dback.h"
  8. //#include "dutil.h"
  9. //#include "dsubscri.h"
  10. //#include "dcomp.h"
  11. //#include "..security.h"
  12. //#include <mmhelper.h>
  13. //#include "webcheck.h"
  14. //#include "clsobj.h"
  15. //#include <shlwapip.h>
  16. #include <mluisupp.h>
  17. #ifdef POSTSPLIT
  18. #define THISCLASS CActiveDesktop
  19. #define DXA_GROWTH_CONST 10
  20. #define ZINDEX_START 1000
  21. #if 0
  22. #define TF_DESKSTAT     TF_CUSTOM2
  23. #else
  24. #define TF_DESKSTAT     0
  25. #endif
  26. IActiveDesktop *g_pActiveDesk = NULL;
  27. #define c_szRegStrDesktop REGSTR_PATH_DESKTOP
  28. #define c_szWallpaper  REG_VAL_GENERAL_WALLPAPER
  29. #define c_szBackupWallpaper REG_VAL_GENERAL_BACKUPWALLPAPER
  30. #define c_szPattern TEXT("Pattern")
  31. #define c_szTileWall REG_VAL_GENERAL_TILEWALLPAPER
  32. #define c_szWallpaperStyle REG_VAL_GENERAL_WALLPAPERSTYLE
  33. #define c_szWallpaperTime REG_VAL_GENERAL_WALLPAPERTIME
  34. #define c_szRefreshDesktop TEXT("RefreshDesktop")
  35. #define c_szBufferedRefresh TEXT("BufferedRefresh")
  36. #define COMP_TYPE               0x00000003
  37. #define COMP_SELECTED           0x00002000
  38. #define COMP_NOSCROLL           0x00004000
  39. #ifdef DEBUG
  40. #define ENTERPROC EnterProcDS
  41. #define EXITPROC ExitProcDS
  42. void EnterProcDS(DWORD dwTraceLevel, LPSTR szFmt, ...);
  43. void ExitProcDS(DWORD dwTraceLevel, LPSTR szFmt, ...);
  44. extern DWORD g_dwDeskStatTrace;
  45. #else
  46. #ifndef CCOVER
  47. #pragma warning(disable:4002)
  48. #define ENTERPROC()
  49. #define EXITPROC()
  50. #else // work around a bug in preprocessing by cl.exe
  51. #define ENTERPROC 1 ? (void) 0 : (void)
  52. #define EXITPROC 1 ? (void) 0 : (void)
  53. #endif
  54. #endif
  55. STDAPI ParseDesktopComponent(HWND hwndOwner, LPWSTR wszURL, COMPONENT *pInfo);
  56. int GetIntFromReg(HKEY    hKey,
  57.                   LPCTSTR lpszSubkey,
  58.                   LPCTSTR lpszNameValue,
  59.                   int     iDefault)
  60. {
  61.     TCHAR szValue[20];
  62.     DWORD dwSizeofValueBuff = SIZEOF(szValue);
  63.     int iRetValue = iDefault;
  64.     DWORD dwType;
  65.     if ((SHGetValue(hKey, lpszSubkey, lpszNameValue, &dwType,(LPBYTE)szValue,
  66.                    &dwSizeofValueBuff) == ERROR_SUCCESS) && dwSizeofValueBuff)
  67.     {
  68.         if (dwType == REG_SZ)
  69.         {
  70.             iRetValue = (int)StrToInt(szValue);
  71.         }
  72.     }
  73.     return iRetValue;
  74. }
  75. BOOL GetStringFromReg(HKEY    hkey,
  76.               LPCTSTR lpszSubkey,
  77.               LPCTSTR lpszValueName,
  78.               LPCTSTR lpszDefault,
  79.               LPTSTR  lpszValue,
  80.               DWORD   cchSizeofValueBuff)
  81. {
  82.     BOOL fRet = FALSE;
  83.     DWORD dwType;
  84.     cchSizeofValueBuff *= sizeof(TCHAR);
  85.     if (SHGetValue(hkey, lpszSubkey, lpszValueName, &dwType, lpszValue, &cchSizeofValueBuff) == ERROR_SUCCESS)
  86.     {
  87.         fRet = TRUE;
  88.     }
  89.     //
  90.     // On failure use the default string.
  91.     //
  92.     if (!fRet && lpszDefault)
  93.     {
  94.         lstrcpy(lpszValue, lpszDefault);
  95.     }
  96.     return fRet;
  97. }
  98. void GetWallpaperFileTime(LPCTSTR pszWallpaper, LPFILETIME lpftFileTime)
  99. {
  100.     HANDLE   hFile;
  101.     BOOL     fSuccess = FALSE;
  102.     if((hFile = CreateFile(pszWallpaper, GENERIC_READ, FILE_SHARE_READ,
  103.             NULL, OPEN_EXISTING,
  104.             FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE)
  105.     {
  106.         if(GetFileTime(hFile, NULL, NULL, lpftFileTime))
  107.             fSuccess = TRUE;
  108.         CloseHandle(hFile);
  109.     }
  110.     if(!fSuccess)
  111.         ZeroMemory(lpftFileTime, SIZEOF(*lpftFileTime));
  112. }
  113. BOOL  HasWallpaperReallyChanged(LPCTSTR pszRegKey, LPTSTR pszOldWallpaper, LPTSTR pszBackupWallpaper, LPFILETIME lpftFileTime,
  114.                                 DWORD dwOldWallpaperStyle, DWORD dwNewWallpaperStyle)
  115. {
  116.     BOOL    fRet = FALSE; //Assume that the wallpaper hasn't changed.
  117.     FILETIME ftBackupFileTime;
  118.     DWORD   cchBuffSize;
  119.     DWORD   dwType;
  120.     GetWallpaperFileTime(pszOldWallpaper, lpftFileTime);
  121.     if(lstrcmpi(pszOldWallpaper, pszBackupWallpaper))
  122.         return (TRUE);   //The name of the wallpaper changed.
  123.     // The wallpaper filename hasn't changed. But, the content of this file
  124.     // could have changed. See if the content has changed by looking at the 
  125.     // last-written date and time stamp on this file.
  126.      
  127.     cchBuffSize = SIZEOF(ftBackupFileTime);
  128.     //Get the last written time of the backup wallpaper from registry
  129.     if (SHGetValue(HKEY_CURRENT_USER, pszRegKey, c_szWallpaperTime, &dwType, &ftBackupFileTime, &cchBuffSize) != ERROR_SUCCESS)
  130.         ZeroMemory(&ftBackupFileTime, SIZEOF(ftBackupFileTime));
  131.     if((lpftFileTime->dwLowDateTime != ftBackupFileTime.dwLowDateTime) ||
  132.        (lpftFileTime->dwHighDateTime != ftBackupFileTime.dwHighDateTime))
  133.         fRet = TRUE; //The wallpaper content has changed
  134.     //See if the wallpaper style has changed.
  135.     if(dwOldWallpaperStyle != dwNewWallpaperStyle)
  136.         fRet = TRUE;
  137.     
  138.     return (fRet);
  139. }
  140. //-------------------------------------------------------------------------------------------------------------//
  141. //  Function: ReadWallpaperStyleFromReg()
  142. //
  143. // This function reads the "TileWallpaper" and the "WallpaperStyle" from the given location
  144. // in the registry.
  145. //
  146. //-------------------------------------------------------------------------------------------------------------//
  147. void ReadWallpaperStyleFromReg(LPCTSTR pszRegKey, DWORD *pdwWallpaperStyle, BOOL fIgnorePlatforms)
  148. {
  149.     //Do not read "Stretch" bits for older platforms.
  150.     if(fIgnorePlatforms || g_bRunOnMemphis || g_bRunOnNT5)
  151.         *pdwWallpaperStyle = GetIntFromReg(HKEY_CURRENT_USER, pszRegKey, c_szWallpaperStyle, WPSTYLE_CENTER);
  152.     else
  153.         *pdwWallpaperStyle = WPSTYLE_CENTER;
  154.     if (GetIntFromReg(HKEY_CURRENT_USER, pszRegKey, c_szTileWall, WPSTYLE_TILE))
  155.     {
  156.         //
  157.         // "Tile" overrides the "Stretch" style.
  158.         //
  159.         *pdwWallpaperStyle = WPSTYLE_TILE;
  160.     }
  161.     // else, STRETCH or CENTER.
  162. }
  163. void THISCLASS::_ReadWallpaper(BOOL fActiveDesktop)
  164. {
  165.     ENTERPROC(2, "DS ReadWallpaper()");
  166.     TCHAR lpszDeskcomp[MAX_PATH];
  167.     GetRegLocation(lpszDeskcomp, REG_DESKCOMP_GENERAL, _pszScheme);
  168.     //
  169.     // Read in the wallpaper and style from the appropriate registry location.
  170.     //
  171.     LPCTSTR pszRegKey;
  172.     if (fActiveDesktop)
  173.     {
  174.         pszRegKey = (LPCTSTR)lpszDeskcomp;
  175.         TCHAR   szOldWallpaper[MAX_PATH];
  176.         DWORD   dwOldWallpaperStyle;
  177.         // Read the Wallpaper from the Old location.
  178.         if(!GetStringFromReg(HKEY_CURRENT_USER, c_szRegStrDesktop, c_szWallpaper, c_szNULL, szOldWallpaper, ARRAYSIZE(szOldWallpaper)))
  179.             szOldWallpaper[0] = TEXT('');
  180.         // Read wallpaper style from the old location.
  181.         ReadWallpaperStyleFromReg((LPCTSTR)c_szRegStrDesktop, &dwOldWallpaperStyle, FALSE);
  182.         // Read the wallpaper from the new location too!
  183.         if (!GetStringFromReg(HKEY_CURRENT_USER, pszRegKey, c_szWallpaper, c_szNULL, _szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper)))
  184.         {
  185.             pszRegKey = c_szRegStrDesktop;
  186.             lstrcpy(_szSelectedWallpaper, szOldWallpaper);
  187.         }
  188.         //Read wallpaper style from the new location too!
  189.         ReadWallpaperStyleFromReg(pszRegKey, &_wpo.dwStyle, FALSE);
  190.         
  191.         //If there is a Safe mode scheme here do NOT attempt to change wallpaper
  192.         WCHAR wszDisplay[MAX_PATH];
  193.         DWORD dwcch = MAX_PATH;
  194.         if(FAILED(GetScheme(wszDisplay, &dwcch, SCHEME_GLOBAL | SCHEME_DISPLAY)) ||
  195.                  (StrCmpW(wszDisplay, REG_DESKCOMP_SAFEMODE_SUFFIX_L) != 0))
  196.         {
  197.             DWORD     dwType;
  198.             DWORD     cchBuffSize;
  199.             //We are not in Safe mode.
  200.             cchBuffSize = SIZEOF(_ftWallpaperFileTime);
  201.             //Read what is currently stored as wallpaper last-written time.
  202.             if (SHGetValue(HKEY_CURRENT_USER, pszRegKey, c_szWallpaperTime, &dwType, &_ftWallpaperFileTime, &cchBuffSize) != ERROR_SUCCESS)
  203.                 ZeroMemory(&_ftWallpaperFileTime, SIZEOF(_ftWallpaperFileTime));
  204.             FILETIME ftOldFileTime;
  205.             //Read what is stored as "Backup" wallpaper.
  206.             if (!GetStringFromReg(HKEY_CURRENT_USER, pszRegKey, c_szBackupWallpaper, c_szNULL, _szBackupWallpaper, ARRAYSIZE(_szBackupWallpaper)))
  207.                 lstrcpy(_szBackupWallpaper, szOldWallpaper);
  208.     
  209.             //See if the Old wallpaper is differnet from the backed up wallpaper
  210.             if(HasWallpaperReallyChanged(pszRegKey, szOldWallpaper, _szBackupWallpaper, &ftOldFileTime, dwOldWallpaperStyle, _wpo.dwStyle))
  211.             {
  212.                 //They are different. This means that some other app has changed the "Old" wallpaper
  213.                 //after the last time we backed it up in the registry.
  214.                 // Make this wallpaper as the Selected wallpaper!
  215.                 // This is a kinda hack, but the best possible solution right now. The scenario is as follows.
  216.                 // The Memphis setup guys replace what the user specifies as the wallpaper in the old location
  217.                 // and restore it after setup is complete. But, SetDefaultWallpaper() gets called bet. these
  218.                 // two times and we are supposed to take a decision on whether to set the default htm wallpaper or not,
  219.                 // depending on what the user had set before the installation. The solution is to delay making
  220.                 // this decision until after the setup guys have restored the user's wallpaper. We do this in
  221.                 // CActiveDesktop::_ReadWallpaper(). We specify that SetDefaultWallpaper() was called by setting
  222.                 // the backup wallpaper in the new location to the default wallpaper.
  223.                 TCHAR szDefaultWallpaper[INTERNET_MAX_URL_LENGTH];
  224.                 GetWallpaperDirName(szDefaultWallpaper, ARRAYSIZE(szDefaultWallpaper));
  225.                 lstrcat(szDefaultWallpaper, TEXT("\"));
  226.                 TCHAR szWP[INTERNET_MAX_URL_LENGTH];
  227.                 GetDefaultWallpaper(szWP);
  228.                 lstrcat(szDefaultWallpaper, szWP);
  229.         
  230.                 if(lstrcmp(_szBackupWallpaper, szDefaultWallpaper) == 0
  231.                     && (!szOldWallpaper[0] || lstrcmp(szOldWallpaper, g_szNone) == 0))
  232.                 {
  233.                     lstrcpy(_szSelectedWallpaper, szDefaultWallpaper);
  234.                 }
  235.                 else
  236.                 {
  237.                     lstrcpy(_szSelectedWallpaper, szOldWallpaper);
  238.                 }
  239.                 _ftWallpaperFileTime = ftOldFileTime;
  240.                 _wpo.dwStyle = dwOldWallpaperStyle;
  241.                 _fWallpaperDirty = TRUE;
  242.                 _fWallpaperChangedDuringInit = TRUE;
  243.             }
  244.             //Make a backup of the "Old" wallpaper
  245.             lstrcpy(_szBackupWallpaper, szOldWallpaper);
  246.         }
  247.         else
  248.         {
  249.             lstrcpy(_szBackupWallpaper, szOldWallpaper);
  250.             GetWallpaperFileTime(_szBackupWallpaper, &_ftWallpaperFileTime);
  251.         }
  252.     }
  253.     else
  254.     {
  255.         pszRegKey = c_szRegStrDesktop; //Get it from the old location!
  256.         //Since active desktop is not available, read wallpaper from old location.
  257.         GetStringFromReg(HKEY_CURRENT_USER, pszRegKey, c_szWallpaper, c_szNULL, _szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper));
  258.         //Make a backup of the "Old" wallpaper
  259.         lstrcpy(_szBackupWallpaper, _szSelectedWallpaper);
  260.         GetWallpaperFileTime(_szBackupWallpaper, &_ftWallpaperFileTime);
  261.         //Read the wallpaper style
  262.         ReadWallpaperStyleFromReg(pszRegKey, &_wpo.dwStyle, TRUE);
  263.     }
  264.     EXITPROC(2, "DS ReadWallpaper! (_szSelectedWP=>%s<)", _szSelectedWallpaper);
  265. }
  266. void THISCLASS::_ReadPattern(void)
  267. {
  268.     ENTERPROC(2, "DS ReadPattern()");
  269.     GetStringFromReg(HKEY_CURRENT_USER, c_szRegStrDesktop, c_szPattern, c_szNULL, _szSelectedPattern, ARRAYSIZE(_szSelectedPattern));
  270.     EXITPROC(2, "DS ReadPattern! (_szSelectedPattern=>%s<)", _szSelectedPattern);
  271. }
  272. void THISCLASS::_ReadComponent(HKEY hkey, LPCTSTR pszComp)
  273. {
  274.     ENTERPROC(2, "DS ReadComponent(hk=%08X,pszComp=>%s<)", hkey, pszComp);
  275.     HKEY hkeyComp;
  276.     if (RegOpenKeyEx(hkey, pszComp, 0, KEY_READ, &hkeyComp) == ERROR_SUCCESS)
  277.     {
  278.         DWORD cbSize, dwType;
  279.         COMPONENTA comp;
  280.         comp.dwSize = sizeof(COMPONENTA);
  281.         //
  282.         // Read in the source string.
  283.         //
  284.         cbSize = SIZEOF(comp.szSource);
  285.         if (RegQueryValueEx(hkeyComp, REG_VAL_COMP_SOURCE, NULL, &dwType, (LPBYTE)&comp.szSource, &cbSize) != ERROR_SUCCESS)
  286.         {
  287.             comp.szSource[0] = TEXT('');
  288.         }
  289.         //
  290.         // Read in the SubscribedURL string.
  291.         //
  292.         cbSize = SIZEOF(comp.szSubscribedURL);
  293.         if (RegQueryValueEx(hkeyComp, REG_VAL_COMP_SUBSCRIBED_URL, NULL, &dwType, (LPBYTE)&comp.szSubscribedURL, &cbSize) != ERROR_SUCCESS)
  294.         {
  295.             comp.szSubscribedURL[0] = TEXT('');
  296.         }
  297.         //
  298.         // Read in the Friendly name string.
  299.         //
  300.         cbSize = SIZEOF(comp.szFriendlyName);
  301.         if (RegQueryValueEx(hkeyComp, REG_VAL_COMP_NAME, NULL, &dwType, (LPBYTE)&comp.szFriendlyName, &cbSize) != ERROR_SUCCESS)
  302.         {
  303.             comp.szFriendlyName[0] = TEXT('');
  304.         }
  305.         //
  306.         // Read in and parse the flags.
  307.         //
  308.         DWORD dwFlags;
  309.         cbSize = SIZEOF(dwFlags);
  310.         if (RegQueryValueEx(hkeyComp, REG_VAL_COMP_FLAGS, NULL, &dwType, (LPBYTE)&dwFlags, &cbSize) != ERROR_SUCCESS)
  311.         {
  312.             dwFlags = 0;
  313.         }
  314.         comp.iComponentType = dwFlags & COMP_TYPE;
  315.         comp.fChecked = (dwFlags & COMP_SELECTED) != 0;
  316.         comp.fNoScroll = (dwFlags & COMP_NOSCROLL) != 0;
  317.         comp.fDirty = FALSE;    //Reading it fresh from registry; Can't be dirty!
  318.         //
  319.         // Read in the location.
  320.         //
  321.         cbSize = SIZEOF(comp.cpPos);
  322.         if (RegQueryValueEx(hkeyComp, REG_VAL_COMP_POSITION, NULL, &dwType, (LPBYTE)&comp.cpPos, &cbSize) != ERROR_SUCCESS)
  323.         {
  324.             ZeroMemory(&comp.cpPos, SIZEOF(comp.cpPos));
  325.         }
  326.         //
  327.         // In IE4.x, we have a very huge positive number (0x7fffffff) as the COMPONENT_TOP;
  328.         // As a result some component's z-index overflowed into the negative range (0x80000003)
  329.         // To fix this, we halved the COMPONENT_TOP (0x3fffffff) and also check for negative z-index
  330.         // values and covert them to postive values.
  331.         if(comp.cpPos.izIndex < 0)
  332.             comp.cpPos.izIndex = COMPONENT_TOP;
  333.         //
  334.         // Make sure the cpPos.dwSize is set to correct value
  335.         //
  336.         comp.cpPos.dwSize = sizeof(COMPPOS);
  337.         //
  338.         //  Read in the current ItemState
  339.         //
  340.         cbSize = SIZEOF(comp.dwCurItemState);
  341.         if (RegQueryValueEx(hkeyComp, REG_VAL_COMP_CURSTATE, NULL, &dwType, (LPBYTE)&comp.dwCurItemState, &cbSize) != ERROR_SUCCESS)
  342.         {
  343.             //If the item state is missing, we must be reading from IE4 machine.
  344.             comp.dwCurItemState = IS_NORMAL;
  345.         }
  346.         //
  347.         //  Read in the Original state info.
  348.         //
  349.         cbSize = SIZEOF(comp.csiOriginal);
  350.         if (RegQueryValueEx(hkeyComp, REG_VAL_COMP_ORIGINALSTATEINFO, NULL, &dwType, (LPBYTE)&comp.csiOriginal, &cbSize) != ERROR_SUCCESS)
  351.         {
  352.             //If the item state is missing, we must be reading from IE4 machine.
  353.             // Set the OriginalState to the default info.
  354.             SetStateInfo(&comp.csiOriginal, &comp.cpPos, IS_NORMAL);
  355.         }
  356.         //
  357.         //  Read in the Restored state info.
  358.         //
  359.         cbSize = SIZEOF(comp.csiRestored);
  360.         if (RegQueryValueEx(hkeyComp, REG_VAL_COMP_RESTOREDSTATEINFO, NULL, &dwType, (LPBYTE)&comp.csiRestored, &cbSize) != ERROR_SUCCESS)
  361.         {
  362.             //If the item state is missing, we must be reading from IE4 machine.
  363.             // Set the restored State to the default info.
  364.             SetStateInfo(&comp.csiRestored, &comp.cpPos, IS_NORMAL);
  365.         }
  366.         //
  367.         // Add the component to the component list.
  368.         //
  369.         AddComponentPrivate(&comp, StrToInt(pszComp));
  370.         //
  371.         // Increment our counter so we know where to add any new
  372.         // components after we're done.
  373.         //
  374.         _dwNextID++;
  375.         RegCloseKey(hkeyComp);
  376.     }
  377.     EXITPROC(2, "DS ReadComponent!");
  378. }
  379. typedef struct _tagSortStruct {
  380.     int ihdsaIndex;
  381.     int izIndex;
  382. } SORTSTRUCT;
  383. int CALLBACK pfnComponentSort(LPVOID p1, LPVOID p2, LPARAM lParam)
  384. {
  385.     SORTSTRUCT * pss1 = (SORTSTRUCT *)p1;
  386.     SORTSTRUCT * pss2 = (SORTSTRUCT *)p2;
  387.     if (pss1->izIndex > pss2->izIndex)
  388.         return 1;
  389.     if (pss1->izIndex < pss2->izIndex)
  390.         return -1;
  391.     return(0);
  392. }
  393. //
  394. // ModifyZIndex
  395. //
  396. // Little helper function to put the zindex of the windowed and windowless components
  397. // into correct buckets so that zorting will produce a correct order by zindex.
  398. //
  399. // If we don't do this then windowless components may end up zordering above windowed ones.
  400. //
  401. void ModifyZIndex(COMPONENTA * pcomp)
  402. {
  403.     if (pcomp->cpPos.izIndex != COMPONENT_TOP) {
  404.         if (!IsWindowLessComponent(pcomp))
  405.             pcomp->cpPos.izIndex += COMPONENT_TOP_WINDOWLESS;
  406.     }
  407.     else
  408.     {
  409.         if (IsWindowLessComponent(pcomp))
  410.             pcomp->cpPos.izIndex = COMPONENT_TOP_WINDOWLESS;
  411.     }
  412. }
  413. //
  414. // SortAndRationalize
  415. //
  416. // SortAndRationalize will take an unsorted component list and sort it such that the components
  417. // come out in the correct z-index indicated order.  It will also rebase the z-index values at
  418. // a known constant so that the z-index values will not grow endlessly.  SortAndRationalize also
  419. // imposes windowed vs. windowless criteria to the zindex values such that windowless components
  420. // always zorder under windowed ones.
  421. //
  422. void THISCLASS::_SortAndRationalize(void)
  423. {
  424.     int icComponents;
  425.     HDPA hdpa;
  426.     if (_hdsaComponent && ((icComponents = DSA_GetItemCount(_hdsaComponent)) > 1) && (hdpa = DPA_Create(0))) {
  427.         COMPONENTA * pcomp;
  428.         SORTSTRUCT * pss;
  429.         int i, iCur = ZINDEX_START;
  430.         BOOL fInsertFailed = FALSE;
  431.         HDSA hdsaOld;
  432.         // Go through each component and insert it's hdsa-index and zindex into the hdpa
  433.         for (i = 0; i < icComponents; i++)
  434.         {
  435.             if (!(pss = (SORTSTRUCT *)LocalAlloc(LPTR, sizeof(SORTSTRUCT))))
  436.                 break;
  437.             pcomp = (COMPONENTA *)DSA_GetItemPtr(_hdsaComponent, i);
  438.             ModifyZIndex(pcomp);
  439.             pss->ihdsaIndex = i;
  440.             pss->izIndex = pcomp->cpPos.izIndex;
  441.             if (DPA_AppendPtr(hdpa, (void FAR *)pss) == -1) {
  442.                 LocalFree((HANDLE)pss);
  443.                 break;
  444.             }
  445.         }
  446.         // Sort the hdpa by zindex
  447.         DPA_Sort(hdpa, pfnComponentSort, 0);
  448.         // Save old values
  449.         hdsaOld = _hdsaComponent;
  450.         // Null out the old hdsa, so AddComponentPrivate will create a new one
  451.         _hdsaComponent = NULL;
  452.         // Now go through the sorted hdpa and update the component zindex with a ZINDEX_START based zindex, then
  453.         // add the component to the new hdsa in sorted order.
  454.         for (i = 0; i < icComponents; i++) {
  455.             if (!(pss = (SORTSTRUCT *)DPA_GetPtr(hdpa, i)))
  456.                 break;
  457.             // Get component and update it's zIndex and id
  458.             pcomp = (COMPONENTA *)DSA_GetItemPtr(hdsaOld, pss->ihdsaIndex);
  459.             pcomp->cpPos.izIndex = iCur;
  460.             iCur += 2;
  461.             // Free ptr
  462.             LocalFree((HANDLE)pss);
  463.             // Add to new hdsa in sorted order
  464.             if (!fInsertFailed) {
  465.                 fInsertFailed = !AddComponentPrivate(pcomp, pcomp->dwID);
  466.             }
  467.         }
  468.         // If we're completely successfull then destroy the old hdsa.  Otherwise we need
  469.         // to destroy the new one and restore the old one.
  470.         if ((i == icComponents) && !fInsertFailed) {
  471.             DSA_Destroy(hdsaOld);
  472.         } else {
  473.             if (_hdsaComponent)
  474.             DSA_Destroy(_hdsaComponent);
  475.             _hdsaComponent = hdsaOld;
  476.         }
  477.         DPA_Destroy(hdpa);
  478.     }
  479. }
  480. void THISCLASS::_ReadComponents(BOOL fActiveDesktop)
  481. {
  482.     ENTERPROC(2, "DS ReadComponents()");
  483.     HKEY hkey;
  484.     TCHAR lpszDeskcomp[MAX_PATH];
  485.     GetRegLocation(lpszDeskcomp, REG_DESKCOMP_COMPONENTS, _pszScheme);
  486.     if (RegOpenKeyEx(HKEY_CURRENT_USER, lpszDeskcomp, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
  487.     {
  488.         DWORD cbSize, dwType;
  489.         int i = 0;
  490.         TCHAR lpszSubkey[MAX_PATH];
  491.         //
  492.         // Read in the general settings.
  493.         //
  494.         DWORD dwSettings;
  495.         cbSize = SIZEOF(dwSettings);
  496.         if (RegQueryValueEx(hkey, REG_VAL_COMP_SETTINGS, NULL, &dwType, (LPBYTE)&dwSettings, &cbSize) == ERROR_SUCCESS)
  497.         {
  498.             _co.fEnableComponents = (dwSettings & COMPSETTING_ENABLE) != 0;
  499.         }
  500.         _co.fActiveDesktop = fActiveDesktop;
  501.         //
  502.         // Read in all the desktop components
  503.         //
  504.         while (RegEnumKey(hkey, i, lpszSubkey, ARRAYSIZE(lpszSubkey)) == ERROR_SUCCESS)
  505.         {
  506.             _ReadComponent(hkey, lpszSubkey);
  507.             i++;
  508.         }
  509.         _SortAndRationalize();
  510.         RegCloseKey(hkey);
  511.     }
  512.     EXITPROC(2, "DS ReadComponents!");
  513. }
  514. void THISCLASS::_Initialize(void)
  515. {
  516.     ENTERPROC(2, "DS Initialize()");
  517.     if (!_fInitialized)
  518.     {
  519.         _fInitialized = TRUE;
  520.         InitDeskHtmlGlobals();
  521.         SHELLSTATE ss = {0};
  522.         SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE);
  523.         
  524.         BOOL fActiveDesktop = BOOLIFY(ss.fDesktopHTML);
  525.         
  526.         _co.dwSize = SIZEOF(_co);
  527.         _wpo.dwSize = SIZEOF(_wpo);
  528.         //
  529.         // This per-user registry branch may not exist for this user. Or, even if
  530.         // it does exist, it may have some stale info. So ensure that atlreast the 
  531.         // default components are there and that the html version is current for this
  532.         // branch of the registry!
  533.         //  If everything is current, the following function does nothing!
  534.         //
  535.         CDeskHtmlProp_RegUnReg(TRUE);  //TRUE => install.
  536.         _ReadWallpaper(fActiveDesktop);
  537.         _ReadPattern();
  538.         _ReadComponents(fActiveDesktop);
  539.         _fDirty = FALSE;
  540.         _fNeedBodyEnd = FALSE;
  541.     }
  542.     EXITPROC(2, "DS Initialize!");
  543. }
  544. void THISCLASS::_SaveWallpaper(void)
  545. {
  546.     ENTERPROC(2, "DS SaveWallpaper");
  547.     TCHAR lpszDeskcomp[MAX_PATH];
  548.     BOOL    fNormalWallpaper;
  549.     GetRegLocation(lpszDeskcomp, REG_DESKCOMP_GENERAL, _pszScheme);
  550.     //
  551.     // Compute tiling string.
  552.     //
  553.     TCHAR szTiled[2];
  554.     lstrcpy(szTiled, c_szZero);
  555.     szTiled[0] = szTiled[0] + (TCHAR)(_wpo.dwStyle & WPSTYLE_TILE);
  556.     //
  557.     // Compute the Wallpaper styling string
  558.     //
  559.     TCHAR       szWPStyle[2];
  560.     lstrcpy(szWPStyle, c_szZero);
  561.     //
  562.     // NOTE: If WPSTYLE_TILE is set, we still want to say WallpaperStyle="0"; This won't hurt
  563.     // because TileWallpaper="1" will over-ride this anyway.
  564.     // The reason for this hack is that during memphis setup, they put a tiled wallpaper. Then we
  565.     // write WallpaperStyle=1 and TileWallpaper=1 in new and old locations. Then, then change
  566.     // the wallpaper and set TileWallpaper=0. Since the WallpaperStyle continues to be 1, they 
  567.     // get a tiled wallpaper finally. The following is to avoid this problem!
  568.     // 
  569.     szWPStyle[0] = szWPStyle[0] + (TCHAR)(_wpo.dwStyle & WPSTYLE_STRETCH);
  570.     
  571.     //
  572.     // Write out wallpaper settings in new active desktop area.
  573.     //
  574.     if(_fWallpaperDirty || _fWallpaperChangedDuringInit)
  575.     {
  576.         SHSetValue(HKEY_CURRENT_USER, lpszDeskcomp,
  577.             c_szTileWall, REG_SZ, (LPBYTE)szTiled, SIZEOF(TCHAR)*(lstrlen(szTiled)+1));
  578.         //
  579.         // Note: We do not write the Wallpaper Style string for older systems because we do not
  580.         // want to over-write what PlusPack writes. However, for newer Operating systems, we 
  581.         // want to write the WallpaperStyle also.
  582.         //
  583.         if(g_bRunOnMemphis || g_bRunOnNT5)
  584.         {
  585.             SHSetValue(HKEY_CURRENT_USER, lpszDeskcomp,
  586.                 c_szWallpaperStyle, REG_SZ, (LPBYTE)szWPStyle, SIZEOF(TCHAR)*(lstrlen(szWPStyle)+1));
  587.         }
  588.     
  589.         SHSetValue(HKEY_CURRENT_USER, lpszDeskcomp,
  590.                     c_szWallpaper, REG_SZ, (LPBYTE)_szSelectedWallpaper,
  591.                     SIZEOF(TCHAR)*(lstrlen(_szSelectedWallpaper)+1));
  592.     }
  593.     if(fNormalWallpaper = IsNormalWallpaper(_szSelectedWallpaper))
  594.     {
  595.         lstrcpyn(_szBackupWallpaper, _szSelectedWallpaper, ARRAYSIZE(_szBackupWallpaper));
  596.         GetWallpaperFileTime(_szSelectedWallpaper, &_ftWallpaperFileTime);
  597.     }
  598.     // Backup the "Old type" wallpaper's name here in the new location
  599.     // sothat we can detect when this gets changed by some other app.
  600.     SHSetValue(HKEY_CURRENT_USER, lpszDeskcomp,
  601.                 c_szBackupWallpaper, REG_SZ, (LPBYTE)_szBackupWallpaper,
  602.                 SIZEOF(TCHAR)*(lstrlen(_szBackupWallpaper)+1));
  603.     SHSetValue(HKEY_CURRENT_USER, lpszDeskcomp,
  604.                 c_szWallpaperTime, REG_BINARY, (LPBYTE)&_ftWallpaperFileTime,
  605.                 SIZEOF(_ftWallpaperFileTime));    
  606.     //
  607.     // Even if this wallpaper is not valid in normal desktop (i.e., even if it is not a .BMP),
  608.     // write it out in normal desktop registry area.
  609.     //
  610.     if (_fWallpaperDirty)
  611.     {
  612.         SHSetValue(HKEY_CURRENT_USER, c_szRegStrDesktop,
  613.                     c_szTileWall, REG_SZ, (LPBYTE)szTiled, SIZEOF(TCHAR)*(lstrlen(szTiled)+1));
  614.         //
  615.         // Note: We do not write the Wallpaper Style string for older systems because we do not
  616.         // want to over-write what PlusPack writes. However, for newer Operating systems, we 
  617.         // want to write the WallpaperStyle also.
  618.         //
  619.         if(g_bRunOnMemphis || g_bRunOnNT5)
  620.         {
  621.             SHSetValue(HKEY_CURRENT_USER, c_szRegStrDesktop,
  622.                         c_szWallpaperStyle, REG_SZ, (LPBYTE)szWPStyle, SIZEOF(TCHAR)*(lstrlen(szWPStyle)+1));
  623.         }
  624.         SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, 
  625.                     (fNormalWallpaper ? _szSelectedWallpaper : _szBackupWallpaper),
  626.                      SPIF_UPDATEINIFILE);
  627.     }
  628.     EXITPROC(2, "DS SaveWallpaper");
  629. }
  630. void THISCLASS::_SaveComponent(HKEY hkey, int iIndex, COMPONENTA *pcomp)
  631. {
  632.     ENTERPROC(2, "DS SaveComponent(hkey=%08X,iIndex=%d,pcomp=%08X)", hkey, iIndex, pcomp);
  633.     TCHAR szSubKey[8];
  634.     HKEY hkeySub;
  635.     wsprintf(szSubKey, TEXT("%d"), iIndex);
  636.     if (RegCreateKey(hkey, szSubKey, &hkeySub) == ERROR_SUCCESS)
  637.     {
  638.         pcomp->fDirty = FALSE; //Since we are saving in the registry, reset this!
  639.         //
  640.         // Write out the source string and Friendly name string.
  641.         //
  642.         RegSetValueEx(hkeySub, REG_VAL_COMP_SOURCE, 0, REG_SZ, (LPBYTE)pcomp->szSource, (lstrlen(pcomp->szSource)+1)*SIZEOF(TCHAR));
  643.         RegSetValueEx(hkeySub, REG_VAL_COMP_SUBSCRIBED_URL, 0, REG_SZ, (LPBYTE)pcomp->szSubscribedURL, (lstrlen(pcomp->szSubscribedURL)+1)*SIZEOF(TCHAR));
  644.         RegSetValueEx(hkeySub, REG_VAL_COMP_NAME, 0, REG_SZ, (LPBYTE)pcomp->szFriendlyName, (lstrlen(pcomp->szFriendlyName)+1)*SIZEOF(TCHAR));
  645.         //
  646.         // Compute and write out flags.
  647.         //
  648.         DWORD dwFlags = 0;
  649.         dwFlags |= pcomp->iComponentType;
  650.         if (pcomp->fChecked)
  651.         {
  652.             dwFlags |= COMP_SELECTED;
  653.         }
  654.         if (pcomp->fNoScroll)
  655.         {
  656.             dwFlags |= COMP_NOSCROLL;
  657.         }
  658.         RegSetValueEx(hkeySub, REG_VAL_COMP_FLAGS, 0, REG_DWORD, (LPBYTE)&dwFlags, SIZEOF(dwFlags));
  659.         //
  660.         // Write out the position.
  661.         //
  662.         RegSetValueEx(hkeySub, REG_VAL_COMP_POSITION, 0, REG_BINARY, (LPBYTE)&pcomp->cpPos, SIZEOF(pcomp->cpPos));
  663.         //  Write out the Current state
  664.         RegSetValueEx(hkeySub, REG_VAL_COMP_CURSTATE, 0, REG_DWORD, (LPBYTE)&pcomp->dwCurItemState, SIZEOF(pcomp->dwCurItemState));
  665.         //  Write out the Original State Info
  666.         RegSetValueEx(hkeySub, REG_VAL_COMP_ORIGINALSTATEINFO, 0, REG_BINARY, (LPBYTE)&pcomp->csiOriginal, SIZEOF(pcomp->csiOriginal));
  667.         
  668.         //  Write out the Restored State Info
  669.         RegSetValueEx(hkeySub, REG_VAL_COMP_RESTOREDSTATEINFO, 0, REG_BINARY, (LPBYTE)&pcomp->csiRestored, SIZEOF(pcomp->csiRestored));
  670.         RegCloseKey(hkeySub);
  671.     }
  672.     EXITPROC(2, "DS SaveComponent!");
  673. }
  674. void THISCLASS::_SaveComponents(void)
  675. {
  676.     ENTERPROC(2, "DS SaveComponents");
  677.     int i;
  678.     TCHAR lpszDeskcomp[MAX_PATH];
  679.     GetRegLocation(lpszDeskcomp, REG_DESKCOMP_COMPONENTS, _pszScheme);
  680.     //
  681.     // Delete the entire registry key.
  682.     //
  683.     SHDeleteKey(HKEY_CURRENT_USER, lpszDeskcomp);
  684.     //
  685.     // Recreate the registry key.
  686.     //
  687.     HKEY hkey;
  688.     if (RegCreateKey(HKEY_CURRENT_USER, lpszDeskcomp, &hkey) == ERROR_SUCCESS)
  689.     {
  690.         //
  691.         // Write out the version number.
  692.         //
  693.         DWORD dw = CUR_DESKHTML_VERSION;
  694.         RegSetValueEx(hkey, REG_VAL_COMP_VERSION, 0, REG_DWORD, (LPBYTE)(&dw), SIZEOF(dw));
  695.         dw = CUR_DESKHTML_MINOR_VERSION;
  696.         RegSetValueEx(hkey, REG_VAL_COMP_MINOR_VERSION, 0, REG_DWORD, (LPBYTE)(&dw), SIZEOF(dw));
  697.     
  698.         //
  699.         // Write out the general settings.
  700.         //
  701.         DWORD dwSettings = 0;
  702.         if (_co.fEnableComponents)
  703.         {
  704.             dwSettings |= COMPSETTING_ENABLE;
  705.         }
  706.         RegSetValueEx(hkey, REG_VAL_COMP_SETTINGS, 0, REG_DWORD, (LPBYTE)&dwSettings, SIZEOF(dwSettings));
  707.         if (_hdsaComponent)
  708.         {
  709.             //
  710.             // Write out the settings for each component
  711.             //
  712.             for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++)
  713.             {
  714.                 COMPONENTA * pcomp;
  715.                 if (pcomp = (COMPONENTA *)DSA_GetItemPtr(_hdsaComponent, i))
  716.                 {
  717.                     pcomp->dwID = i;
  718.                     _SaveComponent(hkey, i, pcomp);
  719.                 }
  720.             }
  721.         }
  722.         RegCloseKey(hkey);
  723.     }
  724.     EXITPROC(2, "DS SaveComponents");
  725. }
  726. void THISCLASS::_SavePattern(DWORD dwFlags)
  727. {
  728.     ENTERPROC(2, "DS SavePattern()");
  729.     if (_fPatternDirty && (dwFlags & SAVE_PATTERN_NAME))
  730.     {
  731.         //
  732.         // Write out the pattern to the registry and INI files.
  733.         //
  734.         SystemParametersInfo(SPI_SETDESKPATTERN, 0, _szSelectedPattern, SPIF_UPDATEINIFILE);
  735.     }
  736.     if (IsValidPattern(_szSelectedPattern) && (dwFlags & GENERATE_PATTERN_FILE))
  737.     {
  738.         //
  739.         // Write out the pattern as a BMP file for use in HTML.
  740.         //
  741.         TCHAR szBitmapFile[MAX_PATH];
  742.         GetPerUserFileName(szBitmapFile, ARRAYSIZE(szBitmapFile), PATTERN_FILENAME);
  743.         HANDLE hFileBitmap;
  744.         hFileBitmap = CreateFile(szBitmapFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  745.                                     FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, NULL);
  746.         if (hFileBitmap != INVALID_HANDLE_VALUE)
  747.         {
  748.             DWORD cbWritten;
  749.             BITMAPFILEHEADER bmfh = {0};
  750.             bmfh.bfType = 0x4D42;   // 'BM'
  751.             bmfh.bfSize = SIZEOF(BITMAPFILEHEADER) + SIZEOF(BITMAPINFOHEADER) + 2*SIZEOF(RGBQUAD) + 8*SIZEOF(DWORD);
  752.             bmfh.bfOffBits = SIZEOF(BITMAPFILEHEADER) + SIZEOF(BITMAPINFOHEADER) + 2*SIZEOF(RGBQUAD);
  753.             WriteFile(hFileBitmap, &bmfh, SIZEOF(bmfh), &cbWritten, NULL);
  754.             BITMAPINFOHEADER bmih = {0};
  755.             bmih.biSize = SIZEOF(BITMAPINFOHEADER);
  756.             bmih.biWidth = 8;
  757.             bmih.biHeight = 8;
  758.             bmih.biPlanes = 1;
  759.             bmih.biBitCount = 1;
  760.             bmih.biCompression = BI_RGB;
  761.             WriteFile(hFileBitmap, &bmih, SIZEOF(bmih), &cbWritten, NULL);
  762.             RGBQUAD argbTable[2] = {0};
  763.             DWORD rgb;
  764.             rgb = GetSysColor(COLOR_BACKGROUND);
  765.             argbTable[0].rgbBlue = GetBValue(rgb);
  766.             argbTable[0].rgbGreen = GetGValue(rgb);
  767.             argbTable[0].rgbRed = GetRValue(rgb);
  768.             rgb = GetSysColor(COLOR_WINDOWTEXT);
  769.             argbTable[1].rgbBlue = GetBValue(rgb);
  770.             argbTable[1].rgbGreen = GetGValue(rgb);
  771.             argbTable[1].rgbRed = GetRValue(rgb);
  772.             WriteFile(hFileBitmap, argbTable, SIZEOF(argbTable), &cbWritten, NULL);
  773.             DWORD adwBits[8];
  774.             PatternToDwords(_szSelectedPattern, adwBits);
  775.             WriteFile(hFileBitmap, adwBits, SIZEOF(adwBits), &cbWritten, NULL);
  776.             CloseHandle(hFileBitmap);
  777.         }
  778.     }
  779.     EXITPROC(2, "DS SavePattern!");
  780. }
  781. void THISCLASS::_WriteHtmlFromString(LPCTSTR psz)
  782. {
  783.     ENTERPROC(3, "DS WriteHtmlFromString(psz=>%s<)", psz);
  784.     DWORD cbWritten;
  785. #ifdef UNICODE
  786.     //if the string is unicode then convert it to ascii before writing it to
  787.     // the file.
  788.     char szBuf[INTERNET_MAX_URL_LENGTH];
  789.     int cch = SHUnicodeToAnsi(psz, szBuf, ARRAYSIZE(szBuf));
  790.     ASSERT(cch == lstrlenW(psz) + 1);       
  791.     WriteFile(_hFileHtml, szBuf, lstrlenA(szBuf), &cbWritten, NULL);
  792. #else
  793.     WriteFile(_hFileHtml, psz, lstrlen(psz), &cbWritten, NULL);
  794. #endif
  795.     EXITPROC(3, "DS WriteHtmlFromString!");
  796. }
  797. void THISCLASS::_WriteHtmlFromId(UINT uid)
  798. {
  799.     ENTERPROC(3, "DS WriteHtmlFromId(uid=%d)", uid);
  800.     TCHAR szBuf[INTERNET_MAX_URL_LENGTH];
  801.     MLLoadString(uid, szBuf, ARRAYSIZE(szBuf));
  802.     _WriteHtmlFromString(szBuf);
  803.     EXITPROC(3, "DS WriteHtmlFromId!");
  804. }
  805. void THISCLASS::_WriteHtmlFromIdF(UINT uid, ...)
  806. {
  807.     ENTERPROC(3, "DS WriteHtmlFromIdF(uid=%d,...)", uid);
  808.     TCHAR szBufFmt[INTERNET_MAX_URL_LENGTH];
  809.     TCHAR szBuf[INTERNET_MAX_URL_LENGTH];
  810.     MLLoadString(uid, szBufFmt, ARRAYSIZE(szBufFmt));
  811.     va_list arglist;
  812.     va_start(arglist, uid);
  813.     wvsprintf(szBuf, szBufFmt, arglist);
  814.     va_end(arglist);
  815.     _WriteHtmlFromString(szBuf);
  816.     EXITPROC(3, "DS WriteHtmlFromIdF!");
  817. }
  818. void THISCLASS::_WriteHtmlFromFile(LPCTSTR pszContents)
  819. {
  820.     CHAR szContents[MAX_PATH];
  821.     ENTERPROC(3, "DS WriteHtmlFromFile(pszContents=>%s<)", pszContents);
  822.     SHTCharToAnsi(pszContents, szContents, ARRAYSIZE(szContents));
  823.     HFILE hfileContents = _lopen(szContents, OF_READ);
  824.     if (hfileContents != HFILE_ERROR)
  825.     {
  826.         UINT cb;
  827.         BYTE rgbBuf[INTERNET_MAX_URL_LENGTH];
  828.         while ((cb = _lread(hfileContents, rgbBuf, SIZEOF(rgbBuf))) != HFILE_ERROR)
  829.         {
  830.             DWORD cbWritten;
  831.             WriteFile(_hFileHtml, rgbBuf, cb, &cbWritten, NULL);
  832.             if (cb < SIZEOF(rgbBuf))
  833.             {
  834.                 break;
  835.             }
  836.         }
  837.     }
  838.     _lclose(hfileContents);
  839.     EXITPROC(3, "DS WriteHtmlFromFile!");
  840. }
  841. void THISCLASS::_WriteHtmlFromHfile(HFILE hfile, int iOffsetStart, int iOffsetEnd)
  842. {
  843.     ENTERPROC(3, "DS WriteHtmlFromHfile(hfile=%08X,iOffsetStart=%d,iOffsetEnd=%d)", hfile, iOffsetStart, iOffsetEnd);
  844.     if (iOffsetStart != -1)
  845.     {
  846.         _llseek(hfile, iOffsetStart, FILE_BEGIN);
  847.     }
  848.     else
  849.     {
  850.         ASSERT(iOffsetEnd == -1);
  851.         iOffsetEnd = -1;
  852.     }
  853.     DWORD cbWrite = (iOffsetEnd == -1) ? 0xFFFFFFFF : (iOffsetEnd - iOffsetStart);
  854.     while (cbWrite)
  855.     {
  856.         CHAR rgbBuf[INTERNET_MAX_URL_LENGTH];
  857.         //
  858.         // Read a chunk.
  859.         //
  860.         DWORD cbTryRead = min(cbWrite, SIZEOF(rgbBuf));
  861.         DWORD cbActualRead = _lread(hfile, rgbBuf, cbTryRead);
  862.         if (cbActualRead != HFILE_ERROR)
  863.         {
  864.             //
  865.             // Write a chunk.
  866.             //
  867.             DWORD cbWritten;
  868.             WriteFile(_hFileHtml, rgbBuf, cbActualRead, &cbWritten, NULL);
  869.             if (cbActualRead < cbTryRead)
  870.             {
  871.                 //
  872.                 // End of file, all done.
  873.                 //
  874.                 break;
  875.             }
  876.             cbWrite -= cbActualRead;
  877.         }
  878.         else
  879.         {
  880.             //
  881.             // Error reading from file, all done.
  882.             //
  883.             break;
  884.         }
  885.     }
  886.     EXITPROC(3, "DS WriteHtmlFromHfile!");
  887. }
  888. int THISCLASS::_ScanForTag(HFILE hfile, int iOffsetStart, LPCSTR pszTagA)
  889. {
  890.     ENTERPROC(2, "DS ScanForTag(hfile=%08X,iOffsetStart=%d,pszTagA=>%s<)",
  891.     hfile, iOffsetStart, pszTagA);
  892.     int iRet = -1;
  893.     BOOL fDoneReading = FALSE;
  894.     int iOffset;
  895.     DWORD cchTag = lstrlenA(pszTagA);
  896.     _llseek(hfile, iOffsetStart, FILE_BEGIN);
  897.     iOffset = iOffsetStart;
  898.     DWORD cbBuf = 0;
  899.     while (!fDoneReading)
  900.     {
  901.         CHAR szBufA[INTERNET_MAX_URL_LENGTH];
  902.         //
  903.         // Fill in the buffer.
  904.         //
  905.         DWORD cbTryRead = SIZEOF(szBufA) - cbBuf - 1;
  906.         DWORD cbRead = _lread(_hfileHtmlBackground, &szBufA[cbBuf], cbTryRead);
  907.         if (cbRead != HFILE_ERROR)
  908.         {
  909.             cbBuf += cbRead;
  910.             //
  911.             // Terminate the string.
  912.             //
  913.             szBufA[cbBuf] = '';
  914.             //
  915.             // Scan for the tag.
  916.             //
  917.             LPSTR pszTagInBufA = StrStrIA(szBufA, pszTagA);
  918.             if (pszTagInBufA)
  919.             {
  920.                 //
  921.                 // Found the tag, compute the offset.
  922.                 //
  923.                 iRet = iOffset + pszTagInBufA - szBufA;
  924.                 fDoneReading = TRUE;
  925.             }
  926.             else if (cbRead < cbTryRead)
  927.             {
  928.                 //
  929.                 // Ran out of file without finding tag.
  930.                 //
  931.                 fDoneReading = TRUE;
  932.             }
  933.             else
  934.             {
  935.                 //
  936.                 // Compute how many bytes we want to throw away
  937.                 // from this buffer so we can read in more data.
  938.                 // We don't want to throw away all the bytes because
  939.                 // the tag we want may span two buffers.
  940.                 //
  941.                 DWORD cbSkip = cbBuf - cchTag;
  942.                 //
  943.                 // Advance the file offset.
  944.                 //
  945.                 iOffset += cbSkip;
  946.                 //
  947.                 // Reduce the buffer size.
  948.                 //
  949.                 cbBuf -= cbSkip;
  950.                 //
  951.                 // Move the kept bytes to the beginning of the buffer.
  952.                 //
  953.                 MoveMemory(szBufA, szBufA + cbSkip, cbBuf);
  954.             }
  955.         }
  956.         else
  957.         {
  958.             fDoneReading = TRUE;
  959.         }
  960.     }
  961.     EXITPROC(2, "DS ScanForTag=%d", iRet);
  962.     return iRet;
  963. }
  964. int THISCLASS::_ScanTagEntries(HFILE hfile, int iOffsetStart, TAGENTRY *pte, int cte)
  965. {
  966.     ENTERPROC(2, "DS ScanTagEntries(hfile=%08X,iOffsetStart=%d,pte=%08X,cte=%d)",
  967.     hfile, iOffsetStart, pte, cte);
  968.     int iRet = -1;
  969.     int i;
  970.     for (i=0; i<cte; i++,pte++)
  971.     {
  972.         iRet = _ScanForTag(hfile, iOffsetStart, pte->pszTag);
  973.         if (iRet != -1)
  974.         {
  975.             if (pte->fSkipPast)
  976.             {
  977.                 iRet += lstrlenA(pte->pszTag);
  978.             }
  979.             break;
  980.         }
  981.     }
  982.     EXITPROC(2, "DS ScanTagEntries=%d", iRet);
  983.     return iRet;
  984. }
  985. void THISCLASS::_GenerateHtmlHeader(void)
  986. {
  987.     ENTERPROC(2, "DS GenerateHtmlHeader()");
  988.     EnumMonitorsArea ema;
  989.     GetMonitorSettings(&ema);
  990.     RECT rcViewAreas[LV_MAX_WORKAREAS];  // WorkArea minus toolbar/tray areas
  991.     int nViewAreas = ARRAYSIZE(rcViewAreas);
  992.     // Get the ViewAreas
  993.     if (!GetViewAreas(rcViewAreas, &nViewAreas))
  994.     {
  995.         nViewAreas = 0;
  996.     }
  997.     //
  998.     // Write out the background and color.
  999.     //
  1000.     TCHAR szSelectedWallpaper[INTERNET_MAX_URL_LENGTH];
  1001.     // If the wallpaper does not have a directory specified (this may happen if other apps. change this value),
  1002.     // we have to figure it out.
  1003.     GetWallpaperWithPath(_szSelectedWallpaper, szSelectedWallpaper, ARRAYSIZE(szSelectedWallpaper));
  1004.     
  1005.     BOOL fValidWallpaper = GetFileAttributes(szSelectedWallpaper) != 0xFFFFFFFF;
  1006.     if (_fSingleItem || IsWallpaperPicture(szSelectedWallpaper) || !fValidWallpaper)
  1007.     {
  1008.         // To account for the vagaries of the desktop browser (it's TopLeft starts from the TopLeft
  1009.         // of the Desktop ViewArea instead of the TopLeft of the monitor, as might be expected)
  1010.         // which happens only in the case of one active monitor systems, we add the width of the
  1011.         // tray/toolbars to the co-ordinates of the DIV section of each monitor's wallpaper.
  1012.         int iLeft, iTop;
  1013.         if(nViewAreas == 1)
  1014.         {
  1015.             iLeft = rcViewAreas[0].left - ema.rcVirtualMonitor.left;
  1016.             iTop = rcViewAreas[0].top - ema.rcVirtualMonitor.top;
  1017.         }
  1018.         else
  1019.         {
  1020.             iLeft = 0;
  1021.             iTop = 0;
  1022.         }
  1023.         //
  1024.         // Write out the standard header.
  1025.         //
  1026.         UINT i;
  1027.         for (i=IDS_COMMENT_BEGIN; i<IDS_BODY_BEGIN; i++)
  1028.         {
  1029.             _WriteHtmlFromIdF(i);
  1030.         }
  1031.         //
  1032.         // Write out the body tag, with background bitmap.
  1033.         //
  1034.         DWORD rgbDesk;
  1035.         rgbDesk = GetSysColor(COLOR_DESKTOP);
  1036.         TCHAR szBitmapFile[MAX_PATH];
  1037.         GetPerUserFileName(szBitmapFile, ARRAYSIZE(szBitmapFile), PATTERN_FILENAME);
  1038.         if (!_fSingleItem && _szSelectedWallpaper[0] && fValidWallpaper)
  1039.         {
  1040.             TCHAR szWallpaperUrl[INTERNET_MAX_URL_LENGTH];
  1041.             DWORD cch = ARRAYSIZE(szWallpaperUrl);
  1042.             UrlCreateFromPath(szSelectedWallpaper, szWallpaperUrl, &cch, URL_INTERNAL_PATH);
  1043.             switch (_wpo.dwStyle)
  1044.             {
  1045.                 case WPSTYLE_TILE:
  1046.                     //
  1047.                     // Ignore the pattern, tile the wallpaper as background.
  1048.                     //
  1049.                     _WriteHtmlFromIdF(IDS_BODY_BEGIN2, szWallpaperUrl, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk));
  1050.                     break;
  1051.                 case WPSTYLE_CENTER:
  1052.                     if (IsValidPattern(_szSelectedPattern))
  1053.                     {
  1054.                         //
  1055.                         // Tile the pattern as the main background.
  1056.                         //
  1057.                         _WriteHtmlFromIdF(IDS_BODY_BEGIN2, szBitmapFile, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk));
  1058.                         if(_fBackgroundHtml)   // We are generating the HTML for preview
  1059.                         {
  1060.                             _WriteHtmlFromIdF(IDS_BODY_PATTERN_AND_WP, szWallpaperUrl);
  1061.                         }
  1062.                         else
  1063.                         {
  1064.                             //
  1065.                             // Write out a DIV section for a centered, untiled wallpaper.
  1066.                             //
  1067.                             // write it out for each monitor.
  1068.                             for(int i = 0; i < ema.iMonitors; i++)
  1069.                             {
  1070.                                 _WriteHtmlFromIdF(IDS_BODY_PATTERN_AND_WP2,
  1071.                                             ema.rcMonitor[i].left - ema.rcVirtualMonitor.left - iLeft,
  1072.                                             ema.rcMonitor[i].top - ema.rcVirtualMonitor.top - iTop,
  1073.                                             ema.rcMonitor[i].right - ema.rcMonitor[i].left,
  1074.                                             ema.rcMonitor[i].bottom - ema.rcMonitor[i].top,
  1075.                                             szWallpaperUrl);
  1076.                             }
  1077.                         }
  1078.                     }
  1079.                     else
  1080.                     {
  1081.                         //
  1082.                         // Write out a non-tiled, centered wallpaper as background.
  1083.                         //
  1084.                         if(_fBackgroundHtml)   // We are generating the HTML for preview
  1085.                         {
  1086.                             _WriteHtmlFromIdF(IDS_BODY_CENTER_WP, szWallpaperUrl, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk));
  1087.                         }
  1088.                         else
  1089.                         {
  1090.                             _WriteHtmlFromIdF(IDS_BODY_CENTER_WP2, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk));
  1091.                             // write it out for each monitor.
  1092.                             for(int i = 0; i < ema.iMonitors; i++)
  1093.                             {
  1094.                                 _WriteHtmlFromIdF(IDS_BODY_PATTERN_AND_WP2,
  1095.                                                     ema.rcMonitor[i].left - ema.rcVirtualMonitor.left - iLeft,
  1096.                                                     ema.rcMonitor[i].top - ema.rcVirtualMonitor.top - iTop,
  1097.                                                     ema.rcMonitor[i].right - ema.rcMonitor[i].left,
  1098.                                                     ema.rcMonitor[i].bottom - ema.rcMonitor[i].top,
  1099.                                                     szWallpaperUrl);
  1100.                             }
  1101.                         }
  1102.                     }
  1103.                     break;
  1104.                 case WPSTYLE_STRETCH:
  1105.                     //
  1106.                     // Ignore the pattern, create a DIV section of the wallpaper
  1107.                     // stretched to 100% of the screen.
  1108.                     //
  1109.                     _WriteHtmlFromIdF(IDS_BODY_BEGIN2, c_szNULL, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk));
  1110.                     if(_fBackgroundHtml)   // We are generating the HTML for preview
  1111.                     {
  1112.                         _WriteHtmlFromIdF(IDS_STRETCH_WALLPAPER, szWallpaperUrl);
  1113.                     }
  1114.                     else
  1115.                     {
  1116.                         // stretch it for each monitor.
  1117.                         for(int i = 0; i < ema.iMonitors; i++)
  1118.                         {
  1119.                             _WriteHtmlFromIdF(IDS_DIV_START3, ema.rcMonitor[i].left - ema.rcVirtualMonitor.left - iLeft,
  1120.                                                 ema.rcMonitor[i].top - ema.rcVirtualMonitor.top - iTop,
  1121.                                                 ema.rcMonitor[i].right - ema.rcMonitor[i].left,
  1122.                                                 ema.rcMonitor[i].bottom - ema.rcMonitor[i].top);
  1123.                             _WriteHtmlFromIdF(IDS_STRETCH_WALLPAPER, szWallpaperUrl);
  1124.                             _WriteHtmlFromId(IDS_DIV_END);
  1125.                         }
  1126.                     }
  1127.                     break;
  1128.             }
  1129.         }
  1130.         else
  1131.         {
  1132.             //
  1133.             // Ignore the wallpaper, generate either a tiled pattern
  1134.             // or solid color background.
  1135.             //
  1136.             _WriteHtmlFromIdF(IDS_BODY_BEGIN2, !_fSingleItem && IsValidPattern(_szSelectedPattern) ? szBitmapFile : c_szNULL, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk));
  1137.         }
  1138.     }
  1139.     else
  1140.     {
  1141.         CHAR szTempFileName[MAX_PATH];
  1142.         SHTCharToAnsi(szSelectedWallpaper, szTempFileName, ARRAYSIZE(szTempFileName));
  1143.         _hfileHtmlBackground = _lopen(szTempFileName, OF_READ);
  1144.         if (_hfileHtmlBackground != HFILE_ERROR)
  1145.         {
  1146.             //
  1147.             // Figure out where to insert the base href tag.
  1148.             //
  1149.             int iOffsetBase = 0;
  1150.             BOOL fUseBaseHref = (_ScanForTag(_hfileHtmlBackground, 0, "<BASE") == -1);
  1151.             if (fUseBaseHref)
  1152.             {
  1153.                 TAGENTRY rgteBase[] = {
  1154.                                         { "<HEAD>", TRUE, },
  1155.                                         { "<BODY", FALSE, },
  1156.                                         { "<HTML>", TRUE, },
  1157.                                       };
  1158.                 iOffsetBase = _ScanTagEntries(_hfileHtmlBackground, 0, rgteBase, ARRAYSIZE(rgteBase));
  1159.                 if (iOffsetBase == -1)
  1160.                 {
  1161.                     iOffsetBase = 0;
  1162.                 }
  1163.             }
  1164.             //
  1165.             // Figure out where to insert the components.
  1166.             //
  1167.             TAGENTRY rgteComponents[] = {
  1168.                                             { "</BODY>", FALSE, },
  1169.                                             { "</HTML>", FALSE, },
  1170.                                         };
  1171.             int iOffsetComponents = _ScanTagEntries(_hfileHtmlBackground, iOffsetBase, rgteComponents, ARRAYSIZE(rgteComponents));
  1172.             //
  1173.             // Write out the initial HTML up to the <HEAD> tag.
  1174.             //
  1175.             _WriteHtmlFromHfile(_hfileHtmlBackground, 0, iOffsetBase);
  1176.             //
  1177.             // Write out the base tag.
  1178.             //
  1179.             if (fUseBaseHref)
  1180.             {
  1181.                 //BASE tag must point to the base "URL". So, don't strip out the filename.
  1182.                 _WriteHtmlFromIdF(IDS_BASE_TAG, szSelectedWallpaper);
  1183.             }
  1184.             // Figure out where to insert the DIV clause
  1185.             TAGENTRY rgteBodyStart[] = {
  1186.                                         { "<BODY", FALSE, },
  1187.                                        };
  1188.             int iOffsetBodyStart = _ScanTagEntries(_hfileHtmlBackground, iOffsetBase, rgteBodyStart, ARRAYSIZE(rgteBodyStart));
  1189.             // Write out HTML until after the <BODY ......>
  1190.             if (iOffsetBodyStart == -1)
  1191.             {   // the <BODY> tag is not found, so we need to insert it.
  1192.                 // Copy over stuff until </HEAD>
  1193.                 TAGENTRY rgteHeadEnd[] = {
  1194.                                             { "</HEAD>", TRUE, },
  1195.                                          };
  1196.                 int iOffsetHeadEnd = _ScanTagEntries(_hfileHtmlBackground, iOffsetBase, rgteHeadEnd, ARRAYSIZE(rgteHeadEnd));
  1197.                 if(iOffsetHeadEnd != -1)
  1198.                 {
  1199.                     _WriteHtmlFromHfile(_hfileHtmlBackground, iOffsetBase, iOffsetHeadEnd);
  1200.                     iOffsetBase = iOffsetHeadEnd;
  1201.                 }
  1202.                 _WriteHtmlFromIdF(IDS_BODY_CENTER_WP2); // "<BODY>"
  1203.                 _fNeedBodyEnd = TRUE;
  1204.             }
  1205.             else
  1206.             {
  1207.                 TAGENTRY rgteBodyEnd[] = {
  1208.                                             { ">", TRUE, },
  1209.                                          };
  1210.                 int iOffsetBodyEnd = _ScanTagEntries(_hfileHtmlBackground, iOffsetBodyStart, rgteBodyEnd, ARRAYSIZE(rgteBodyEnd));
  1211.                 if (iOffsetBodyEnd == -1)
  1212.                 {   // An error in the HTML.
  1213.                     iOffsetBodyEnd = iOffsetBodyStart;  // BUGBUG: We need a better recovery idea.
  1214.                 }
  1215.                 _WriteHtmlFromHfile(_hfileHtmlBackground, iOffsetBase, iOffsetBodyEnd);
  1216.                 iOffsetBase = iOffsetBodyEnd;
  1217.             }
  1218.             // Insert the DIV clause
  1219.             if(ema.iMonitors > 1)
  1220.             {
  1221.                 if(nViewAreas <= 0 || rcViewAreas[0].right == rcViewAreas[0].left)
  1222.                 // The second case could occur on bootup
  1223.                 {
  1224.                     // Some error occured when getting the ViewAreas. Recover from the error by using the workarea.
  1225.                     // Get the workarea of the primary monitor, since HTML wallpapers are displayed only there.
  1226.                     HMONITOR hMonPrimary = GetPrimaryMonitor();
  1227.                     GetMonitorWorkArea(hMonPrimary, &rcViewAreas[0]);
  1228.                 }
  1229.                 _WriteHtmlFromIdF(IDS_DIV_START3, rcViewAreas[0].left - ema.rcVirtualMonitor.left,
  1230.                 rcViewAreas[0].top - ema.rcVirtualMonitor.top,
  1231.                 rcViewAreas[0].right - rcViewAreas[0].left, rcViewAreas[0].bottom - rcViewAreas[0].top);
  1232.             }
  1233.             //
  1234.             // Write out HTML from after <HEAD> tag to just before </BODY> tag.
  1235.             //
  1236.             _WriteHtmlFromHfile(_hfileHtmlBackground, iOffsetBase, iOffsetComponents);
  1237.             if(ema.iMonitors > 1)
  1238.             {
  1239.                 _WriteHtmlFromId(IDS_DIV_END);
  1240.             }
  1241.         }
  1242.         else
  1243.         {
  1244.             _hfileHtmlBackground = NULL;
  1245.         }
  1246.     }
  1247.     EXITPROC(2, "DS GenerateHtmlHeader!");
  1248. }
  1249. void THISCLASS::_WriteResizeable(COMPONENTA *pcomp)
  1250. {
  1251.     TCHAR   szResizeable[3];
  1252.     szResizeable[0] = TEXT('');
  1253.     //If Resize is set, then the comp is resizeable in both X and Y directions!
  1254.     if(pcomp->cpPos.fCanResize)
  1255.         lstrcat(szResizeable, TEXT("XY"));
  1256.     else
  1257.     {
  1258.         if(pcomp->cpPos.fCanResizeX)
  1259.             lstrcat(szResizeable, TEXT("X"));
  1260.         if(pcomp->cpPos.fCanResizeY)
  1261.             lstrcat(szResizeable, TEXT("Y"));
  1262.     }
  1263.     _WriteHtmlFromIdF(IDS_RESIZEABLE, szResizeable);
  1264. }
  1265. void THISCLASS::_GenerateHtmlPicture(COMPONENTA *pcomp)
  1266. {
  1267.     ENTERPROC(2, "DS GenerateHtmlPicture(pcomp=%08X)");
  1268.     //
  1269.     // Write out the image src HTML.
  1270.     //
  1271.     TCHAR szUrl[INTERNET_MAX_URL_LENGTH];
  1272.     DWORD cch=ARRAYSIZE(szUrl);
  1273.     if (FAILED(UrlCreateFromPath(pcomp->szSource, szUrl, &cch, 0)))
  1274.     {
  1275.         lstrcpy(szUrl, pcomp->szSource);
  1276.     }
  1277.     _WriteHtmlFromIdF(IDS_IMAGE_BEGIN2, pcomp->dwID, szUrl);
  1278.     //
  1279.     // Write out whether this image is resizeable or not!
  1280.     //
  1281.     _WriteResizeable(pcomp);
  1282.     //
  1283.     // Write out the URL that must be used for subscription purposes.
  1284.     //
  1285.     _WriteHtmlFromIdF(IDS_SUBSCRIBEDURL, pcomp->szSubscribedURL);
  1286.     //
  1287.     // Write out the image location HTML.
  1288.     //
  1289.     if ((pcomp->cpPos.dwWidth == COMPONENT_DEFAULT_WIDTH) &&
  1290.         (pcomp->cpPos.dwHeight == COMPONENT_DEFAULT_HEIGHT))
  1291.     {
  1292.         _WriteHtmlFromIdF(IDS_IMAGE_LOCATION, _fSingleItem ? 0 : pcomp->cpPos.iLeft, _fSingleItem ? 0 : pcomp->cpPos.iTop, pcomp->cpPos.izIndex);
  1293.     }
  1294.     else
  1295.     {
  1296.         _WriteHtmlFromIdF(IDS_IMAGE_SIZE, _fSingleItem ? 0 : pcomp->cpPos.iLeft, _fSingleItem ? 0 : pcomp->cpPos.iTop,
  1297.                             pcomp->cpPos.dwWidth, pcomp->cpPos.dwHeight, pcomp->cpPos.izIndex);
  1298.     }
  1299.     EXITPROC(2, "DS GenerateHtmlPicture!");
  1300. }
  1301. void THISCLASS::_GenerateHtmlDoc(COMPONENTA *pcomp)
  1302. {
  1303.     ENTERPROC(2, "DS GenerateHtmlDoc(pcomp=%08X)");
  1304.     //
  1305.     // Write out the DIV header HTML.
  1306.     //
  1307.     _WriteHtmlFromIdF(IDS_DIV_START2, pcomp->dwID);
  1308.     //
  1309.     // Write out whether this component is resizeable or not!
  1310.     //
  1311.     _WriteResizeable(pcomp);
  1312.     //
  1313.     // Write out the DIV location HTML.
  1314.     //
  1315.     _WriteHtmlFromIdF(IDS_DIV_SIZE, pcomp->cpPos.dwHeight, _fSingleItem ? 0 : pcomp->cpPos.iLeft,
  1316.     _fSingleItem ? 0 : pcomp->cpPos.iTop, pcomp->cpPos.dwWidth, pcomp->cpPos.izIndex);
  1317.     //
  1318.     // Extract the doc contents directly into the HTML.
  1319.     //
  1320.     _WriteHtmlFromFile(pcomp->szSource);
  1321.     //
  1322.     // Close the DIV section.
  1323.     //
  1324.     _WriteHtmlFromId(IDS_DIV_END);
  1325.     EXITPROC(2, "DS GenerateHtmlDoc!");
  1326. }
  1327. void THISCLASS::_GenerateHtmlSite(COMPONENTA *pcomp)
  1328. {
  1329.     ENTERPROC(2, "DS GenerateHtmlSite(pcomp=%08X)");
  1330.     //
  1331.     // Write out the frame src HTML.
  1332.     //
  1333.     TCHAR szUrl[INTERNET_MAX_URL_LENGTH];
  1334.     DWORD cch=ARRAYSIZE(szUrl);
  1335.     if (FAILED(UrlCreateFromPath(pcomp->szSource, szUrl, &cch, 0)))
  1336.     {
  1337.         lstrcpy(szUrl, pcomp->szSource);
  1338.     }
  1339.     _WriteHtmlFromIdF(IDS_IFRAME_BEGIN2, pcomp->dwID, szUrl, pcomp->fNoScroll ? TEXT("scrolling=no") : c_szNULL);
  1340.     //
  1341.     // Write out whether this Component is resizeable or not!
  1342.     //
  1343.     _WriteResizeable(pcomp);
  1344.     //
  1345.     // Write out the URL that must be used for subscription purposes.
  1346.     //
  1347.     _WriteHtmlFromIdF(IDS_SUBSCRIBEDURL, pcomp->szSubscribedURL);
  1348.     //
  1349.     // Write out the frame location HTML.
  1350.     //
  1351.     _WriteHtmlFromIdF(IDS_IFRAME_SIZE, _fSingleItem ? 0 : pcomp->cpPos.iLeft, _fSingleItem ? 0 : pcomp->cpPos.iTop,
  1352.     pcomp->cpPos.dwWidth, pcomp->cpPos.dwHeight, pcomp->cpPos.izIndex);
  1353.     EXITPROC(2, "DS GenerateHtmlSite!");
  1354. }
  1355. void THISCLASS::_GenerateHtmlControl(COMPONENTA *pcomp)
  1356. {
  1357.     ENTERPROC(2, "DS GenerateHtmlControl(pcomp=%08X)");
  1358.     ASSERT(pcomp);
  1359.     
  1360.     // Did the Administrator restrict "Channel UI"?
  1361.     if (SHRestricted2W(REST_NoChannelUI, NULL, 0))
  1362.     {
  1363.         TCHAR szChannelOCGUID[GUIDSTR_MAX];
  1364.         SHStringFromGUID(CLSID_ChannelOC, szChannelOCGUID, ARRAYSIZE(szChannelOCGUID));
  1365.         if (!StrCmpNI(pcomp->szSource, &(szChannelOCGUID[1]), lstrlen(pcomp->szSource)-3))
  1366.         {
  1367.             // Yes, so we need to hide the Channel Desktop Component.
  1368.             // Return here before we generate it.
  1369.             return;
  1370.         }        
  1371.     }
  1372.     
  1373.     //
  1374.     // Write out the control HTML.
  1375.     //
  1376.     // First the control header
  1377.     _WriteHtmlFromIdF(IDS_CONTROL_1, pcomp->dwID);
  1378.     // then the size
  1379.     _WriteHtmlFromIdF(IDS_CONTROL_2, pcomp->cpPos.dwHeight, _fSingleItem ? 0 : pcomp->cpPos.iLeft,
  1380.     _fSingleItem ? 0 : pcomp->cpPos.iTop, pcomp->cpPos.dwWidth, pcomp->cpPos.izIndex);
  1381.     //
  1382.     // Write out whether this Control is resizeable or not!
  1383.     //
  1384.     _WriteResizeable(pcomp);
  1385.     // Finally the rest of the control
  1386.     _WriteHtmlFromIdF(IDS_CONTROL_3, pcomp->szSource);
  1387.     EXITPROC(2, "DS GenerateHtmlControl!");
  1388. }
  1389. void THISCLASS::_GenerateHtmlComponent(COMPONENTA *pcomp)
  1390. {
  1391.     ENTERPROC(2, "DS GenerateHtmlComponent(pcomp=%08X)");
  1392.     switch(pcomp->iComponentType)
  1393.     {
  1394.         case COMP_TYPE_PICTURE:
  1395.             _GenerateHtmlPicture(pcomp);
  1396.             break;
  1397.         case COMP_TYPE_HTMLDOC:
  1398.             _GenerateHtmlDoc(pcomp);
  1399.             break;
  1400.         case COMP_TYPE_WEBSITE:
  1401.             _GenerateHtmlSite(pcomp);
  1402.             break;
  1403.         case COMP_TYPE_CONTROL:
  1404.             _GenerateHtmlControl(pcomp);
  1405.             break;
  1406.     }
  1407.     EXITPROC(2, "DS GenerateHtmlComponent!");
  1408. }
  1409. void THISCLASS::_GenerateHtmlFooter(void)
  1410. {
  1411.     ENTERPROC(2, "DS GenerateHtmlFooter()");
  1412.     //
  1413.     // Write out the deskmovr object.
  1414.     //
  1415.     if (!_fNoDeskMovr)
  1416.     {
  1417.         TCHAR szDeskMovrFile[MAX_PATH];
  1418.         GetWindowsDirectory(szDeskMovrFile, ARRAYSIZE(szDeskMovrFile));
  1419.         lstrcat(szDeskMovrFile, DESKMOVR_FILENAME);
  1420.         _WriteHtmlFromFile(szDeskMovrFile);
  1421.     }
  1422.     //
  1423.     // Write out the concluding HTML tags.
  1424.     //
  1425.     if (_hfileHtmlBackground)
  1426.     {
  1427.         if(_fNeedBodyEnd)
  1428.         {    // We had introduced the <BODY> tag by ourselves.
  1429.             _WriteHtmlFromId(IDS_BODY_END2);
  1430.             _fNeedBodyEnd = FALSE;
  1431.         }
  1432.         _WriteHtmlFromHfile(_hfileHtmlBackground, -1, -1);
  1433.         _lclose(_hfileHtmlBackground);
  1434.         _hfileHtmlBackground = NULL;
  1435.     }
  1436.     else
  1437.     {
  1438.         _WriteHtmlFromId(IDS_BODY_END);
  1439.     }
  1440.     EXITPROC(2, "DS GenerateHtmlFooter!");
  1441. }
  1442. void THISCLASS::_GenerateHtml(void)
  1443. {
  1444.     ENTERPROC(2, "DS GenerateHtml()");
  1445.     TCHAR szHtmlFile[MAX_PATH];
  1446.     //
  1447.     // Compute the filename.
  1448.     //
  1449.     szHtmlFile[0] = TEXT('');
  1450.     GetPerUserFileName(szHtmlFile, ARRAYSIZE(szHtmlFile), DESKTOPHTML_FILENAME);
  1451.     //
  1452.     // Recreate the file.
  1453.     //
  1454.     _hFileHtml = CreateFile(szHtmlFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  1455.                             FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, NULL);
  1456.     if (_hFileHtml != INVALID_HANDLE_VALUE)
  1457.     {
  1458.         _GenerateHtmlHeader();
  1459.         if (_co.fEnableComponents && _hdsaComponent && DSA_GetItemCount(_hdsaComponent))
  1460.         {
  1461.             int i;
  1462.             for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++)
  1463.             {
  1464.                 COMPONENTA comp;
  1465.                 comp.dwSize = sizeof(COMPONENTA);
  1466.                 if ((DSA_GetItem(_hdsaComponent, i, &comp) != -1) && (comp.fChecked))
  1467.                 {
  1468.                     _GenerateHtmlComponent(&comp);
  1469.                 }
  1470.             }
  1471.         }
  1472.         _GenerateHtmlFooter();
  1473.         CloseHandle(_hFileHtml);
  1474.     }
  1475.     
  1476.     SetDesktopFlags(COMPONENTS_DIRTY, 0);
  1477.     EXITPROC(2, "DS GenerateHtml!");
  1478. }
  1479. HRESULT THISCLASS::GenerateDesktopItemHtml(LPCWSTR pwszFileName, COMPONENT *pcomp, DWORD dwReserved)
  1480. {
  1481.     HRESULT hres = E_FAIL;
  1482.     ENTERPROC(2, "DS GenerateComponentHtml(pcomp=%08X)", pcomp);
  1483.     LPTSTR  pszFileName;
  1484.     //Check for the input parameters
  1485.     if(!pwszFileName || (pcomp && (pcomp->dwSize != SIZEOF(*pcomp)) && (pcomp->dwSize != SIZEOF(IE4COMPONENT))))
  1486.         return E_INVALIDARG;
  1487.     ASSERT(!dwReserved);     // These should be 0
  1488. #ifndef UNICODE
  1489.     CHAR    szFileName[MAX_PATH];
  1490.     SHUnicodeToAnsi(pwszFileName, szFileName, ARRAYSIZE(szFileName));
  1491.     pszFileName = szFileName;
  1492. #else
  1493.     pszFileName = (LPTSTR)pwszFileName;
  1494. #endif
  1495.     //
  1496.     // Create the file.
  1497.     //
  1498.     _hFileHtml = CreateFile(pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  1499.                                 FILE_ATTRIBUTE_NORMAL, NULL);
  1500.     if (_hFileHtml != INVALID_HANDLE_VALUE)
  1501.     {
  1502.         _fNoDeskMovr = TRUE;
  1503.         _fBackgroundHtml = TRUE;
  1504.         //Check if we need to add a component
  1505.         if(pcomp)
  1506.         {
  1507.             COMPONENTA  CompA;
  1508.             CompA.dwSize = sizeof(CompA);
  1509.             WideCompToMultiComp(pcomp, &CompA);
  1510.             _fSingleItem = TRUE;
  1511.             _GenerateHtmlHeader();
  1512.             _GenerateHtmlComponent(&CompA);
  1513.             _GenerateHtmlFooter();
  1514.             _fSingleItem = FALSE;
  1515.         }
  1516.         else
  1517.         {
  1518.             //generate just the header and the footer with proper
  1519.             // wallpaper and pattern info!
  1520.             _GenerateHtmlHeader();
  1521.             _GenerateHtmlFooter();
  1522.         }
  1523.         _fBackgroundHtml = FALSE;
  1524.         _fNoDeskMovr = FALSE;
  1525.         CloseHandle(_hFileHtml);
  1526.         hres = S_OK;
  1527.     }
  1528.     _hFileHtml = NULL;
  1529.     EXITPROC(2, "DS GenerateComponentHtml=%d", hres);
  1530.     return hres;
  1531. }
  1532. //
  1533. // AddUrl
  1534. //
  1535. //
  1536. HRESULT THISCLASS::AddUrl(HWND hwnd, LPCWSTR pszSourceW, LPCOMPONENT pcomp, DWORD dwFlags)
  1537. {
  1538.     LPTSTR pszExt;
  1539.     HRESULT fOkay = TRUE;
  1540.     BOOL fExtIsCdf,fPathIsUrl;
  1541.     BOOL fSubscribed = FALSE;
  1542.     COMPONENT   compLocal;
  1543.     COMPONENTA  compA;
  1544.     TCHAR szSource[INTERNET_MAX_URL_LENGTH];
  1545.     compLocal.dwSize = sizeof(compLocal);
  1546.     compA.dwSize = sizeof(compA);
  1547.     //Check for the input parameters.
  1548.     if(!pszSourceW || (pcomp && (pcomp->dwSize != SIZEOF(*pcomp)) && (pcomp->dwSize != SIZEOF(IE4COMPONENT))))
  1549.         return E_INVALIDARG;
  1550.     // Catch folks that call our API's to add components and prevent them from doing
  1551.     // so if the restriction is in place.
  1552.     if (SHIsRestricted(NULL, REST_NOADDDESKCOMP))
  1553.         return E_ACCESSDENIED;
  1554.     
  1555.     g_pActiveDesk = this;
  1556.     SHUnicodeToTChar(pszSourceW, szSource, ARRAYSIZE(szSource));
  1557.     pszExt = PathFindExtension(szSource);
  1558.     fExtIsCdf = lstrcmpi(pszExt, TEXT(".CDF")) == 0;
  1559.     fPathIsUrl = PathIsURL(szSource) && !UrlIsFileUrl(szSource);
  1560.     if (!pcomp)
  1561.     {
  1562.         pcomp = &compLocal;
  1563.         pcomp->dwSize = SIZEOF(*pcomp);
  1564.     }
  1565.     if (FindComponent(szSource))
  1566.     {
  1567.         if (dwFlags & ADDURL_SILENT)  
  1568.         {
  1569.             lstrcpy(compA.szSource, szSource);
  1570.             MultiCompToWideComp(&compA, pcomp);
  1571.             RemoveDesktopItem(pcomp, 0);
  1572.         }
  1573.         else  
  1574.         {
  1575.             // This is a long string. So,...
  1576.             TCHAR szMsg[512];
  1577.             TCHAR szMsg2[256];
  1578.             TCHAR szTitle[128];
  1579.             MLLoadString(IDS_COMP_EXISTS, szMsg, ARRAYSIZE(szMsg));
  1580.             MLLoadString(IDS_COMP_EXISTS_2, szMsg2, ARRAYSIZE(szMsg2));
  1581.             lstrcat(szMsg, szMsg2);
  1582.             MLLoadString(IDS_COMP_TITLE, szTitle, ARRAYSIZE(szTitle));
  1583.             MessageBox(hwnd, szMsg, szTitle, MB_OK);
  1584.             fOkay = FALSE;
  1585.         }
  1586.     }
  1587.     if (fOkay && CheckForExistingSubscription(szSource))
  1588.     {
  1589.         if ((dwFlags & ADDURL_SILENT) ||
  1590.             (ShellMessageBox(MLGetHinst(), hwnd, MAKEINTRESOURCE(IDS_COMP_SUBSCRIBED), 
  1591.                  MAKEINTRESOURCE(IDS_COMP_TITLE), MB_YESNO) == IDYES))
  1592.         {
  1593.             DeleteFromSubscriptionList(szSource);
  1594.         }
  1595.         else
  1596.         {
  1597.             fOkay = FALSE;
  1598.         }
  1599.     }
  1600.     if (fOkay)
  1601.     {
  1602.         if (fPathIsUrl || fExtIsCdf)
  1603.         {
  1604.             WCHAR szUrlW[INTERNET_MAX_URL_LENGTH];
  1605.             SHTCharToUnicode(szSource, szUrlW, ARRAYSIZE(szUrlW));
  1606.             HRESULT hr = ParseDesktopComponent(hwnd, szUrlW, pcomp);
  1607.             if (SUCCEEDED(hr))
  1608.             {
  1609.                 //
  1610.                 // Convert ed's wide thinggy to multi.
  1611.                 //
  1612.                 WideCompToMultiComp(pcomp, &compA);
  1613.                 PositionComponent(&compA.cpPos, compA.iComponentType);
  1614.                 fSubscribed = TRUE;
  1615.             }
  1616.             else if (!fExtIsCdf)
  1617.             {
  1618.                 //
  1619.                 // This is some non-CDF url.
  1620.                 //
  1621.                 CreateComponent(&compA, szSource);
  1622.             }
  1623.             else
  1624.             {
  1625.                 //
  1626.                 // We barfed on a CDF, bring up an error message.
  1627.                 //
  1628.                 if (!(dwFlags & ADDURL_SILENT))
  1629.                 {
  1630.                     ShellMessageBox(MLGetHinst(), hwnd, MAKEINTRESOURCE(IDS_COMP_BADURL), 
  1631.                                     MAKEINTRESOURCE(IDS_COMP_TITLE), MB_OK);
  1632.                 }
  1633.                 fOkay = FALSE;
  1634.             }
  1635.         }
  1636.         else
  1637.         {
  1638.             //
  1639.             // This is just some local file.
  1640.             //
  1641.             CreateComponent(&compA, szSource);
  1642.         }
  1643.     }
  1644.     if (fOkay && fPathIsUrl && !fSubscribed)
  1645.     {
  1646.         //
  1647.         // Run subscription code on URLs if CDF code hasn't already.
  1648.         //
  1649.         if (dwFlags & ADDURL_SILENT)
  1650.         {
  1651.             ISubscriptionMgr *psm;
  1652.             if (SUCCEEDED(CoCreateInstance(CLSID_SubscriptionMgr, NULL,
  1653.                             CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr, (void**)&psm)))
  1654.             {
  1655.                 WCHAR wzURL[INTERNET_MAX_URL_LENGTH];
  1656.                 LPWSTR pwzURL = wzURL;
  1657.                 //We need to zero init this structure except the cbSize field.
  1658.                 SUBSCRIPTIONINFO siDefault = {sizeof(SUBSCRIPTIONINFO)};
  1659.                 #ifndef UNICODE
  1660.                     SHAnsiToUnicode(szSource, wzURL, ARRAYSIZE(wzURL));
  1661.                 #else // UNICODE
  1662.                     pwzURL = szSource;
  1663.                 #endif // UNICODE
  1664.                 //This field is already initialized above.
  1665.                 //siDefault.cbSize = sizeof(siDefault);
  1666.                 psm->CreateSubscription(hwnd, pwzURL, pwzURL, CREATESUBS_NOUI, SUBSTYPE_DESKTOPURL, &siDefault);
  1667.                 psm->UpdateSubscription(pwzURL);
  1668.                 psm->Release();
  1669.             }
  1670.         }
  1671.         else
  1672.         {
  1673.             HRESULT hres = CreateSubscriptionsWizard(SUBSTYPE_DESKTOPURL, szSource, NULL, hwnd);
  1674.             if(!SUCCEEDED(hres))  //Some error, or the user chose Cancel - we should fail.
  1675.             {
  1676.                 ShellMessageBox(MLGetHinst(), hwnd, MAKEINTRESOURCE(IDS_COMP_BADSUBSCRIBE), 
  1677.                                 MAKEINTRESOURCE(IDS_COMP_TITLE), MB_OK);
  1678.             }
  1679.             fOkay = (hres == S_OK);    //could be S_FALSE, which means CreateSubscription was cancelled
  1680.             //so we don't display the above error, but we don't create the DTI
  1681.         }
  1682.     }
  1683.     MultiCompToWideComp(&compA, pcomp);
  1684.  
  1685.     if (fOkay)
  1686.     {
  1687.         AddDesktopItem(pcomp, 0);
  1688.         return S_OK;
  1689.     }
  1690.     else  
  1691.     {
  1692.         return E_FAIL;
  1693.     }
  1694. }
  1695. void THISCLASS::_SaveSettings(DWORD dwFlags)
  1696. {
  1697.     ENTERPROC(2, "DS SaveSettings()");
  1698.     if (dwFlags & AD_APPLY_SAVE)
  1699.     {
  1700.         // Don't ever modify the safemode settings
  1701.         TCHAR lpszDeskcomp[MAX_PATH];
  1702.         GetRegLocation(lpszDeskcomp, REG_DESKCOMP_GENERAL, _pszScheme);
  1703.         if (!StrStr(lpszDeskcomp, REG_DESKCOMP_SAFEMODE_SUFFIX))
  1704.         {
  1705.             //
  1706.             // Write out registry settings.
  1707.             //
  1708.             _SaveWallpaper();
  1709.             _SaveComponents();
  1710.             _SavePattern(SAVE_PATTERN_NAME);
  1711.         }
  1712.     };
  1713.     if (dwFlags & AD_APPLY_HTMLGEN)
  1714.     {
  1715.         //We need to generate the Patten.bmp file too!
  1716.         _SavePattern(GENERATE_PATTERN_FILE);
  1717.         //
  1718.         // Write out HTML file.
  1719.         //
  1720.         _GenerateHtml();
  1721.     }
  1722.     if (dwFlags & AD_APPLY_REFRESH)
  1723.     {
  1724.         HWND    hwndShell = GetShellWindow();
  1725.         //
  1726.         // Broadcast the world that the settings have changed.
  1727.         //
  1728.         SHELLSTATE ss = {0};
  1729.         SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE);
  1730.         BOOL fWasActiveDesktop = BOOLIFY(ss.fDesktopHTML);
  1731.         BOOL fIsActiveDesktop = BOOLIFY(_co.fActiveDesktop);
  1732.         if (fIsActiveDesktop != fWasActiveDesktop)
  1733.         {
  1734.             SendMessage(hwndShell, WM_WININICHANGE, SPI_SETDESKWALLPAPER, (LPARAM)TEXT("ToggleDesktop"));
  1735.             //Force a SHRefresh with this dummy call
  1736.             SHGetSetSettings(NULL, 0, TRUE);
  1737.         }
  1738.         else
  1739.         {
  1740.             SendMessage(hwndShell, WM_WININICHANGE, SPI_SETDESKWALLPAPER, 
  1741.                     (LPARAM)((dwFlags & AD_APPLY_BUFFERED_REFRESH) ? c_szBufferedRefresh : c_szRefreshDesktop));
  1742.         }
  1743.     }
  1744.     //
  1745.     // Data is no longer dirty.
  1746.     //
  1747.     _fDirty = FALSE;
  1748.     _fWallpaperDirty = FALSE;
  1749.     _fWallpaperChangedDuringInit = FALSE;
  1750.     _fPatternDirty = FALSE;
  1751.     EXITPROC(2, "DS SaveSettings!");
  1752. }
  1753. ULONG THISCLASS::AddRef(void)
  1754. {
  1755.     ENTERPROC(1, "DS AddRef()");
  1756.     _cRef++;
  1757.     EXITPROC(1, "DS AddRef=%d", _cRef);
  1758.     return _cRef;
  1759. }
  1760. HRESULT THISCLASS::ApplyChanges(DWORD dwFlags)
  1761. {
  1762.     HRESULT hres = E_FAIL;
  1763.     ENTERPROC(1, "DS Apply(dwFlags=%08X)", dwFlags);
  1764.     if (dwFlags & AD_APPLY_FORCE)
  1765.     {
  1766.         _fDirty = TRUE;
  1767.         _fWallpaperDirty = TRUE;
  1768.         _fPatternDirty = TRUE;
  1769.     }
  1770.     if (_fDirty || _fWallpaperChangedDuringInit)
  1771.     {
  1772.         _SaveSettings(dwFlags);
  1773.     }
  1774.     hres = S_OK;
  1775.     EXITPROC(1, "DS ApplyChanges=%d", hres);
  1776.     return hres;
  1777. }
  1778. ULONG THISCLASS::Release(void)
  1779. {
  1780.     UINT nRet = --_cRef;
  1781.     ENTERPROC(1, "DS Release()");
  1782.     if (_cRef == 0)
  1783.     {
  1784.         delete this;
  1785.     }
  1786.     EXITPROC(1, "DS Release=%d", nRet);
  1787.     return nRet;
  1788. }
  1789. THISCLASS::CActiveDesktop()
  1790. {
  1791.     _cRef = 1;
  1792.     _fNoDeskMovr = FALSE;
  1793.     _fBackgroundHtml = FALSE;
  1794.     DllAddRef();
  1795. }
  1796. THISCLASS::~CActiveDesktop()
  1797. {
  1798.     if (_hdsaComponent)
  1799.     {
  1800.         DSA_Destroy(_hdsaComponent);
  1801.     }
  1802.     if (_pszScheme)
  1803.     {
  1804.         LocalFree((HANDLE)_pszScheme);
  1805.     }
  1806.     DllRelease();
  1807. }
  1808. HRESULT THISCLASS::GetWallpaper(LPWSTR pwszWallpaper, UINT cchWallpaper, DWORD dwReserved)
  1809. {
  1810.     HRESULT hres = E_INVALIDARG;
  1811.     ENTERPROC(1, "DS GetWallpaper(pszWallpaper=%08X,cchWallpaper=%d)", pwszWallpaper, cchWallpaper);
  1812.     ASSERT(!dwReserved);     // These should be 0
  1813.     if (pwszWallpaper && cchWallpaper)
  1814.     {
  1815. #ifndef UNICODE
  1816.         MultiByteToWideChar(CP_ACP, 0, _szSelectedWallpaper, -1, pwszWallpaper, cchWallpaper);
  1817. #else
  1818.         StrCpyNW(pwszWallpaper, _szSelectedWallpaper, cchWallpaper);
  1819. #endif
  1820.         hres = S_OK;
  1821.     }
  1822.     else
  1823.     {
  1824.         TraceMsg(TF_WARNING, "DS GetWallpaper unable to return wallpaper");
  1825.     }
  1826.     EXITPROC(1, "DS GetWallpaper=%d", hres);
  1827.     return hres;
  1828. }
  1829. HRESULT THISCLASS::SetWallpaper(LPCWSTR pwszWallpaper, DWORD dwReserved)
  1830. {
  1831.     HRESULT hres = E_FAIL;
  1832.     LPCTSTR pszWallpaper;
  1833.     ASSERT(!dwReserved);     // These should be 0
  1834.     if (pwszWallpaper)
  1835.     {
  1836. #ifdef UNICODE
  1837.         pszWallpaper = pwszWallpaper;
  1838. #else
  1839.         TCHAR szWallpaper[INTERNET_MAX_URL_LENGTH];
  1840.         WideCharToMultiByte(CP_ACP, 0, pwszWallpaper, -1, szWallpaper, ARRAYSIZE(szWallpaper), NULL, NULL);
  1841.         pszWallpaper = szWallpaper;
  1842. #endif
  1843.         if (lstrcmp(_szSelectedWallpaper, pszWallpaper) != 0)
  1844.         {
  1845.             lstrcpyn(_szSelectedWallpaper, pszWallpaper, ARRAYSIZE(_szSelectedWallpaper));
  1846.             _fWallpaperDirty = TRUE;
  1847.             _fDirty = TRUE;
  1848.         }
  1849.         hres = S_OK;
  1850.     }
  1851.     ENTERPROC(1, "DS SetWallpaper(pszWallpaper=>%s<)", pwszWallpaper ? pszWallpaper : TEXT("(NULL)"));
  1852.     EXITPROC(1, "DS SetWallpaper=%d", hres);
  1853.     return hres;
  1854. }
  1855. HRESULT THISCLASS::GetWallpaperOptions(WALLPAPEROPT *pwpo, DWORD dwReserved)
  1856. {
  1857.     HRESULT hres = E_INVALIDARG;
  1858.     ENTERPROC(1, "DS GetWallpaperOptions(pwpo=%08X)");
  1859.     ASSERT(!dwReserved);     // These should be 0
  1860.     if ((pwpo) && (pwpo->dwSize == SIZEOF(*pwpo)))
  1861.     {
  1862.         *pwpo = _wpo;
  1863.         hres = S_OK;
  1864.     }
  1865.     else
  1866.     {
  1867.         TraceMsg(TF_WARNING, "DS GetWallpaperOptions could not return options");
  1868.     }
  1869.     EXITPROC(1, "DS GetWallpaperOptions=%d", hres);
  1870.     return hres;
  1871. }
  1872. HRESULT THISCLASS::SetWallpaperOptions(LPCWALLPAPEROPT pwpo, DWORD dwReserved)
  1873. {
  1874.     HRESULT hres = E_INVALIDARG;
  1875.     ENTERPROC(1, "DS SetWallpaperOptions(pwpo=%08X)", pwpo);
  1876.     ASSERT(!dwReserved);     // These should be 0
  1877.     if ((pwpo) && (pwpo->dwSize == SIZEOF(*pwpo)))
  1878.     {
  1879.         _wpo = *pwpo;
  1880.         _fWallpaperDirty = TRUE;
  1881.         _fDirty = TRUE;
  1882.         hres = S_OK;
  1883.     }
  1884.     else
  1885.     {
  1886.         TraceMsg(TF_WARNING, "DS SetWallpaperOptions could not set options");
  1887.     }
  1888.     EXITPROC(1, "DS SetWallpaperOptions=%d", hres);
  1889.     return hres;
  1890. }
  1891. HRESULT THISCLASS::GetPattern(LPWSTR pwszPattern, UINT cchPattern, DWORD dwReserved)
  1892. {
  1893.     HRESULT hres = S_OK;
  1894.     ENTERPROC(1, "DS GetPattern(psz=%08X,cch=%d)", pwszPattern, cchPattern);
  1895.     ASSERT(!dwReserved);     // These should be 0
  1896.     if(!pwszPattern || (cchPattern == 0))
  1897.         return (E_INVALIDARG);
  1898. #ifndef UNICODE
  1899.     MultiByteToWideChar(CP_ACP, 0, _szSelectedPattern, -1, pwszPattern, cchPattern);
  1900. #else
  1901.     StrCpyNW(pwszPattern, _szSelectedPattern, cchPattern);
  1902. #endif
  1903.     EXITPROC(1, "DS GetPattern=%d", hres);
  1904.     return hres;
  1905. }
  1906. HRESULT THISCLASS::SetPattern(LPCWSTR pwszPattern, DWORD dwReserved)
  1907. {
  1908.     HRESULT hres = E_FAIL;
  1909.     LPCTSTR pszPattern;
  1910.     ASSERT(!dwReserved);     // These should be 0
  1911.     if (pwszPattern)
  1912.     {
  1913. #ifndef UNICODE
  1914.         TCHAR szPattern[INTERNET_MAX_URL_LENGTH];
  1915.         SHUnicodeToAnsi(pwszPattern, szPattern, ARRAYSIZE(szPattern));
  1916.         pszPattern = szPattern;
  1917. #else
  1918.         pszPattern = pwszPattern;
  1919. #endif
  1920.         if (lstrcmp(_szSelectedPattern, pszPattern) != 0)
  1921.         {
  1922.             lstrcpyn(_szSelectedPattern, pszPattern, ARRAYSIZE(_szSelectedPattern));
  1923.             _fPatternDirty = TRUE;
  1924.             _fDirty = TRUE;
  1925.             hres = S_OK;
  1926.         }
  1927.     }
  1928.     ENTERPROC(1, "DS SetPattern(psz=>%s<)", pwszPattern ? pszPattern : TEXT("(NULL)"));
  1929.     EXITPROC(1, "DS SetPattern=%d", hres);
  1930.     return hres;
  1931. }
  1932. HRESULT THISCLASS::GetDesktopItemOptions(COMPONENTSOPT *pco, DWORD dwReserved)
  1933. {
  1934.     HRESULT hres = E_INVALIDARG;
  1935.     ENTERPROC(1, "DS GetComponentsOptions(pco=%08X)", pco);
  1936.     ASSERT(!dwReserved);     // These should be 0
  1937.     if (pco && (pco->dwSize == SIZEOF(*pco)))
  1938.     {
  1939.         *pco = _co;
  1940.         hres = S_OK;
  1941.     }
  1942.     else
  1943.     {
  1944.         TraceMsg(TF_WARNING, "DS GetComponentsOptions unable to return options");
  1945.     }
  1946.     EXITPROC(1, "DS GetComponentsOptions=%d", hres);
  1947.     return hres;
  1948. }
  1949. HRESULT THISCLASS::SetDesktopItemOptions(LPCCOMPONENTSOPT pco, DWORD dwReserved)
  1950. {
  1951.     HRESULT hres = E_INVALIDARG;
  1952.     ENTERPROC(1, "DS SetComponentsOptions(pco=%08X)", pco);
  1953.     ASSERT(!dwReserved);     // These should be 0
  1954.     if (pco && (pco->dwSize == SIZEOF(*pco)))
  1955.     {
  1956.         _co = *pco;
  1957.         _fDirty = TRUE;
  1958.         hres = S_OK;
  1959.     }
  1960.     else
  1961.     {
  1962.         TraceMsg(TF_WARNING, "DS SetComponentsOptions unable to set options");
  1963.     }
  1964.     EXITPROC(1, "DS SetComponentsOptions=%d", hres);
  1965.     return hres;
  1966. }
  1967. //
  1968. // SetStateInfo()
  1969. //      This function simply sets up the COMPSTATEINFO structure passed using the current
  1970. // position and size from the COMPPOS structure and the itemState passed.
  1971. //
  1972. void SetStateInfo(COMPSTATEINFO *pCompStateInfo, COMPPOS *pCompPos, DWORD dwItemState)
  1973. {
  1974.     pCompStateInfo->dwSize   = sizeof(*pCompStateInfo);
  1975.     pCompStateInfo->iLeft    = pCompPos->iLeft;
  1976.     pCompStateInfo->iTop     = pCompPos->iTop;
  1977.     pCompStateInfo->dwWidth  = pCompPos->dwWidth;
  1978.     pCompStateInfo->dwHeight = pCompPos->dwHeight;
  1979.     pCompStateInfo->dwItemState = dwItemState;
  1980. }
  1981. void ConvertCompStruct(COMPONENTA *pCompDest, COMPONENTA *pCompSrc, BOOL fPubToPriv)
  1982. {
  1983.     pCompDest -> dwID = pCompSrc -> dwID;
  1984.     pCompDest -> iComponentType = pCompSrc -> iComponentType;
  1985.     pCompDest -> fChecked = pCompSrc -> fChecked;
  1986.     pCompDest -> fDirty = pCompSrc -> fDirty;
  1987.     pCompDest -> fNoScroll = pCompSrc -> fNoScroll;
  1988.     pCompDest -> cpPos = pCompSrc -> cpPos;
  1989.     if(fPubToPriv)
  1990.     {
  1991.         COMPONENT *pComp = (COMPONENT *)pCompSrc;
  1992.         pCompDest->dwSize = sizeof(COMPONENTA);
  1993.         SHUnicodeToTChar(pComp->wszSource, pCompDest->szSource, ARRAYSIZE(pCompDest->szSource));
  1994.         SHUnicodeToTChar(pComp->wszFriendlyName, pCompDest->szFriendlyName, ARRAYSIZE(pCompDest->szFriendlyName));
  1995.         SHUnicodeToTChar(pComp->wszSubscribedURL, pCompDest->szSubscribedURL, ARRAYSIZE(pCompDest->szSubscribedURL));
  1996.         
  1997.         //Check to see if the public component is from IE4 app (old size)
  1998.         if(pCompSrc->dwSize == sizeof(COMPONENT))
  1999.         {
  2000.             // Since the dest component is the same size as the most current structure, all fields
  2001.             // are valid.
  2002.             // CAUTION: The following fields are at a different offset in public and private 
  2003.             // structures. So, you need to use pcomp instead of pCompSrc for example.
  2004.             pCompDest->dwCurItemState = pComp->dwCurItemState;
  2005.             pCompDest->csiOriginal = pComp->csiOriginal;
  2006.             pCompDest->csiRestored = pComp->csiRestored;
  2007.         }
  2008.         else
  2009.         {
  2010.             // Since the size did not match, we assume that this is an older structure.
  2011.             // Since the older struct does not have any Original and Restored sizes, let's copy 
  2012.             // the default values.
  2013.             IE4COMPONENT   *pIE4Comp = (IE4COMPONENT *)pCompSrc;
  2014.             pCompDest->dwCurItemState = IS_NORMAL;
  2015.             SetStateInfo(&pCompDest->csiOriginal, &pIE4Comp->cpPos, IS_NORMAL);
  2016.             SetStateInfo(&pCompDest->csiRestored, &pIE4Comp->cpPos, IS_NORMAL);
  2017.         }
  2018.     }
  2019.     else
  2020.     {
  2021.         COMPONENT *pComp = (COMPONENT *)pCompDest;
  2022.         
  2023.         if(pCompDest->dwSize != sizeof(COMPONENT))
  2024.             pCompDest->dwSize = sizeof(IE4COMPONENT);
  2025.         SHTCharToUnicode(pCompSrc->szSource, pComp->wszSource, ARRAYSIZE(pComp->wszSource));
  2026.         SHTCharToUnicode(pCompSrc->szFriendlyName, pComp->wszFriendlyName, ARRAYSIZE(pComp->wszFriendlyName));
  2027.         SHTCharToUnicode(pCompSrc->szSubscribedURL, pComp->wszSubscribedURL, ARRAYSIZE(pComp->wszSubscribedURL));
  2028.         
  2029.         //Check to see if the public component is from IE4 app (old size)
  2030.         if(pComp->dwSize == sizeof(COMPONENT))
  2031.         {
  2032.             // Since the dest component is the same size as the most current structure, all fields
  2033.             // are valid.
  2034.             // CAUTION: The following fields are at a different offset in public and private 
  2035.             // structures. So, you need to use pcomp instead of pCompDest for example.
  2036.             pComp->dwCurItemState = pCompSrc->dwCurItemState;
  2037.             pComp->csiOriginal = pCompSrc->csiOriginal;
  2038.             pComp->csiRestored = pCompSrc->csiRestored;
  2039.         }
  2040.         // else, the dest component is IE4COMPONENT and the additional fields are not there.
  2041.     }
  2042. }
  2043. HRESULT THISCLASS::_AddDTIWithUIPrivateA(HWND hwnd, LPCCOMPONENT pComp, DWORD dwFlags)
  2044. {
  2045.     HRESULT hres = E_FAIL;
  2046.     TCHAR szUrl[INTERNET_MAX_URL_LENGTH];
  2047.     int nScheme;
  2048. #ifdef UNICODE
  2049.     StrCpyN(szUrl, pComp->wszSource, ARRAYSIZE(szUrl));
  2050. #else // UNICODE
  2051.     SHUnicodeToAnsi(pComp->wszSource, szUrl, ARRAYSIZE(szUrl));
  2052. #endif // UNICODE
  2053.     nScheme = GetUrlScheme(szUrl);
  2054.     if ((URL_SCHEME_INVALID == nScheme) || (URL_SCHEME_UNKNOWN == nScheme))
  2055.     {
  2056.         TCHAR szFullyQualified[INTERNET_MAX_URL_LENGTH];
  2057.         DWORD cchSize = ARRAYSIZE(szFullyQualified);
  2058.         if (SUCCEEDED(ParseURLFromOutsideSource(szUrl, szFullyQualified, &cchSize, NULL)))
  2059.             nScheme = GetUrlScheme(szFullyQualified);
  2060.     }
  2061.     // Is this URL valid to subscribe to?  Did the caller specify they want use
  2062.     // to try to subscribe to it?
  2063.     if ((URL_SCHEME_FILE != nScheme) && (URL_SCHEME_ABOUT != nScheme) && 
  2064.         IsFlagSet(dwFlags, DTI_ADDUI_DISPSUBWIZARD) && hwnd)
  2065.     {
  2066.         //Create a subscription.
  2067.         hres = CreateSubscriptionsWizard(SUBSTYPE_DESKTOPURL, szUrl, NULL, hwnd);
  2068.         if(hres != S_OK)
  2069.         {
  2070.             return hres;
  2071.         }
  2072.     }
  2073.     //
  2074.     // Add the component to the registry.
  2075.     //
  2076.     // BUGBUG: This sucks because this function creates a second COM objects.  
  2077.     //         We need to Inline the functionality.
  2078.     hres = AddDesktopComponentNoUI(AD_APPLY_ALL, szUrl, NULL, pComp->iComponentType, 
  2079.         pComp->cpPos.iLeft, pComp->cpPos.iTop, pComp->cpPos.dwWidth, pComp->cpPos.dwHeight, NULL, TRUE) ? S_OK : E_FAIL;
  2080.     return hres;
  2081. }
  2082. #define     STC_DESKTOPCOMPONENT    0x00000002
  2083. EXTERN_C STDAPI_(HRESULT) SubscribeToCDF(HWND hwndParent, LPCWSTR pwzUrl, DWORD dwCDFTypes);
  2084. HRESULT THISCLASS::AddDesktopItemWithUI(HWND hwnd, LPCOMPONENT pComp, DWORD dwFlags)
  2085. {
  2086.     HRESULT hres = E_FAIL;
  2087.     // We need to support IE4 apps calling with the old component structure too!
  2088.     // We use the size field to detect IE4 v/s newer apps!
  2089.     if(!pComp || ((pComp->dwSize != SIZEOF(*pComp)) && (pComp->dwSize != SIZEOF(IE4COMPONENT))))
  2090.         return E_INVALIDARG;
  2091.     // Catch folks that call our API's to add components and prevent them from doing
  2092.     // so if the restriction is in place.
  2093.     if (SHIsRestricted(NULL, REST_NOADDDESKCOMP))
  2094.         return E_ACCESSDENIED;
  2095.     if (dwFlags & DTI_ADDUI_POSITIONITEM)
  2096.         PositionComponent(&pComp->cpPos, pComp->iComponentType);
  2097.     //
  2098.     // BUGBUG -- WhichPlatform just looks back at shell32. which we are.
  2099.     // So maybe the answer is always the same.  -raymondc
  2100.     //
  2101.     //
  2102.     // Check if we are in INTEGRATED mode
  2103.     //
  2104.     if(WhichPlatform() != PLATFORM_INTEGRATED)
  2105.     {
  2106.         if (hwnd)
  2107.         {
  2108.             //Desktop channels can't be added in BrowserOnly mode!
  2109.             ShellMessageBox(MLGetHinst(), hwnd, MAKEINTRESOURCE(IDS_CANTADD_BROWSERONLY), 
  2110.                                 MAKEINTRESOURCE(IDS_INTERNET_EXPLORER), MB_OK);
  2111.         }
  2112.         return E_FAIL;
  2113.     }
  2114.     // Check if the component already exists.
  2115.     BOOL fCompExists = FALSE;
  2116.     int cComp;
  2117.     GetDesktopItemCount(&cComp, 0);
  2118.     int i;
  2119.     COMPONENT comp;
  2120.     comp.dwSize = sizeof(COMPONENT);  //This needs to be initialized for ConvertCompStruc to work!
  2121.     COMPONENTA compA;
  2122.     TCHAR   szSource[INTERNET_MAX_URL_LENGTH];
  2123.     SHUnicodeToTChar(pComp->wszSource, szSource, ARRAYSIZE(szSource));
  2124.     for (i=0; i<cComp && !fCompExists; i++)
  2125.     {
  2126.         compA.dwSize = SIZEOF(compA);
  2127.         if(GetComponentPrivate(i, &compA)
  2128.                 && lstrcmpi(szSource, compA.szSource) == 0)
  2129.         {
  2130.             fCompExists = TRUE;
  2131.             ConvertCompStruct((COMPONENTA *)&comp, &compA, FALSE);
  2132.             break;
  2133.         }
  2134.     }
  2135.     BOOL fAskToInstall;
  2136.     if(ZoneCheckUrlW(pComp->wszSource, URLACTION_SHELL_INSTALL_DTITEMS, (PUAF_NOUI), NULL) == S_OK)
  2137.     {
  2138.         fAskToInstall = TRUE;
  2139.     }
  2140.     else
  2141.     {
  2142.         fAskToInstall = FALSE;
  2143.     }
  2144.     if (S_OK != ZoneCheckUrlW(pComp->wszSource, URLACTION_SHELL_INSTALL_DTITEMS, (hwnd ? (PUAF_FORCEUI_FOREGROUND | PUAF_WARN_IF_DENIED) : PUAF_NOUI), NULL))
  2145.         return E_ACCESSDENIED;
  2146.     BOOL fCompSubDeleted = FALSE;
  2147.     SUBSCRIPTIONINFO si = {sizeof(SUBSCRIPTIONINFO)};
  2148.     // si.bstrUserName = NULL;
  2149.     // si.bstrPassword = NULL;
  2150.     // si.bstrFriendlyName = NULL;
  2151.     //
  2152.     // Confirmation dialog.
  2153.     //
  2154.     if(hwnd)
  2155.     {
  2156.         if(fCompExists)
  2157.         {
  2158.             //Prompt the user to delete the existing ADI.
  2159.             // This is a long string. So,...
  2160.             TCHAR szMsg[512];
  2161.             TCHAR szMsg2[256];
  2162.             TCHAR szTitle[128];
  2163.             MLLoadString(IDS_COMP_EXISTS, szMsg, ARRAYSIZE(szMsg));
  2164.             MLLoadString(IDS_COMP_EXISTS_2, szMsg2, ARRAYSIZE(szMsg2));
  2165.             lstrcat(szMsg, szMsg2);
  2166.             MLLoadString(IDS_COMP_TITLE, szTitle, ARRAYSIZE(szTitle));
  2167.             MessageBox(hwnd, szMsg, szTitle, MB_OK);
  2168.             return E_FAIL;
  2169. #if 0
  2170.             comp.dwSize = SIZEOF(comp);
  2171.             //Prompt the user to reinstall the ADI.
  2172.             if(ShellMessageBox(MLGetHinst(), hwnd, MAKEINTRESOURCE(IDS_CONFIRM_ADI_REINSTALL), 
  2173.                 MAKEINTRESOURCE(IDS_COMP_TITLE), MB_YESNO) != IDYES)
  2174.             {
  2175.                 return E_FAIL; //User choses not to install this desktop component!
  2176.             }
  2177.             else
  2178.             {
  2179.                 ISubscriptionMgr *psm;
  2180.                 if (SUCCEEDED(hres = CoCreateInstance(CLSID_SubscriptionMgr, NULL,
  2181.                         CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr, (void**)&psm)))
  2182.                 {
  2183.                     si.cbSize = sizeof(si);
  2184.                     si.fUpdateFlags = SUBSINFO_ALLFLAGS;
  2185.                     //Backup and remove the subscription also
  2186.                     hres = psm->GetSubscriptionInfo(comp.wszSubscribedURL, &si);
  2187.                     if(SUCCEEDED(hres))
  2188.                     {
  2189.                         hres = RemoveDesktopItem(&comp, 0);
  2190.                         if(SUCCEEDED(hres))
  2191.                         {
  2192.                             psm->DeleteSubscription(comp.wszSubscribedURL, NULL);
  2193.                             ApplyChanges(AD_APPLY_SAVE);
  2194.                             fCompSubDeleted = TRUE;
  2195.                             // Set the new component to be enabled
  2196.                             pComp->fChecked = TRUE;
  2197.                         }
  2198.                     }
  2199.                     psm->Release();
  2200.                 }
  2201.                 else
  2202.                 {
  2203.                     TraceMsg(TF_WARNING, "CActiveDesktop::AddDesktopItemWithUI : CoCreateInstance for CLSID_SubscriptionMgr failed.");
  2204.                 }
  2205.             }
  2206. #endif
  2207.         }
  2208.         else if(fAskToInstall)
  2209.         {
  2210.             if(ShellMessageBox(MLGetHinst(), hwnd, MAKEINTRESOURCE(IDS_CONFIRM_ADD), 
  2211.                                 MAKEINTRESOURCE(IDS_INTERNET_EXPLORER), MB_YESNO) != IDYES)
  2212.             {
  2213.                 return E_FAIL; //User choses not to install this desktop component!
  2214.             }
  2215.         }
  2216.     }
  2217.     if(hwnd)
  2218.     {
  2219.         //If the active desktop is currently OFF, prompt the user to turn it on.
  2220.         SHELLSTATE ss = {0};
  2221.         SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE);
  2222.         if(!ss.fDesktopHTML)
  2223.         {
  2224.             if(ShellMessageBox(MLGetHinst(), hwnd, MAKEINTRESOURCE(IDS_CONFIRM_AD_ON), 
  2225.                             MAKEINTRESOURCE(IDS_INTERNET_EXPLORER), MB_YESNO) != IDNO)
  2226.             {
  2227.                 //The end-user agreed to turn ON the active desktop.
  2228.                 COMPONENTSOPT co;
  2229.                 co.dwSize = sizeof(COMPONENTSOPT);
  2230.                 GetDesktopItemOptions(&co, 0);
  2231.                 co.fActiveDesktop = TRUE;
  2232.                 SetDesktopItemOptions(&co, 0);
  2233.                 ApplyChanges(AD_APPLY_REFRESH);
  2234.             }
  2235.         }
  2236.     }
  2237.     hres = SubscribeToCDF(hwnd, pComp->wszSubscribedURL, STC_DESKTOPCOMPONENT);
  2238.     switch(hres)
  2239.     {
  2240.         case E_INVALIDARG:
  2241.         {
  2242.             // E_UNEXPECTED is returned from SubscribeToCDFUrlA() when the URL doesn't point to
  2243.             // a CDF file, so we assume it's a web page.
  2244.             hres = _AddDTIWithUIPrivateA(hwnd, pComp, dwFlags);
  2245.             if(hres != S_OK && fCompSubDeleted)    // Restore the old component
  2246.             {
  2247.                 hres = AddDesktopItem(&comp, 0);
  2248.                 if(SUCCEEDED(hres))
  2249.                 {
  2250.                     ISubscriptionMgr *psm;
  2251.                     if (SUCCEEDED(CoCreateInstance(CLSID_SubscriptionMgr, NULL,
  2252.                             CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr, (void**)&psm)))
  2253.                     {
  2254.                         si.cbSize = sizeof(si);
  2255.                         psm->CreateSubscription(hwnd, comp.wszSubscribedURL, si.bstrFriendlyName, CREATESUBS_NOUI, SUBSTYPE_DESKTOPURL, &si);
  2256.                         psm->Release();
  2257.                     }
  2258.                     else
  2259.                     {
  2260.                         TraceMsg(TF_WARNING, "CActiveDesktop::AddDesktopItemWithUI : CoCreateInstance for CLSID_SubscriptionMgr failed.");
  2261.                     }
  2262.                 }
  2263.             }
  2264.             ApplyChanges(AD_APPLY_ALL);
  2265.         }
  2266.         break;
  2267.         case E_ACCESSDENIED:
  2268.             // The file was a CDF but didn't contain Desktop Component Information
  2269.             if (hwnd)
  2270.             {
  2271.                 TCHAR szMsg[MAX_PATH];
  2272.                 TCHAR szTitle[MAX_PATH];
  2273.                 MLLoadString(IDS_ADDCOMP_ERROR_CDFNODTI, szMsg, ARRAYSIZE(szMsg));
  2274.                 MLLoadString(IDS_INTERNET_EXPLORER, szTitle, ARRAYSIZE(szTitle));
  2275.                 MessageBox(hwnd, szMsg, szTitle, MB_OK);
  2276.             }
  2277.             break;
  2278.         case E_UNEXPECTED:      
  2279.             // This was a CDF but it was misauthored.
  2280.             if (hwnd)
  2281.             {
  2282.                 TCHAR szMsg[MAX_PATH];
  2283.                 TCHAR szTitle[MAX_PATH];
  2284.                 MLLoadString(IDS_ADDCOMP_ERROR_CDFINALID, szMsg, ARRAYSIZE(szMsg));
  2285.                 MLLoadString(IDS_INTERNET_EXPLORER, szTitle, ARRAYSIZE(szTitle));
  2286.                 MessageBox(hwnd, szMsg, szTitle, MB_OK);
  2287.             }
  2288.             break;
  2289.         default:
  2290.             break;
  2291.     }
  2292.     if(fCompSubDeleted)
  2293.     {
  2294.         if(si.bstrUserName)
  2295.         {
  2296.             SysFreeString(si.bstrUserName);
  2297.         }
  2298.         if(si.bstrPassword)
  2299.         {
  2300.             SysFreeString(si.bstrPassword);
  2301.         }
  2302.         if(si.bstrFriendlyName)
  2303.         {
  2304.             SysFreeString(si.bstrFriendlyName);
  2305.         }
  2306.     }
  2307.     return hres;
  2308. }
  2309. HRESULT THISCLASS::AddDesktopItem(LPCCOMPONENT pComp, DWORD dwReserved)
  2310. {
  2311.     HRESULT     hres = E_FAIL;
  2312.     COMPONENTA  CompA;
  2313.     CompA.dwSize = SIZEOF(CompA);
  2314.     ASSERT(!dwReserved);     // These should be 0
  2315.     // We need to support IE4 apps calling with the old component structure too!
  2316.     // We use the size field to detect IE4 v/s newer apps!
  2317.     if(!pComp || ((pComp->dwSize != SIZEOF(*pComp)) && (pComp->dwSize != SIZEOF(IE4COMPONENT))))
  2318.         return E_INVALIDARG;
  2319.     // Catch folks that call our API's to add components and prevent them from doing
  2320.     // so if the restriction is in place.
  2321.     if (SHIsRestricted(NULL, REST_NOADDDESKCOMP))
  2322.         return E_ACCESSDENIED;
  2323.     // Convert the external structure to the internal format
  2324.     ConvertCompStruct(&CompA, (COMPONENTA *)pComp, TRUE);
  2325.  
  2326.     // If the component is already present, then fail the call!
  2327.     if(_FindComponentBySource(CompA.szSource, &CompA) > -1) 
  2328.         return hres;
  2329.     //Make sure that the COMPPOS size field is set before we add it!
  2330.     CompA.cpPos.dwSize = sizeof(COMPPOS);
  2331.     PositionComponent(&CompA.cpPos, CompA.iComponentType);
  2332.     //Make sure the this component's fDirty flag is off.
  2333.     CompA.fDirty = FALSE;
  2334.     if(AddComponentPrivate(&CompA, _dwNextID++))
  2335.     {
  2336.         // It might be cheaper to attempt to insert the component in the
  2337.         // correct z-order but it's less code to just call _SortAndRationalize
  2338.         // after the insertion is done.
  2339.         _SortAndRationalize();
  2340.         hres = S_OK;
  2341.     }
  2342.     return(hres);
  2343. }
  2344. BOOL THISCLASS::AddComponentPrivate(COMPONENTA *pcomp, DWORD dwID)
  2345. {
  2346.     BOOL fRet = FALSE;
  2347.     ENTERPROC(1, "DS AddComponent(pcomp=%08X)", pcomp);
  2348.     if (pcomp)
  2349.     {
  2350.         if (_hdsaComponent == NULL)
  2351.         {
  2352.             _hdsaComponent = DSA_Create(SIZEOF(COMPONENTA), DXA_GROWTH_CONST);
  2353.         }
  2354.         if (_hdsaComponent)
  2355.         {
  2356.             pcomp->dwID = dwID;
  2357.             if (DSA_AppendItem(_hdsaComponent, pcomp) != -1)
  2358.             {
  2359.                 _fDirty = TRUE;
  2360.                 fRet = TRUE;
  2361.             }
  2362.             else
  2363.             {
  2364.                 TraceMsg(TF_WARNING, "DS AddComponent unable to append DSA");
  2365.             }
  2366.         }
  2367.         else
  2368.         {
  2369.             TraceMsg(TF_WARNING, "DS AddComponent unable to create DSA");
  2370.         }
  2371.     }
  2372.     else
  2373.     {
  2374.         TraceMsg(TF_WARNING, "DS AddComponent unable to add a component");
  2375.     }
  2376.     EXITPROC(1, "DS AddComponent=%d", fRet);
  2377.     return fRet;
  2378. }
  2379. //
  2380. // This finds out if a given component already exists by comparing the szSource
  2381. // If so, it fills out the correct dwID and returns the index.
  2382. //
  2383. int THISCLASS::_FindComponentBySource(LPTSTR lpszSource, COMPONENTA *pComp)
  2384. {
  2385.     int iRet = -1;
  2386.     ENTERPROC(2, "DS FindComponentIdBySource(pComp=%8X)", pComp);
  2387.     if (_hdsaComponent)
  2388.     {
  2389.         int i;
  2390.         for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++)
  2391.         {
  2392.             COMPONENTA comp;
  2393.             comp.dwSize = sizeof(COMPONENTA);
  2394.             if (DSA_GetItem(_hdsaComponent, i, &comp) != -1)
  2395.             {
  2396.                 if (!lstrcmpi(comp.szSource, lpszSource))
  2397.                 {
  2398.                     *pComp = comp;
  2399.                     iRet = i;
  2400.                     break;
  2401.                 }
  2402.             }
  2403.             else
  2404.             {
  2405.                 TraceMsg(TF_WARNING, "DS FindComponentIndexByID unable to get a component");
  2406.             }
  2407.         }
  2408.     }
  2409.     EXITPROC(2, "DS FindComponentIdBySource=%d", iRet);
  2410.     return iRet;
  2411. }
  2412. int THISCLASS::_FindComponentIndexByID(DWORD dwID)
  2413. {
  2414.     int iRet = -1;
  2415.     ENTERPROC(2, "DS FindComponentIndexByID(dwID=%d)", dwID);
  2416.     if (_hdsaComponent)
  2417.     {
  2418.         int i;
  2419.         for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++)
  2420.         {
  2421.             COMPONENTA comp;
  2422.             comp.dwSize = sizeof(COMPONENTA);
  2423.             if (DSA_GetItem(_hdsaComponent, i, &comp) != -1)
  2424.             {
  2425.                 if (comp.dwID == dwID)
  2426.                 {
  2427.                     iRet = i;
  2428.                     break;
  2429.                 }
  2430.             }
  2431.             else
  2432.             {
  2433.                 TraceMsg(TF_WARNING, "DS FindComponentIndexByID unable to get a component");
  2434.             }
  2435.         }
  2436.     }
  2437.     EXITPROC(2, "DS FindComponent=%d", iRet);
  2438.     return iRet;
  2439. }
  2440. HRESULT THISCLASS:: GetDesktopItemByID(DWORD dwID, COMPONENT *pcomp, DWORD dwReserved)
  2441. {
  2442.     HRESULT hres = E_FAIL;
  2443.     ENTERPROC(1, "DS GetComponentByID(dwID=%d,pcomp=%08X)", dwID, pcomp);
  2444.     COMPONENTA  CompA;
  2445.     ASSERT(!dwReserved);     // These should be 0
  2446.     // We need to support IE4 apps calling with the old component structure too!
  2447.     // We use the size field to detect IE4 v/s newer apps!
  2448.     if(!pcomp || ((pcomp->dwSize != SIZEOF(*pcomp)) && (pcomp->dwSize != SIZEOF(IE4COMPONENT))))
  2449.         return E_INVALIDARG;
  2450.     if (pcomp)
  2451.     {
  2452.         int index = _FindComponentIndexByID(dwID);
  2453.         if (index != -1)
  2454.         {
  2455.             if (DSA_GetItem(_hdsaComponent, index, &CompA) != -1)
  2456.             {
  2457.                 hres = S_OK;
  2458.             }
  2459.             else
  2460.             {
  2461.                 TraceMsg(TF_WARNING, "DS GetComponentByID unable to get component");
  2462.             }
  2463.         }
  2464.         else
  2465.         {
  2466.             TraceMsg(TF_WARNING, "DS GetComponentByID unable to find component");
  2467.         }
  2468.     }
  2469.     else
  2470.     {
  2471.         TraceMsg(TF_WARNING, "DS GetComponentByID given NULL pcomp");
  2472.     }
  2473.     if(SUCCEEDED(hres))
  2474.     {
  2475.         MultiCompToWideComp(&CompA, pcomp);
  2476.     }
  2477.     EXITPROC(1, "DS GetComponentByID=%d", hres);
  2478.     return hres;
  2479. }
  2480. HRESULT THISCLASS::RemoveDesktopItem(LPCCOMPONENT pComp, DWORD dwReserved)
  2481. {
  2482.     COMPONENTA  CompA, CompToDelete;
  2483.     int         iIndex;
  2484.     HRESULT     hres = E_FAIL;
  2485.     ASSERT(!dwReserved);     // These should be 0
  2486.     // We need to support IE4 apps calling with the old component structure too!
  2487.     // We use the size field to detect IE4 v/s newer apps!
  2488.     if(!pComp || ((pComp->dwSize != SIZEOF(*pComp)) && (pComp->dwSize != SIZEOF(IE4COMPONENT))))
  2489.         return E_INVALIDARG;
  2490.     CompA.dwSize = SIZEOF(CompA);
  2491.     CompToDelete.dwSize = SIZEOF(CompToDelete);
  2492.     //Convert the struct to internal struct.
  2493.     ConvertCompStruct(&CompA, (COMPONENTA *)pComp, TRUE);
  2494.     // See if the component already exists.
  2495.     iIndex = _FindComponentBySource(CompA.szSource, &CompToDelete);
  2496.     if(iIndex > -1)
  2497.     {
  2498.         if(RemoveComponentPrivate(iIndex, &CompToDelete))
  2499.         {
  2500.             hres = S_OK;
  2501.         }
  2502.     }
  2503.     return(hres);
  2504. }
  2505. BOOL THISCLASS::RemoveComponentPrivate(int iIndex, COMPONENTA *pcomp)
  2506. {
  2507.     BOOL fRet = FALSE;
  2508.     ENTERPROC(1, "DS RemoveComponent(pcomp=%08X)", pcomp);
  2509.     if (_hdsaComponent)
  2510.     {
  2511.         if(iIndex == -1)
  2512.             iIndex = _FindComponentIndexByID(pcomp->dwID);
  2513.         if (iIndex != -1)
  2514.         {
  2515.             if (DSA_DeleteItem(_hdsaComponent, iIndex) != -1)
  2516.             {
  2517.                 _fDirty = TRUE;
  2518.                 fRet = TRUE;
  2519.             }
  2520.             else
  2521.             {
  2522.                 TraceMsg(TF_WARNING, "DS RemoveComponent could not remove an item");
  2523.             }
  2524.         }
  2525.         else
  2526.         {
  2527.             TraceMsg(TF_WARNING, "DS RemoveComponent could not find item to remove");
  2528.         }
  2529.     }
  2530.     else
  2531.     {
  2532.         TraceMsg(TF_WARNING, "DS RemoveComponent has no components to remove");
  2533.     }
  2534.     EXITPROC(1, "DS RemoveComponent=%d", fRet);
  2535.     return fRet;
  2536. }
  2537. HRESULT THISCLASS::_CopyComponent(COMPONENTA *pCompDest, COMPONENTA *pCompSrc, DWORD dwFlags)
  2538. {
  2539.     //Copy only those elements mentioned in the flag!
  2540. //    if(dwFlags & COMP_ELEM_ID)
  2541. //        pCompDest->dwID = pCompSrc->dwID;
  2542.     if(dwFlags & COMP_ELEM_TYPE)
  2543.         pCompDest-> iComponentType = pCompSrc->iComponentType;
  2544.     if(dwFlags & COMP_ELEM_CHECKED)
  2545.         pCompDest-> fChecked = pCompSrc->fChecked;
  2546.     if(dwFlags & COMP_ELEM_DIRTY)
  2547.         pCompDest-> fDirty = pCompSrc-> fDirty;
  2548.     if(dwFlags & COMP_ELEM_NOSCROLL)
  2549.         pCompDest-> fNoScroll = pCompSrc-> fNoScroll;
  2550.     if(dwFlags & COMP_ELEM_POS_LEFT)
  2551.         pCompDest-> cpPos.iLeft= pCompSrc->cpPos.iLeft;
  2552.     if(dwFlags & COMP_ELEM_POS_TOP)
  2553.         pCompDest-> cpPos.iTop= pCompSrc->cpPos.iTop;
  2554.     if(dwFlags & COMP_ELEM_SIZE_WIDTH)
  2555.         pCompDest-> cpPos.dwWidth= pCompSrc->cpPos.dwWidth;
  2556.     if(dwFlags & COMP_ELEM_SIZE_HEIGHT)
  2557.         pCompDest-> cpPos.dwHeight= pCompSrc->cpPos.dwHeight;
  2558.     if(dwFlags & COMP_ELEM_POS_ZINDEX)
  2559.         pCompDest-> cpPos.izIndex= pCompSrc->cpPos.izIndex;
  2560.     if(dwFlags & COMP_ELEM_SOURCE)
  2561.         lstrcpy(pCompDest->szSource, pCompSrc->szSource);
  2562.     if(dwFlags & COMP_ELEM_FRIENDLYNAME)
  2563.         lstrcpy(pCompDest->szFriendlyName, pCompSrc->szFriendlyName);
  2564.     if(dwFlags & COMP_ELEM_SUBSCRIBEDURL)
  2565.         lstrcpy(pCompDest->szSubscribedURL, pCompSrc->szSubscribedURL);
  2566.     return(S_OK);
  2567. }
  2568. HRESULT THISCLASS::GetDesktopItemBySource(LPCWSTR lpcwszSource, LPCOMPONENT pComp, DWORD dwFlags)
  2569. {
  2570.     COMPONENTA CompNew; 
  2571.     HRESULT   hres = E_FAIL;
  2572.     int       iIndex;
  2573.     //Passing a NULL to SHUnicodeToTChar causes a fault. So, let's fail it.
  2574.     if(lpcwszSource == NULL)
  2575.         return E_INVALIDARG;
  2576.         
  2577.     // We need to support IE4 apps calling with the old component structure too!
  2578.     // We use the size field to detect IE4 v/s newer apps!
  2579.     if(!pComp || ((pComp->dwSize != SIZEOF(*pComp)) && (pComp->dwSize != SIZEOF(IE4COMPONENT))))
  2580.         return E_INVALIDARG;
  2581.     CompNew.dwSize = sizeof(COMPONENTA);
  2582.     SHUnicodeToTChar(lpcwszSource, CompNew.szSource, ARRAYSIZE(CompNew.szSource));
  2583.     iIndex = _FindComponentBySource(CompNew.szSource, &CompNew);
  2584.     if(iIndex > -1)
  2585.     {
  2586.         MultiCompToWideComp(&CompNew, pComp);
  2587.         hres = S_OK;
  2588.     }
  2589.     return(hres);
  2590. }
  2591. HRESULT THISCLASS::ModifyDesktopItem(LPCCOMPONENT pComp, DWORD dwFlags)
  2592. {
  2593.     COMPONENTA  CompA, CompNew;
  2594.     HRESULT     hres = E_FAIL;
  2595.     int         iIndex = -1;
  2596.     // We need to support IE4 apps calling with the old component structure too!
  2597.     // We use the size field to detect IE4 v/s newer apps!
  2598.     if(!pComp || ((pComp->dwSize != SIZEOF(*pComp)) && (pComp->dwSize != SIZEOF(IE4COMPONENT))))
  2599.         return E_INVALIDARG;
  2600.     CompA.dwSize = sizeof(COMPONENTA);
  2601.     CompNew.dwSize = sizeof(COMPONENTA);
  2602.     //Convert public param structure to private param structure.
  2603.     ConvertCompStruct(&CompA, (COMPONENTA *)pComp, TRUE);
  2604.     //See if this component already exists.
  2605.     iIndex = _FindComponentBySource(CompA.szSource, &CompNew);
  2606.     if(iIndex > -1)
  2607.     {
  2608.         _CopyComponent(&CompNew, &CompA, dwFlags);
  2609.         if (dwFlags & (COMP_ELEM_POS_LEFT | COMP_ELEM_POS_TOP | COMP_ELEM_SIZE_WIDTH | COMP_ELEM_SIZE_HEIGHT))
  2610.             PositionComponent(&CompNew.cpPos, CompNew.iComponentType);
  2611.         CompNew.fDirty = TRUE; //Since the component is modified, we set the dirty bit!
  2612.         if(UpdateComponentPrivate(iIndex, &CompNew))
  2613.             hres = S_OK;
  2614.     }
  2615.     return(hres);
  2616. }
  2617. BOOL THISCLASS::UpdateComponentPrivate(int iIndex, COMPONENTA *pcomp)
  2618. {
  2619.     BOOL fRet = FALSE;
  2620.     ENTERPROC(1, "DS UpdateComponentPrivate(pcomp=%08X)", pcomp);
  2621.     if (_hdsaComponent)
  2622.     {
  2623.         if(iIndex == -1)
  2624.             iIndex = _FindComponentIndexByID(pcomp->dwID);
  2625.         if (iIndex != -1)
  2626.         {
  2627.             if (DSA_SetItem(_hdsaComponent, iIndex, pcomp) != -1)
  2628.             {
  2629.                 _fDirty = TRUE;
  2630.                 fRet = TRUE;
  2631.             }
  2632.             else
  2633.             {
  2634.                 TraceMsg(TF_WARNING, "DS UpdateComponent could not update an item");
  2635.             }
  2636.         }
  2637.         else
  2638.         {
  2639.             TraceMsg(TF_WARNING, "DS UpdateComponent could not find item to update");
  2640.         }
  2641.     }
  2642.     else
  2643.     {
  2644.         TraceMsg(TF_WARNING, "DS UpdateComponent has no components to update");
  2645.     }
  2646.     EXITPROC(1, "DS UpdateComponent=%d", fRet);
  2647.     return fRet;
  2648. }
  2649. HRESULT THISCLASS::GetDesktopItemCount(LPINT lpiCount, DWORD dwReserved)
  2650. {
  2651.     if(!lpiCount)
  2652.         return (E_INVALIDARG);
  2653.     *lpiCount = 0;
  2654.     ENTERPROC(1, "DS GetComponentsCount()");
  2655.     ASSERT(!dwReserved);     // These should be 0
  2656.     if (_hdsaComponent)
  2657.     {
  2658.         *lpiCount = DSA_GetItemCount(_hdsaComponent);
  2659.     }
  2660.     EXITPROC(1, "DS GetComponentsCount=%d", *lpiCount);
  2661.     return S_OK;
  2662. }
  2663. HRESULT THISCLASS::GetDesktopItem(int nComponent, COMPONENT *pComp, DWORD dwReserved)
  2664. {
  2665.     COMPONENTA  CompA;
  2666.     ASSERT(!dwReserved);     // These should be 0
  2667.     // We need to support IE4 apps calling with the old component structure too!
  2668.     // We use the size field to detect IE4 v/s newer apps!
  2669.     if((nComponent < 0) || !pComp || ((pComp->dwSize != SIZEOF(*pComp)) && (pComp->dwSize != SIZEOF(IE4COMPONENT))))
  2670.         return E_INVALIDARG;
  2671.     CompA.dwSize = sizeof(COMPONENTA);
  2672.     if(GetComponentPrivate(nComponent, &CompA))
  2673.     {
  2674.         //Convert the structure to the Public form.
  2675.         ConvertCompStruct((COMPONENTA *)pComp, &CompA, FALSE);
  2676.         return(S_OK);
  2677.     }
  2678.     else
  2679.         return(E_FAIL);
  2680. }
  2681. BOOL THISCLASS::GetComponentPrivate(int nComponent, COMPONENTA *pcomp)
  2682. {
  2683.     BOOL fRet = FALSE;
  2684.     ENTERPROC(1, "DS GetComponent(nComponent=%d,pcomp=%08X)", nComponent, pcomp);
  2685.     if (_hdsaComponent && pcomp && (nComponent < DSA_GetItemCount(_hdsaComponent)))
  2686.     {
  2687.         if (DSA_GetItem(_hdsaComponent, nComponent, pcomp) != -1)
  2688.         {
  2689.             fRet = TRUE;
  2690.         }
  2691.         else
  2692.         {
  2693.             TraceMsg(TF_WARNING, "DS GetComponent unable to get a component");
  2694.         }
  2695.     }
  2696.     else
  2697.     {
  2698.         TraceMsg(TF_WARNING, "DS GetComponent does not have a DSA");
  2699.     }
  2700.     EXITPROC(1, "DS GetComponent=%d", fRet);
  2701.     return fRet;
  2702. }
  2703. HRESULT CActiveDesktop::QueryInterface(REFIID riid, LPVOID *ppvObj)
  2704. {
  2705.     if(IsEqualIID(riid, IID_IActiveDesktop))
  2706.     {
  2707.         *ppvObj = (IActiveDesktop *)this;
  2708.         _Initialize();
  2709.     }
  2710.     else if (IsEqualIID(riid, IID_IUnknown))
  2711.     {
  2712.         *ppvObj = (IActiveDesktop *)this;
  2713.     }
  2714.     else if (IsEqualIID(riid, IID_IActiveDesktopP))
  2715.     {
  2716.         *ppvObj = (IActiveDesktopP *)this;
  2717.     }
  2718.     else if (IsEqualIID(riid, IID_IADesktopP2))
  2719.     {
  2720.         *ppvObj = (IADesktopP2 *)this;
  2721.     }
  2722.     else
  2723.     {
  2724.         *ppvObj = NULL;
  2725.         return E_NOINTERFACE;
  2726.     }
  2727.     AddRef();
  2728.     return S_OK;
  2729. }
  2730. // Helper function so that it's easy to create one internally
  2731. // Actually, it's not ver much help any more...
  2732. STDAPI CActiveDesktop_InternalCreateInstance(LPUNKNOWN * ppunk, REFIID riid)
  2733. {
  2734.     return CActiveDesktop_CreateInstance(NULL, riid, (void **)ppunk);
  2735. }
  2736. // Our class factory create instance code
  2737. STDAPI CActiveDesktop_CreateInstance(LPUNKNOWN punkOuter, REFIID riid, void **ppvOut)
  2738. {
  2739.     TraceMsg(TF_DESKSTAT, "CActiveDesktop- CreateInstance");
  2740.     CActiveDesktop *pad = new CActiveDesktop();
  2741.     if(pad)
  2742.     {
  2743.         HRESULT hres = pad->QueryInterface(riid, ppvOut);
  2744.         pad->Release();
  2745.         return hres;
  2746.     }
  2747.     *ppvOut = NULL;
  2748.     return E_OUTOFMEMORY;
  2749. }
  2750. #ifdef DEBUG
  2751. //
  2752. // BUGBUG - Move g_dwDeskStatTrace into ccshell.ini to prevent recompiles.
  2753. //
  2754. DWORD g_dwDeskStatTrace = 2;
  2755. static DWORD g_dwIndent = 0;
  2756. static const TCHAR c_szDotDot[] = TEXT("..");
  2757. #define MAX_INDENTATION_VALUE   0x10
  2758. void EnterProcDS(DWORD dwTraceLevel, LPSTR pszFmt, ...)
  2759. {
  2760.     TCHAR szFmt[1000];
  2761.     TCHAR szOutput[1000];
  2762.     va_list arglist;
  2763.     SHAnsiToTChar(pszFmt, szFmt, ARRAYSIZE(szFmt));
  2764.     if (dwTraceLevel <= g_dwDeskStatTrace)
  2765.     {
  2766.         szOutput[0] = TEXT('');
  2767.         for (DWORD i=0; i<g_dwIndent; i++)
  2768.         {
  2769.             lstrcat(szOutput, c_szDotDot);
  2770.         }
  2771.         va_start(arglist, pszFmt);
  2772.         wvsprintf(szOutput + lstrlen(szOutput), szFmt, arglist);
  2773.         va_end(arglist);
  2774.         TraceMsg(TF_DESKSTAT, "%s", szOutput);
  2775.         // This value can get out of hand if EnterProc and ExitProc
  2776.         // calls do not match. This can trash the stack.
  2777.         if(g_dwIndent < MAX_INDENTATION_VALUE)
  2778.             g_dwIndent++;
  2779.     }
  2780. }
  2781. void ExitProcDS(DWORD dwTraceLevel, LPSTR pszFmt, ...)
  2782. {
  2783.     TCHAR szFmt[1000];
  2784.     TCHAR szOutput[1000];
  2785.     va_list arglist;
  2786.     SHAnsiToTChar(pszFmt, szFmt, ARRAYSIZE(szFmt));
  2787.     if (dwTraceLevel <= g_dwDeskStatTrace)
  2788.     {
  2789.         // This can happen if the EnterProc and 
  2790.         // ExitProc calls do not match.
  2791.         if(g_dwIndent > 0)
  2792.             g_dwIndent--;
  2793.         szOutput[0] = TEXT('');
  2794.         for (DWORD i=0; i<g_dwIndent; i++)
  2795.         {
  2796.             lstrcat(szOutput, c_szDotDot);
  2797.         }
  2798.         va_start(arglist, pszFmt);
  2799.         wvsprintf(szOutput + lstrlen(szOutput), szFmt, arglist);
  2800.         va_end(arglist);
  2801.         TraceMsg(TF_DESKSTAT, "%s", szOutput);
  2802.     }
  2803. }
  2804. #endif
  2805. /*************************************************************************
  2806.  *
  2807.  *  IActiveDesktopP methods and helper functions
  2808.  *
  2809.  *  IActiveDesktopP is a private interface used to implement helper
  2810.  *  functionality that is used internally by the various shell binaries.
  2811.  *
  2812.  *  Notes:
  2813.  *      Getting an interface to IActiveDesktopP does not initialize the state
  2814.  *  of the object such that member functions are able to call IActiveDesktop
  2815.  *  member functions.  This is so that it is a more lightweight implementation
  2816.  *  and also simplifies the implementation of SetScheme.  If a subsequent QI for
  2817.  *  IActiveDesktop is performed then it will initialize properly and any member
  2818.  *  function can then be called.
  2819.  *
  2820.  *************************************************************************/
  2821. //
  2822. // SetScheme
  2823. //
  2824. // Used to set the current scheme that the object will read and write to
  2825. // when it is initialized.  This method must be called before a subsequent
  2826. // QI to IActiveDesktop is made.
  2827. //
  2828. HRESULT THISCLASS::SetScheme(LPCWSTR pwszSchemeName, DWORD dwFlags)
  2829. {
  2830.     LPTSTR pszSchemeName, pszAlloc;
  2831.     int icch;
  2832.     // Can't set the local scheme after we've been initialized...we can fix this
  2833.     // later if necessary but for now it's simplest this way.
  2834.     if (_fInitialized && (dwFlags & SCHEME_LOCAL))
  2835.         return E_FAIL;
  2836.     // Sanity checks
  2837.     if (!pwszSchemeName || ((icch = lstrlenW(pwszSchemeName)) > MAX_PATH - 1))
  2838.         return E_INVALIDARG;
  2839. #ifndef UNICODE
  2840.     CHAR    szName[MAX_PATH];
  2841.     SHUnicodeToAnsi(pwszSchemeName, szName, ARRAYSIZE(szName));
  2842.     pszSchemeName = szName;
  2843. #else
  2844.     pszSchemeName = (LPTSTR)pwszSchemeName;
  2845. #endif
  2846.     if (dwFlags & SCHEME_CREATE)
  2847.     {
  2848.         HRESULT hres;
  2849.         HKEY hkey, hkey2;
  2850.         if (ERROR_SUCCESS == (hres = RegCreateKey(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME_LOCATION, &hkey)))
  2851.         {
  2852.             if (ERROR_SUCCESS == (hres = RegCreateKey(hkey, pszSchemeName, &hkey2)))
  2853.                 RegCloseKey(hkey2);
  2854.             RegCloseKey(hkey);
  2855.         }
  2856.         if (FAILED(hres))
  2857.             return hres;
  2858.     }
  2859.     if (dwFlags & SCHEME_LOCAL)
  2860.     {
  2861.         // The local case is easy - just copy the string to our local variable,
  2862.         // it will be used when IActiveDesktop is initialized.
  2863.         if (!(pszAlloc = (LPTSTR)LocalAlloc(LPTR, (icch + 1) * sizeof(TCHAR))))
  2864.             return E_OUTOFMEMORY;
  2865.         if (_pszScheme)
  2866.             LocalFree((HANDLE)_pszScheme);
  2867.         _pszScheme = pszAlloc;
  2868.         lstrcpy(_pszScheme, pszSchemeName);
  2869.     }
  2870.     if (dwFlags & SCHEME_GLOBAL)
  2871.     {
  2872.         // Update the registry with the new global scheme value
  2873.         if (dwFlags & SCHEME_DISPLAY)
  2874.             SHSetValue(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME, REG_VAL_SCHEME_DISPLAY,
  2875.                         REG_SZ, (LPBYTE)pszSchemeName, (lstrlen(pszSchemeName) + 1) * sizeof(TCHAR));
  2876.         if (dwFlags & SCHEME_EDIT)
  2877.             SHSetValue(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME, REG_VAL_SCHEME_EDIT,
  2878.                         REG_SZ, (LPBYTE)pszSchemeName, (lstrlen(pszSchemeName) + 1) * sizeof(TCHAR));
  2879.     }
  2880.     if (dwFlags & (SCHEME_REFRESH | SCHEME_UPDATE))
  2881.     {
  2882.         DWORD dwUpdateFlags = AD_APPLY_FORCE | AD_APPLY_HTMLGEN | AD_APPLY_SAVE;
  2883.         if (dwFlags & SCHEME_REFRESH)
  2884.             dwUpdateFlags |= AD_APPLY_REFRESH;
  2885.         _Initialize();
  2886.         ApplyChanges(dwUpdateFlags);
  2887.     }
  2888.     return S_OK;
  2889. }
  2890. HRESULT GetGlobalScheme(LPWSTR pwszScheme, LPDWORD lpdwcchBuffer, DWORD dwFlags)
  2891. {
  2892.     DWORD dwType, dwcbBuffer;
  2893.     LONG lret;
  2894.     TCHAR szScheme[MAX_PATH];
  2895.     
  2896.     // Just pull it from the registry
  2897.     dwcbBuffer = sizeof(szScheme);
  2898.     if (ERROR_SUCCESS ==
  2899.         (lret = SHGetValue(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME,
  2900.                     (dwFlags & SCHEME_EDIT) ? REG_VAL_SCHEME_EDIT : REG_VAL_SCHEME_DISPLAY, &dwType,
  2901.                     (LPBYTE)szScheme, &dwcbBuffer)))
  2902.     {
  2903.         SHTCharToUnicode(szScheme, pwszScheme, *lpdwcchBuffer);
  2904.         // Fortunately, even Win95 implements lstrlenW
  2905.         *lpdwcchBuffer = lstrlenW(pwszScheme);
  2906.     }
  2907.     return (lret == ERROR_SUCCESS ? S_OK : E_FAIL);
  2908. }
  2909. //
  2910. // GetScheme
  2911. //
  2912. //
  2913. HRESULT THISCLASS::GetScheme(LPWSTR pwszSchemeName, LPDWORD lpdwcchBuffer, DWORD dwFlags)
  2914. {
  2915.     // Sanity checks
  2916.     if (!pwszSchemeName || *lpdwcchBuffer == 0)
  2917.         return E_INVALIDARG;
  2918.     if (dwFlags & SCHEME_LOCAL)
  2919.     {
  2920.         if (!_pszScheme)
  2921.         {
  2922.             HRESULT hres;
  2923.             // Special case if no local scheme has explicitly been selected yet.
  2924.             // The default scheme is the global display scheme in this case.
  2925.             if (SUCCEEDED(hres = GetGlobalScheme(pwszSchemeName, lpdwcchBuffer, SCHEME_DISPLAY)))
  2926.             {
  2927.                 hres = SetScheme(pwszSchemeName, SCHEME_LOCAL);
  2928.             }
  2929.             return hres;
  2930.         }
  2931. #ifdef UNICODE
  2932.         lstrcpyn(pwszSchemeName, _pszScheme, *lpdwcchBuffer);
  2933. #else
  2934.         SHAnsiToUnicode(_pszScheme, pwszSchemeName, *lpdwcchBuffer);
  2935. #endif
  2936.         *lpdwcchBuffer = lstrlenW(pwszSchemeName);
  2937.         return S_OK;
  2938.     }
  2939.     if (dwFlags & SCHEME_GLOBAL)
  2940.     {
  2941.         return GetGlobalScheme(pwszSchemeName, lpdwcchBuffer, dwFlags);
  2942.     }
  2943.     return E_INVALIDARG;
  2944. }
  2945. BOOL UpdateAllDesktopSubscriptions();
  2946. HRESULT THISCLASS::UpdateAllDesktopSubscriptions()
  2947. {
  2948.     ::UpdateAllDesktopSubscriptions();
  2949.     return S_OK;
  2950. }
  2951. //
  2952. // This function takes a pointer to the ActiveDesktop's ole obj, reads all the changes to be done
  2953. // from the registry and makes those changes to the various elements through dynamic HTML interfaces.
  2954. // NOTE: This function is implemented in NT5 version of shell32.dll. Since shdoc401.dll and 
  2955. // NT5's shell32.dll share the same IDL, I have to add the following dummy implementation here.
  2956. HRESULT CActiveDesktop::MakeDynamicChanges(IOleObject *pOleObj)
  2957. {
  2958.     return(E_NOTIMPL);
  2959. }
  2960. //
  2961. // SetSafeMode
  2962. //
  2963. // Either puts the active desktop in safemode or restores it to the previous
  2964. // scheme before safemode was entered.
  2965. //
  2966. HRESULT THISCLASS::SetSafeMode(DWORD dwFlags)
  2967. {
  2968.     //
  2969.     // Make sure we are in active desktop mode.
  2970.     //
  2971.     SHELLSTATE ss = {0};
  2972.     BOOL fSetSafeMode = (dwFlags & SSM_SET) != 0;
  2973.     SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE);
  2974.     if (ss.fDesktopHTML)
  2975.     {
  2976.         //
  2977.         // All we need to do is switch the "display" scheme to "safemode" in order to
  2978.         // go into safemode.  To go out, we just switch the "display" scheme back to the
  2979.         // previous "edit" scheme.
  2980.         //
  2981.         WCHAR wszEdit[MAX_PATH];
  2982.         WCHAR wszDisplay[MAX_PATH];
  2983.         DWORD dwcch = MAX_PATH;
  2984.         if (SUCCEEDED(GetScheme(wszEdit, &dwcch, SCHEME_GLOBAL | SCHEME_EDIT)))
  2985.         {
  2986.             dwcch = MAX_PATH;
  2987.             if (SUCCEEDED(GetScheme(wszDisplay, &dwcch, SCHEME_GLOBAL | SCHEME_DISPLAY)))
  2988.             {
  2989.                 BOOL fInSafeMode = (StrCmpW(wszDisplay, REG_DESKCOMP_SAFEMODE_SUFFIX_L) == 0);
  2990.                 if (fSetSafeMode != fInSafeMode)
  2991.                 {
  2992.                     LPWSTR lpwstr;
  2993.                     DWORD dwSchemeFlags = SCHEME_GLOBAL | SCHEME_DISPLAY;
  2994.                     if (dwFlags & SSM_REFRESH)
  2995.                         dwSchemeFlags |= SCHEME_REFRESH;
  2996.                     if (dwFlags & SSM_UPDATE)
  2997.                         dwSchemeFlags |= SCHEME_UPDATE;
  2998.                     lpwstr = fSetSafeMode ? REG_DESKCOMP_SAFEMODE_SUFFIX_L : wszEdit;
  2999.                     SetScheme(lpwstr, dwSchemeFlags);
  3000.                 }
  3001.             }
  3002.         }
  3003.     }
  3004.     return S_OK;
  3005. }
  3006. //
  3007. // EnsureUpdateHTML
  3008. //
  3009. // Ensures that the current html file present on the disk is in sync
  3010. // with the registry information for the current active desktop scheme.  If
  3011. // it is not in sync then a fresh copy of the file is generated from the
  3012. // registry for the current scheme.
  3013. //
  3014. HRESULT THISCLASS::EnsureUpdateHTML(void)
  3015. {
  3016.     DWORD dwFlags = 0;
  3017.     DWORD dwDataLength = sizeof(DWORD);
  3018.     DWORD dwType;
  3019.     LONG lRet;
  3020.     TCHAR lpszDeskcomp[MAX_PATH];
  3021.     DWORD dwRestrictUpdate;
  3022.     DWORD dwRestrict = SHRestricted2W(REST_NoChannelUI, NULL, 0);
  3023.     DWORD dwSize = SIZEOF(dwRestrictUpdate);
  3024.     BOOL  fComponentsDirty = FALSE;  //Assume that the components are NOT dirty!
  3025.     DWORD dwVersion;
  3026.     DWORD dwMinorVersion;
  3027.     BOOL  fStaleInfoInReg = FALSE;
  3028.     if (ERROR_SUCCESS != SHGetValue(HKEY_CURRENT_USER, REG_DESKCOMP_COMPONENTS_ROOT, REG_VAL_GENERAL_RESTRICTUPDATE, NULL, (LPVOID) &dwRestrictUpdate, &dwSize))
  3029.         dwRestrictUpdate = 0;
  3030.     GetRegLocation(lpszDeskcomp, REG_DESKCOMP_COMPONENTS, NULL);
  3031.     //See if this branch of registry is old
  3032.     if ((lRet = SHGetValue(HKEY_CURRENT_USER, (LPCTSTR)lpszDeskcomp, REG_VAL_COMP_VERSION, &dwType,
  3033.                             (LPBYTE)(&dwVersion), &dwDataLength)) == ERROR_SUCCESS)
  3034.     {
  3035.         if(dwVersion < CUR_DESKHTML_VERSION)
  3036.             fStaleInfoInReg = TRUE;
  3037.         else
  3038.         {
  3039.             //Major versions are equal. Check minor versions.
  3040.             if ((lRet = SHGetValue(HKEY_CURRENT_USER, (LPCTSTR)lpszDeskcomp, REG_VAL_COMP_MINOR_VERSION, &dwType,
  3041.                                     (LPBYTE)(&dwMinorVersion), &dwDataLength)) == ERROR_SUCCESS)
  3042.             {
  3043.                 if(dwMinorVersion != CUR_DESKHTML_MINOR_VERSION)
  3044.                     fStaleInfoInReg = TRUE;
  3045.             }
  3046.             else
  3047.                 fStaleInfoInReg = TRUE;
  3048.         }
  3049.     }
  3050.     else
  3051.         fStaleInfoInReg = TRUE;
  3052.     dwDataLength = SIZEOF(DWORD);
  3053.     //Check the dirty bit to see if we need to re-generate the desktop html
  3054.     if ((lRet = SHGetValue(HKEY_CURRENT_USER, (LPCTSTR)lpszDeskcomp, REG_VAL_COMP_GENFLAGS, &dwType,
  3055.                             (LPBYTE)(&dwFlags), &dwDataLength)) == ERROR_SUCCESS)
  3056.     {
  3057.         if (IsFlagSet(dwFlags, COMPONENTS_DIRTY))
  3058.             fComponentsDirty = TRUE;
  3059.     }
  3060.     TCHAR   szDesktopFile[MAX_PATH];
  3061.     GetPerUserFileName(szDesktopFile, ARRAYSIZE(szDesktopFile), DESKTOPHTML_FILENAME);
  3062.     if (fComponentsDirty ||
  3063.          fStaleInfoInReg ||
  3064.          (dwRestrictUpdate != dwRestrict) ||
  3065.          (!PathFileExists(szDesktopFile)))  //See if the file exists!
  3066.     {
  3067.         _Initialize();
  3068.         // NOTE #1: The above initialization would have changed the Z-order because of
  3069.         // SortAndRationalize and so we need to APPLY_SAVE here.
  3070.         // Warning: APPLY_SAVE changes the dwID field of components. This should not
  3071.         // be a problem because we do this just before generating a new HTML file.
  3072.         // NOTE #2: Do NOT use AD_APPLY_FORCE here. That sets the _fPatternDirty too and
  3073.         // that causes a SystemParametersInfo() call which results in WM_SYSCOLORCHANGE
  3074.         // and this causes a refresh. So, we set the dirty bit explicitly here.
  3075.         _fDirty = TRUE;  // See Note#2 above.
  3076.         ApplyChanges(AD_APPLY_SAVE | AD_APPLY_HTMLGEN);
  3077.         lRet = ERROR_SUCCESS;
  3078.         if (dwRestrictUpdate != dwRestrict)
  3079.             SHSetValue(HKEY_CURRENT_USER, REG_DESKCOMP_COMPONENTS_ROOT, REG_VAL_GENERAL_RESTRICTUPDATE, NULL, (LPVOID) &dwRestrict, SIZEOF(dwRestrict));
  3080.     }
  3081.     return (lRet == ERROR_SUCCESS ? S_OK : E_FAIL);
  3082. }
  3083. //
  3084. //  ReReadWallpaper()
  3085. //      If the wallpaper was read when the active desktop was disabled, we would have read it from
  3086. //  the old location. Now, if the active desktop is turned ON, then we need to re-read the wallpaper
  3087. //  from the new location. We need to do this iff the wallpaper has not been changed in the mean-while
  3088. //
  3089. HRESULT THISCLASS::ReReadWallpaper(void)
  3090. {
  3091.     if((!_fDirty) || (!_co.fActiveDesktop))  //If nothing has changed OR if active desktop is OFF, 
  3092.         return(S_FALSE);                        // then nothing to do!
  3093.     //ActiveDesktop is ON in our object. Read current shell state.
  3094.     SHELLSTATE ss = {0};
  3095.     
  3096.     SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE);
  3097.     if (ss.fDesktopHTML)
  3098.         return(S_FALSE);        // Active Desktop state hasn't changed. So, nothing to do!
  3099.     //So, Active desktop was originally OFF and now it is turned ON.
  3100.     //If if someone changed the wallpaper, we should not mess with it.
  3101.     if(_fWallpaperDirty || _fWallpaperChangedDuringInit)
  3102.         return(S_FALSE); 
  3103.     // No one has changed the wallpaper. So, we must re-read it from the new wallpaper location
  3104.     // sothat we get the correct wallpaper for the active desktop mode.
  3105.     _ReadWallpaper(TRUE);
  3106.     return(S_OK);
  3107. }
  3108. //
  3109. //  GetADObjectFlags()
  3110. //
  3111. //      Get the Active Desktop object's internal flags
  3112. //
  3113. HRESULT THISCLASS::GetADObjectFlags(LPDWORD lpdwFlags, DWORD dwMask)
  3114. {
  3115.     ASSERT(lpdwFlags);
  3116.     
  3117.     *lpdwFlags = 0; //Init the flags
  3118.     
  3119.     if((dwMask & GADOF_DIRTY) && _fDirty)
  3120.         *lpdwFlags |= GADOF_DIRTY;
  3121.     return(S_OK);
  3122. }
  3123. #endif