Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
dutil.cpp
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 78k
Category:
Windows Kernel
Development Platform:
Visual C++
- #include "stdafx.h"
- #include "icwcfg.h"
- #pragma hdrstop
- EXTERN_C const TCHAR c_szControlIni[] = TEXT("control.ini");
- EXTERN_C const TCHAR c_szPatterns[] = TEXT("patterns");
- EXTERN_C const TCHAR c_szBackgroundPreview2[] = TEXT("BackgroundPreview2");
- EXTERN_C const TCHAR c_szComponentPreview[] = TEXT("ComponentPreview");
- EXTERN_C const TCHAR c_szRegDeskHtmlProp[] = TEXT("Software\Microsoft\Windows\CurrentVersion\Controls Folder\Display\shellex\PropertySheetHandlers\DeskHtmlExt");
- EXTERN_C const TCHAR c_szWallPaperDir[] = TEXT("WallPaperDir");
- // 98/10/01 vtan: Added local function prototypes.
- // Some of these functions are commented out. The linker may not be smart
- // enough to strip the dead code so this is done manually. These prototypes
- // will allow the code to compile but it won't link. If you get linker
- // errors, uncomment the desired function and recompile. It should then link.
- // Point arithmetic
- void SetPt (POINT& pt, LONG x, LONG y);
- void OffsetPt (POINT& pt, LONG dh, LONG dv);
- // Virtual screen calculation
- BOOL CALLBACK GDIToTridentEnumProc (HMONITOR hMonitor, HDC hDC, RECT* rcMonitor, LPARAM lpUserData);
- void CalculateVirtualScreen (RECT& rcVirtualScreen);
- // GDI point to Trident point co-ordinate mapping
- void GDIToTrident (int& leftCoordinate, int& topCoordinate);
- void GDIToTrident (POINT& pt);
- void GDIToTrident (RECT& r);
- void GDIToTrident (HRGN hRgn);
- void TridentToGDI (int& leftCoordinate, int& topCoordinate);
- void TridentToGDI (POINT& pt);
- void TridentToGDI (RECT& r);
- void TridentToGDI (HRGN hRgn);
- // Component position validation
- BOOL CALLBACK ValidateComponentPositionEnumProc (HMONITOR hMonitor, HDC hdcMonitor, RECT* r, LPARAM lParam);
- void GetNextComponentPosition (COMPPOS *pcp)
- {
- int iScreenWidth, iScreenHeight, iBorderSize;
- DWORD dwComponentPosition, dwComponentLayer, dwRegDataScratch;
- HKEY hKey;
- RECT rcScreen;
- TCHAR lpszDeskcomp[MAX_PATH];
- TBOOL(SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScreen, false));
- // 99/04/13 vtan: A result of zero-width or zero-height occurred on a machine.
- // Make a defensive stand against this and assert that this happened but also
- // handle this cause so that division by zero doesn't happen.
- iScreenWidth = rcScreen.right - rcScreen.left;
- iScreenHeight = rcScreen.bottom - rcScreen.top;
- iBorderSize = GetSystemMetrics(SM_CYSMCAPTION);
- ASSERT(iScreenWidth > 0); // get vtan
- ASSERT(iScreenHeight > 0); // if any of
- ASSERT(iBorderSize > 0); // these occur
- if ((iScreenWidth <= 0) || (iScreenHeight <= 0) || (iBorderSize <= 0))
- {
- pcp->iLeft = pcp->iTop = 0;
- pcp->dwWidth = MYCURHOME_WIDTH;
- pcp->dwHeight = MYCURHOME_HEIGHT;
- }
- else
- {
- // Get the number of components positioned. If no such registry key exists
- // or an error occurs then use 0.
- GetRegLocation(lpszDeskcomp, SIZECHARS(lpszDeskcomp), REG_DESKCOMP_GENERAL, NULL);
- dwComponentPosition = 0;
- if (RegCreateKeyEx(HKEY_CURRENT_USER, lpszDeskcomp, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hKey, &dwRegDataScratch) == ERROR_SUCCESS)
- {
- DWORD regDataSize;
- regDataSize = sizeof(dwComponentPosition);
- TW32(SHQueryValueEx(hKey, REG_VAL_GENERAL_CCOMPPOS, NULL, &dwRegDataScratch, &dwComponentPosition, ®DataSize));
- TW32(RegCloseKey(hKey));
- }
- // Compute the layer we live on (see below).
- dwComponentLayer = dwComponentPosition / (COMPONENT_PER_ROW * COMPONENT_PER_COL);
- if (((dwComponentLayer * iBorderSize) > (DWORD)(iScreenWidth / (COMPONENT_PER_ROW + 1))) ||
- ((dwComponentLayer * iBorderSize) > (DWORD)(iScreenHeight / (COMPONENT_PER_COL + 1))))
- {
- int iLayerModulo;
- // 99/04/29 vtan: It's possible for SystemParametersInfo(SPI_GETWORKAREA) to
- // return a work area that's small horizontally. Here's a repro scenario for
- // that.
- // 1. Set screen resolution 1280 x 1024.
- // 2. Move the taskbar to the left of the screen.
- // 3. Grow the taskbar to the right until the center of the screen.
- // 4. Open display control panel.
- // 5. Go to "Settings" tab.
- // 6. Change monitor resolution to 640x480.
- // 7. Click either "OK" or "Apply".
- // 8. BOOM - divide zero.
- iLayerModulo = (iScreenWidth / (COMPONENT_PER_ROW + 1) / iBorderSize);
- if (iLayerModulo != 0)
- dwComponentLayer %= iLayerModulo;
- }
- // Compute the position. Assuming 3 components per row,
- // and 2 per column, we position components thusly:
- //
- // +-------+
- // |x 4 2 0|
- // |x 5 3 1| <-- screen, divided into 4x3 block coordinates
- // |x x x x|
- // +-------+
- //
- // The 6th component sits in a new layer, offset down
- // and to the left of component 0 by the amount iBorder.
- //
- // The first calculation for iLeft and iTop determines the
- // block coordinate value (for instance, component 0 would
- // be at block coordinate value [3,0] and component 1 at [3,1]).
- //
- // The second calculation turns the block coordinate into
- // a screen coordinate.
- //
- // The third calculation adjusts for the border (always down and
- // to the right) and the layers (always down and to the left).
- pcp->iLeft = COMPONENT_PER_ROW - ((dwComponentPosition / COMPONENT_PER_COL) % COMPONENT_PER_ROW); // 3 3 2 2 1 1 3 3 2 2 1 1 ...
- pcp->iLeft *= (iScreenWidth / (COMPONENT_PER_ROW + 1));
- pcp->iLeft += iBorderSize - (dwComponentLayer * iBorderSize);
- pcp->iTop = dwComponentPosition % COMPONENT_PER_COL; // 0 1 0 1 0 1 ...
- pcp->iTop *= (iScreenHeight / (COMPONENT_PER_COL + 1));
- pcp->iTop += iBorderSize + (dwComponentLayer * iBorderSize);
- pcp->iTop += GET_CYCAPTION; //vtan: Added this to allow for the title area of the component window
- pcp->dwWidth = (iScreenWidth / (COMPONENT_PER_ROW + 1)) - 2 * iBorderSize;
- pcp->dwHeight = (iScreenHeight / (COMPONENT_PER_COL + 1)) - 2 * iBorderSize;
- }
- if (IS_BIDI_LOCALIZED_SYSTEM())
- {
- pcp->iLeft = iScreenWidth - (pcp->iLeft + pcp->dwWidth);
- }
- }
- void IncrementComponentsPositioned (void)
- {
- DWORD dwRegDataScratch;
- HKEY hKey;
- TCHAR lpszDeskcomp[MAX_PATH];
- // Increment the registry count. If no such count exists create it.
- GetRegLocation(lpszDeskcomp, SIZECHARS(lpszDeskcomp), REG_DESKCOMP_GENERAL, NULL);
- if (RegCreateKeyEx(HKEY_CURRENT_USER, lpszDeskcomp, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hKey, &dwRegDataScratch) == ERROR_SUCCESS)
- {
- DWORD dwComponentPosition, regDataSize;
- regDataSize = sizeof(dwComponentPosition);
- dwComponentPosition = 0;
- TW32(SHQueryValueEx(hKey, REG_VAL_GENERAL_CCOMPPOS, NULL, &dwRegDataScratch, &dwComponentPosition, ®DataSize));
- ++dwComponentPosition;
- TW32(RegSetValueEx(hKey, REG_VAL_GENERAL_CCOMPPOS, 0, REG_DWORD, reinterpret_cast<unsigned char*>(&dwComponentPosition), sizeof(dwComponentPosition)));
- TW32(RegCloseKey(hKey));
- }
- }
- // vtan: Point arithmetic functions. Simple. It may be worth
- // converting these to inline C++ functions or macros if they
- // get used a lot.
- void SetPt (POINT& pt, LONG x, LONG y)
- {
- pt.x = x;
- pt.y = y;
- }
- void OffsetPt (POINT& pt, LONG dh, LONG dv)
- {
- pt.x += dh;
- pt.y += dv;
- }
- BOOL CALLBACK GDIToTridentEnumProc (HMONITOR hMonitor, HDC hDC, RECT* rcMonitor, LPARAM lpUserData)
- {
- RECT* prcNew, rcOld;
- prcNew = reinterpret_cast<RECT*>(lpUserData);
- // Documentation for UnionRect does not specify whether the
- // RECT structures passed must be distinct. To be safe they
- // are passed as distinct structures.
- TBOOL(CopyRect(&rcOld, prcNew));
- TBOOL(UnionRect(prcNew, &rcOld, rcMonitor));
- return(TRUE);
- }
- void CalculateVirtualScreen (RECT& rcVirtualScreen)
- // vtan: Calculates the virtual screen in GDI co-ordinates for
- // use in converting co-ordinates from trident scheme to GDI
- // scheme.
- {
- TBOOL(SetRectEmpty(&rcVirtualScreen));
- TBOOL(EnumDisplayMonitors(NULL, NULL, GDIToTridentEnumProc, reinterpret_cast<LPARAM>(&rcVirtualScreen)));
- }
- void GDIToTrident (int& leftCoordinate, int& topCoordinate)
- {
- RECT rcVirtualScreen;
- CalculateVirtualScreen(rcVirtualScreen);
- leftCoordinate -= rcVirtualScreen.left;
- topCoordinate -= rcVirtualScreen.top;
- }
- /*
- void GDIToTrident (POINT& pt)
- {
- RECT rcVirtualScreen;
- CalculateVirtualScreen(rcVirtualScreen);
- OffsetPt(pt, -rcVirtualScreen.left, -rcVirtualScreen.top);
- }
- */
- void GDIToTrident (RECT& rc)
- {
- RECT rcVirtualScreen;
- CalculateVirtualScreen(rcVirtualScreen);
- TBOOL(OffsetRect(&rc, -rcVirtualScreen.left, -rcVirtualScreen.top));
- }
- void GDIToTrident (HRGN hRgn)
- {
- RECT rcVirtualScreen;
- CalculateVirtualScreen(rcVirtualScreen);
- TBOOL(OffsetRgn(hRgn, -rcVirtualScreen.left, -rcVirtualScreen.top));
- }
- /*
- void TridentToGDI (int& leftCoordinate, int& topCoordinate)
- {
- RECT rcVirtualScreen;
- CalculateVirtualScreen(rcVirtualScreen);
- leftCoordinate += rcVirtualScreen.left;
- topCoordinate += rcVirtualScreen.top;
- }
- */
- /*
- void TridentToGDI (POINT& pt)
- {
- RECT rcVirtualScreen;
- CalculateVirtualScreen(rcVirtualScreen);
- OffsetPt(pt, +rcVirtualScreen.left, +rcVirtualScreen.top);
- }
- */
- void TridentToGDI (RECT& rc)
- {
- RECT rcVirtualScreen;
- CalculateVirtualScreen(rcVirtualScreen);
- TBOOL(OffsetRect(&rc, +rcVirtualScreen.left, +rcVirtualScreen.top));
- }
- /*
- void TridentToGDI (HRGN hRgn)
- {
- RECT rcVirtualScreen;
- CalculateVirtualScreen(rcVirtualScreen);
- (BOOL)OffsetRgn(hRgn, +rcVirtualScreen.left, +rcVirtualScreen.top);
- }
- */
- // 98/08/14 vtan #196180, #196185: The following code validates
- // a new component's position within the current desktop area. This
- // allows a component to have co-ordinates that seem to be unusual
- // on a single monitor system (such as negative co-ordinates).
- class CRGN
- {
- public:
- CRGN (void) { mRgn = CreateRectRgn(0, 0, 0, 0); }
- CRGN (const RECT& rc) { mRgn = CreateRectRgnIndirect(&rc); }
- ~CRGN (void) { TBOOL(DeleteObject(mRgn)); }
- operator HRGN (void) const { return(mRgn); }
- void SetRegion (const RECT& rc) { TBOOL(SetRectRgn(mRgn, rc.left, rc.top, rc.right, rc.bottom)); }
- private:
- HRGN mRgn;
- };
- typedef struct
- {
- bool bAllowEntireDesktopRegion;
- int iMonitorCount;
- CRGN hRgn;
- int iWorkAreaCount;
- RECT *prcWorkAreaRects;
- } tDesktopRegion;
- void ListView_GetWorkAreasAsGDI (HWND hWndListView, int iWorkAreaCount, RECT *prcWorkAreas)
- {
- int i;
- ListView_GetWorkAreas(hWndListView, iWorkAreaCount, prcWorkAreas);
- for (i = 0; i < iWorkAreaCount; ++i)
- {
- TridentToGDI(prcWorkAreas[i]);
- }
- }
- int CopyMostSuitableListViewWorkAreaRect (const RECT *pcrcMonitor, int iListViewWorkAreaCount, const RECT *pcrcListViewWorkAreaRects, RECT *prcWorkArea)
- {
- int i, iResult;
- const RECT *pcrcRects;
- // This function given a rectangle for a GDI monitor (typically the monitor's
- // work area) as well as given the desktop's list view work area rectangle
- // array (obtained by ListView_GetWorkArea()) will search the list view
- // work area array to find a match for the GDI monitor and use the list view
- // work area rectangle instead as this has docked toolbar information which
- // GDI does not have access to.
- // This function works on the principle that the list view rectangle is
- // always a complete subset of the GDI monitor rectangle which is true.
- // The list view rectangle may be smaller but it should never be bigger.
- // It's ok to pass a NULL pcrcListViewWorkAreaRects as long as
- // iListViewWorkAreaCount is 0.
- pcrcRects = pcrcListViewWorkAreaRects;
- iResult = -1;
- i = 0;
- while ((iResult == -1) && (i < iListViewWorkAreaCount))
- {
- RECT rcIntersection;
- TBOOL(IntersectRect(&rcIntersection, pcrcMonitor, pcrcRects));
- if (EqualRect(&rcIntersection, pcrcRects) != 0)
- {
- iResult = i;
- }
- else
- {
- ++pcrcRects;
- ++i;
- }
- }
- if (iResult < 0)
- {
- TraceMsg(TF_WARNING, "CopyMostSuitableListViewWorkAreaRect() unable to find matching list view rectangle for GDI monitor rectangle");
- TBOOL(CopyRect(prcWorkArea, pcrcMonitor));
- }
- else
- {
- TBOOL(CopyRect(prcWorkArea, &pcrcListViewWorkAreaRects[iResult]));
- }
- return(iResult);
- }
- BOOL GetMonitorInfoWithCompensation (int iMonitorCount, HMONITOR hMonitor, MONITORINFO *pMonitorInfo)
- {
- BOOL fResult;
- // 99/05/20 #338585 vtan: Transplanted the logic explained in the
- // comment below for #211510 from GetZoomRect to here so that other
- // functions can share the behavior. Remember that this ONLY applies
- // a single monitor system where there is part of the monitor's
- // rectangle excluded by a docked toolbar on the left or top of the
- // monitor. A very specific case.
- // 98/10/30 #211510 vtan: Oops. If the task bar is at the top of the
- // screen and there is only one monitor then the shell returns a work
- // area starting at (0, 0) instead of (0, 28); the same applies when
- // the task bar is at the left of the screen; this does NOT occur in
- // a multiple monitor setting. In the single monitor case GDI returns
- // a work area starting at (0, 28) so this code checks for the case
- // where there is a single monitor and offsets the GDI information to
- // (0, 0) so that it matches the shell work area which is compared
- // against in the while loop.
- fResult = GetMonitorInfo(hMonitor, pMonitorInfo);
- if ((fResult != 0) && (iMonitorCount == 1))
- {
- TBOOL(OffsetRect(&pMonitorInfo->rcWork, -pMonitorInfo->rcWork.left, -pMonitorInfo->rcWork.top));
- }
- return(fResult);
- }
- // MonitorCountEnumProc()'s body is located in adjust.cpp
- BOOL CALLBACK MonitorCountEnumProc (HMONITOR hMonitor, HDC dc, RECT *rc, LPARAM data);
- BOOL CALLBACK ValidateComponentPositionEnumProc (HMONITOR hMonitor, HDC hdcMonitor, RECT* prc, LPARAM lpUserData)
- {
- HRGN hRgnDesktop;
- HMONITOR hMonitorTopLeft, hMonitorTopRight;
- POINT ptAbove;
- RECT rcMonitor;
- MONITORINFO monitorInfo;
- tDesktopRegion *pDesktopRegion;
- pDesktopRegion = reinterpret_cast<tDesktopRegion*>(lpUserData);
- monitorInfo.cbSize = sizeof(monitorInfo);
- if (GetMonitorInfoWithCompensation(pDesktopRegion->iMonitorCount, hMonitor, &monitorInfo) != 0)
- {
- TINT(CopyMostSuitableListViewWorkAreaRect(&monitorInfo.rcWork, pDesktopRegion->iWorkAreaCount, pDesktopRegion->prcWorkAreaRects, &rcMonitor));
- }
- else
- {
- TBOOL(CopyRect(&rcMonitor, prc));
- }
- // If this monitor does not have a monitor above it then
- // make the monitor rectangle one pixel lower from the
- // top.
- CRGN hRgnMonitor(rcMonitor);
- if (!pDesktopRegion->bAllowEntireDesktopRegion)
- {
- // This bizarre little algorithm calculates the margins of the current
- // monitor that do not have a monitor above them. The rcExclude is the
- // the final rectangle that contains this information and is one pixel
- // high. This calculation is only valid if the entire desktop region
- // has been DISALLOWED (not zooming a component).
- // Note that the algorithm fails if there is a monitor that is above
- // this one but is contained within the confines of it. For example,
- // this monitor is at 1024x768 and the one above is at 640x480 and
- // centered. In this case it should be possible to drop the component
- // on the exact zero pixel point but this case is disallowed due to
- // this fault. No big deal.
- SetPt(ptAbove, rcMonitor.left, rcMonitor.top - 1);
- hMonitorTopLeft = MonitorFromPoint(ptAbove, MONITOR_DEFAULTTONULL);
- SetPt(ptAbove, rcMonitor.right, rcMonitor.top - 1);
- hMonitorTopRight = MonitorFromPoint(ptAbove, MONITOR_DEFAULTTONULL);
- if ((hMonitorTopLeft == NULL) && (hMonitorTopRight == NULL))
- {
- // No monitor above this one
- ++rcMonitor.top;
- hRgnMonitor.SetRegion(rcMonitor);
- }
- else if (hMonitorTopLeft != hMonitorTopRight)
- {
- RECT rcExclude;
- // Either one or two different monitors above this one
- // == case is the same monitor completely covers this
- // monitor.
- TBOOL(SetRect(&rcExclude, rcMonitor.left, rcMonitor.top, rcMonitor.right, rcMonitor.top + 1));
- if (hMonitorTopLeft != NULL)
- {
- TBOOL(GetMonitorInfoWithCompensation(pDesktopRegion->iMonitorCount, hMonitorTopLeft, &monitorInfo));
- rcExclude.left = monitorInfo.rcWork.right + 1;
- }
- if (hMonitorTopRight != NULL)
- {
- TBOOL(GetMonitorInfoWithCompensation(pDesktopRegion->iMonitorCount, hMonitorTopRight, &monitorInfo));
- rcExclude.right = monitorInfo.rcWork.left;
- }
- CRGN hRgnExclude(rcExclude);
- TINT(CombineRgn(hRgnMonitor, hRgnMonitor, hRgnExclude, RGN_DIFF));
- }
- }
- hRgnDesktop = pDesktopRegion->hRgn;
- TINT(CombineRgn(hRgnDesktop, hRgnDesktop, hRgnMonitor, RGN_OR));
- return(true);
- }
- void ValidateComponentPosition (COMPPOS *pcp, DWORD dwComponentState, int iComponentType, bool *pbChangedPosition, bool *pbChangedSize)
- {
- bool bChangedPosition, bChangedSize;
- HRGN hRgnDesktop;
- HWND hWndDesktopListView;
- RECT rcComponent, rcComponentTop;
- tDesktopRegion desktopRegion;
- COMPPOS defaultComponentPosition;
- bChangedPosition = bChangedSize = false;
- GetNextComponentPosition(&defaultComponentPosition);
- GDIToTrident(defaultComponentPosition.iLeft, defaultComponentPosition.iTop);
- // If the component has default left or top then give it the next
- // default component position.
- if ((pcp->iLeft == COMPONENT_DEFAULT_LEFT) && (pcp->iTop == COMPONENT_DEFAULT_TOP))
- {
- pcp->iLeft = defaultComponentPosition.iLeft;
- pcp->iTop = defaultComponentPosition.iTop;
- IncrementComponentsPositioned();
- bChangedPosition = true;
- }
- // If the component has default width or height then give it the
- // next default component size unless it is type COMP_TYPE_PICTURE
- // 98/10/02 #222449 vtan: Only change the size of an unpositioned
- // component if it's not a picture.
- if ((pcp->dwWidth == COMPONENT_DEFAULT_WIDTH) && (pcp->dwHeight == COMPONENT_DEFAULT_HEIGHT) && (iComponentType != COMP_TYPE_PICTURE))
- {
- pcp->dwWidth = defaultComponentPosition.dwWidth;
- pcp->dwHeight = defaultComponentPosition.dwHeight;
- bChangedSize = false;
- }
- // Make sure that the top line of the component is visible or at
- // least one pixel below the top most part of a virtual screen.
- // Check to see if the component has a negative width and height or
- // a width and height that is too small. The only exception to this
- // is if the component is a picture.
- desktopRegion.bAllowEntireDesktopRegion = IsZoomedState(dwComponentState);
- if (iComponentType != COMP_TYPE_PICTURE)
- {
- if (static_cast<int>(pcp->dwWidth) < 10)
- {
- pcp->dwWidth = defaultComponentPosition.dwWidth;
- bChangedSize = false;
- }
- if (static_cast<int>(pcp->dwHeight) < 10)
- {
- pcp->dwHeight= defaultComponentPosition.dwHeight;
- bChangedSize = false;
- }
- }
- TBOOL(SetRect(&rcComponent, pcp->iLeft, pcp->iTop, pcp->iLeft + pcp->dwWidth, pcp->iTop + pcp->dwHeight));
- TBOOL(CopyRect(&rcComponentTop, &rcComponent));
- rcComponentTop.bottom = rcComponentTop.top + 1;
- // Before calculating the desktopRegion as a region by using GDI calls
- // get the List View work area which will have information about docked
- // toolbars in addition to the taskbar which is the only thing that GDI
- // has. This will allow this function to invalidate regions occupied by
- // toolbars also.
- desktopRegion.iWorkAreaCount = 0;
- desktopRegion.prcWorkAreaRects = NULL;
- hWndDesktopListView = FindWindowEx(GetWindow(GetShellWindow(), GW_CHILD), NULL, WC_LISTVIEW, NULL);
- if (hWndDesktopListView != NULL)
- {
- DWORD dwProcessID;
- GetWindowThreadProcessId(hWndDesktopListView, &dwProcessID);
- if (GetCurrentProcessId() == dwProcessID)
- {
- ListView_GetNumberOfWorkAreas(hWndDesktopListView, &desktopRegion.iWorkAreaCount);
- desktopRegion.prcWorkAreaRects = reinterpret_cast<RECT*>(LocalAlloc(GPTR, desktopRegion.iWorkAreaCount * sizeof(desktopRegion.prcWorkAreaRects[0])));
- ListView_GetWorkAreasAsGDI(hWndDesktopListView, desktopRegion.iWorkAreaCount, desktopRegion.prcWorkAreaRects);
- }
- }
- CRGN hRgnComponentTop(rcComponentTop), hRgnResult;
- desktopRegion.iMonitorCount = 0;
- TBOOL(EnumDisplayMonitors(NULL, NULL, MonitorCountEnumProc, reinterpret_cast<LPARAM>(&desktopRegion.iMonitorCount)));
- TBOOL(EnumDisplayMonitors(NULL, NULL, ValidateComponentPositionEnumProc, reinterpret_cast<LPARAM>(&desktopRegion)));
- hRgnDesktop = desktopRegion.hRgn;
- GDIToTrident(hRgnDesktop);
- // 99/03/23 #266412 vtan: Make sure that the top pixel of the component is within
- // the visible desktop. This allows the deskmovr to be positioned over the
- // component and therefore allows it to be moved. If the deskmovr cannot be
- // positioned over it then "snap" the component back into the visible region
- // to a maximum best fit algorithm.
- if (CombineRgn(hRgnResult, hRgnDesktop, hRgnComponentTop, RGN_AND) == NULLREGION)
- {
- LONG lDeltaX, lDeltaY;
- HMONITOR hMonitorNearest;
- RECT rcComponentGDI, rcMonitorWork, rcIntersection;
- MONITORINFO monitorInfo;
- TBOOL(CopyRect(&rcComponentGDI, &rcComponent));
- TridentToGDI(rcComponentGDI);
- hMonitorNearest = MonitorFromRect(&rcComponentGDI, MONITOR_DEFAULTTONEAREST);
- ASSERT(hMonitorNearest != NULL);
- monitorInfo.cbSize = sizeof(monitorInfo);
- TBOOL(GetMonitorInfoWithCompensation(desktopRegion.iMonitorCount, hMonitorNearest, &monitorInfo));
- TINT(CopyMostSuitableListViewWorkAreaRect(&monitorInfo.rcWork, desktopRegion.iWorkAreaCount, desktopRegion.prcWorkAreaRects, &rcMonitorWork));
- ++rcMonitorWork.top;
- lDeltaX = lDeltaY = 0;
- if (rcComponentGDI.left < rcMonitorWork.left)
- lDeltaX = rcMonitorWork.left - rcComponentGDI.left;
- if (rcComponentGDI.top < rcMonitorWork.top)
- lDeltaY = rcMonitorWork.top - rcComponentGDI.top;
- if (rcComponentGDI.right > rcMonitorWork.right)
- lDeltaX = rcMonitorWork.right - rcComponentGDI.right;
- if (rcComponentGDI.bottom > rcMonitorWork.bottom)
- lDeltaY = rcMonitorWork.bottom - rcComponentGDI.bottom;
- TBOOL(OffsetRect(&rcComponentGDI, lDeltaX, lDeltaY));
- TBOOL(IntersectRect(&rcIntersection, &rcComponentGDI, &rcMonitorWork));
- GDIToTrident(rcIntersection);
- pcp->iLeft = rcIntersection.left;
- pcp->iTop = rcIntersection.top;
- pcp->dwWidth = rcIntersection.right - rcIntersection.left;
- pcp->dwHeight = rcIntersection.bottom - rcIntersection.top;
- bChangedPosition = bChangedSize = true;
- }
- if (desktopRegion.prcWorkAreaRects != NULL)
- LocalFree(desktopRegion.prcWorkAreaRects);
- if (pbChangedPosition != NULL)
- *pbChangedPosition = bChangedPosition;
- if (pbChangedSize != NULL)
- *pbChangedSize = bChangedSize;
- }
- // 98/12/11 #250938 vtan: these two functions are lifted from
- // SHBrows2.cpp which is part of browseui.dll.
- EXTERN_C DWORD WINAPI IsSmartStart (void);
- BOOL IsICWCompleted (void)
- {
- DWORD dwICWCompleted, dwICWSize;
- dwICWCompleted = 0;
- dwICWSize = sizeof(dwICWCompleted);
- TW32(SHGetValue(HKEY_CURRENT_USER, TEXT(ICW_REGPATHSETTINGS), TEXT(ICW_REGKEYCOMPLETED), NULL, &dwICWCompleted, &dwICWSize));
- // 99/01/15 #272829 vtan: This is a horrible hack!!! If ICW has
- // not been run but settings have been made manually then values
- // in HKCUSoftwareMicrosoftWindowsCurrentVersionInternet SettingsConnections
- // exists with the values given. Look for the presence of a key
- // to resolve that settings are present but that ICW hasn't been
- // launched.
- // The ideal solution is to get ICW to make this determination
- // for us BUT TO NOT LAUNCH ICWCONN1.EXE IN THE PROCESS.
- // Currently it will only launch. There is no way to get the
- // desired result without a launch.
- // 99/02/01 #280138 vtan: Well the solution put in for #272829
- // doesn't work. So peeking at the CheckConnectionWizard()
- // source in inetcfgexport.cpp shows that it uses a
- // wininet.dll function to determine whether manually configured
- // internet settings exist. It also exports this function so
- // look for it and bind to it dynamically. This uses the
- // DELAY_LOAD macros in dllload.c
- if (dwICWCompleted == 0)
- {
- #define SMART_RUNICW TRUE
- #define SMART_QUITICW FALSE
- dwICWCompleted = BOOLIFY(IsSmartStart() == SMART_QUITICW);
- }
- return(dwICWCompleted != 0);
- }
- void LaunchICW (void)
- {
- static bool sbCheckedICW = false;
- if (!sbCheckedICW && !IsICWCompleted())
- {
- HINSTANCE hICWInst;
- // Prevent an error in finding the ICW from causing this to
- // execute again and again and again.
- sbCheckedICW = true;
- hICWInst = LoadLibrary(TEXT("inetcfg.dll"));
- if (hICWInst != NULL)
- {
- PFNCHECKCONNECTIONWIZARD pfnCheckConnectionWizard;
- pfnCheckConnectionWizard = reinterpret_cast<PFNCHECKCONNECTIONWIZARD>(GetProcAddress(hICWInst, "CheckConnectionWizard"));
- if (pfnCheckConnectionWizard != NULL)
- {
- DWORD dwICWResult;
- // If the user cancels ICW then it needs to be launched
- // again. Allow this case.
- sbCheckedICW = false;
- pfnCheckConnectionWizard(ICW_LAUNCHFULL | ICW_LAUNCHMANUAL, &dwICWResult);
- }
- TBOOL(FreeLibrary(hICWInst));
- }
- }
- }
- BOOL IsLocalPicture (LPCTSTR pszURL)
- {
- return(!PathIsURL(pszURL) && IsUrlPicture(pszURL));
- }
- BOOL DisableUndisplayableComponents (IActiveDesktop *pIAD)
- {
- bool bHasVisibleNonLocalPicture;
- int iItemCount;
- // 98/12/16 vtan #250938: If ICW has not been run to completion then only
- // allow the user to show components that are local pictures of some sort.
- // If any components are not local pictures then hide these components,
- // tell the user why it happened and launch ICW.
- bHasVisibleNonLocalPicture = false;
- if (SUCCEEDED(pIAD->GetDesktopItemCount(&iItemCount, 0)))
- {
- int i;
- for (i = 0; i < iItemCount; ++i)
- {
- COMPONENT component;
- component.dwSize = sizeof(component);
- if (SUCCEEDED(pIAD->GetDesktopItem(i, &component, 0)) && (component.fChecked != 0))
- {
- bool bIsVisibleNonLocalPicture;
- TCHAR szComponentSource[INTERNET_MAX_URL_LENGTH];
- SHUnicodeToTChar(component.wszSource, szComponentSource, ARRAYSIZE(szComponentSource));
- bIsVisibleNonLocalPicture = !IsLocalPicture(szComponentSource);
- bHasVisibleNonLocalPicture = bHasVisibleNonLocalPicture || bIsVisibleNonLocalPicture;
- if (bIsVisibleNonLocalPicture)
- {
- component.fChecked = FALSE;
- THR(pIAD->ModifyDesktopItem(&component, COMP_ELEM_CHECKED));
- }
- }
- }
- }
- if (bHasVisibleNonLocalPicture)
- {
- // Apply the changes. This should recurse to CActiveDesktop::_SaveSettings()
- // but this code path is NOT taken because AD_APPLY_REFRESH is not passed in.
- // CActiveDesktop::_SaveSettings() calls this function!
- bHasVisibleNonLocalPicture = FAILED(pIAD->ApplyChanges(AD_APPLY_SAVE | AD_APPLY_HTMLGEN));
- // Notify the user what happened and launch ICW.
- ShellMessageBox(HINST_THISDLL, NULL, MAKEINTRESOURCE(IDS_COMP_ICW_DISABLE), MAKEINTRESOURCE(IDS_COMP_ICW_TITLE), MB_OK);
- LaunchICW();
- }
- return(bHasVisibleNonLocalPicture);
- }
- int GetIconCountForWorkArea(HWND hwndLV, LPCRECT prect, int crect, int iWorkAreaIndex)
- {
- int iCount;
- iCount = ListView_GetItemCount(hwndLV);
- if (crect > 1)
- {
- int i, iCountWorkArea = 0;
- for (i = 0; i < iCount; i++)
- {
- POINT pt;
- ListView_GetItemPosition(hwndLV, i, &pt);
- if (iWorkAreaIndex == GetWorkAreaIndexFromPoint(pt, prect, crect))
- iCountWorkArea++;
- }
- iCount = iCountWorkArea;
- }
- return iCount;
- }
- BOOL GetZoomRect(BOOL fFullScreen, BOOL fAdjustListview, int iTridentLeft, int iTridentTop, DWORD dwComponentWidth, DWORD dwComponentHeight, LPRECT prcZoom, LPRECT prcWork)
- {
- HWND hwndLV = FindWindowEx(GetWindow(GetShellWindow(), GW_CHILD), NULL, WC_LISTVIEW, NULL);
- int icWorkAreas = 0, iWAC;
- RECT rcWork[LV_MAX_WORKAREAS];
- //
- // First calculate the Work Areas and Work Area index for the component, then perform the
- // particular operation based on lCommand.
- //
- if (hwndLV) {
- DWORD dwpid;
- GetWindowThreadProcessId(hwndLV, &dwpid);
- // This sucks, but the listview doesn't thunk these messages so we can't do
- // this inter-process!
- if (dwpid == GetCurrentProcessId())
- {
- ListView_GetNumberOfWorkAreas(hwndLV, &icWorkAreas);
- if (icWorkAreas <= LV_MAX_WORKAREAS)
- ListView_GetWorkAreas(hwndLV, icWorkAreas, &rcWork);
- else
- hwndLV = NULL;
- } else {
- return FALSE;
- }
- }
- // 98/10/07 vtan: This used to use a variable icWorkAreasAdd.
- // Removed this variable and directly increment icWorkAreas.
- // This doesn't affect the call to ListView_SetWorkAreas()
- // below because in this case hwndLV is NULL.
- if (icWorkAreas == 0)
- {
- RECT rc;
- ++icWorkAreas;
- SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&rc, 0);
- rcWork[0] = rc;
- hwndLV = NULL;
- }
- // 98/10/02 #212654 vtan: Changed the calculation code to find a
- // rectangle to zoom the component to based on GDI co-ordinates.
- // The component is passed in trident co-ordinates which are
- // stored in a RECT and converted to GDI co-ordinates. The system
- // then locates the monitor which the component is on and if it
- // cannot find the monitor then defaults to the primary. The
- // dimensions of the monitor are used before converting back to
- // trident co-ordinates.
- int i, iMonitorCount;
- HMONITOR hMonitor;
- RECT rcComponentRect;
- MONITORINFO monitorInfo;
- iMonitorCount = 0;
- TBOOL(EnumDisplayMonitors(NULL, NULL, MonitorCountEnumProc, reinterpret_cast<LPARAM>(&iMonitorCount)));
- TBOOL(SetRect(&rcComponentRect, iTridentLeft, iTridentTop, iTridentLeft + dwComponentWidth, iTridentTop + dwComponentHeight));
- TridentToGDI(rcComponentRect);
- hMonitor = MonitorFromRect(&rcComponentRect, MONITOR_DEFAULTTOPRIMARY);
- ASSERT(hMonitor != NULL);
- monitorInfo.cbSize = sizeof(monitorInfo);
- TBOOL(GetMonitorInfoWithCompensation(iMonitorCount, hMonitor, &monitorInfo));
- GDIToTrident(monitorInfo.rcWork);
- // 99/05/19 #340772 vtan: Always try to key off work areas returned
- // by ListView_GetWorkAreas because these take into account docked
- // toolbars which GDI does not. In this case the listview work areas
- // will always be the same rectangle when intersected with the GDI
- // work area. Use this rule to determine which listview work area
- // to use as the basis for the zoom rectangle.
- i = CopyMostSuitableListViewWorkAreaRect(&monitorInfo.rcWork, icWorkAreas, rcWork, prcZoom);
- if (i < 0)
- {
- i = 0;
- }
- if (prcWork != NULL)
- {
- TBOOL(CopyRect(prcWork, prcZoom));
- }
- iWAC = i;
- if (!fFullScreen)
- {
- // For the split case we shrink the work area down temporarily to the smallest rectangle
- // that can bound the current number of icons. This will force the icons into that rectangle,
- // then restore it back to the way it was before. Finally, we set the size of the split
- // component to fill the rest of the space.
- if (hwndLV) {
- int iCount, iItemsPerColumn, icxWidth, iRightOld;
- DWORD dwSpacing;
- iCount = GetIconCountForWorkArea(hwndLV, rcWork, icWorkAreas, iWAC);
- // Decrement the count so that rounding works right
- if (iCount)
- iCount--;
- // Calculate the new width for the view rectangle
- dwSpacing = ListView_GetItemSpacing(hwndLV, FALSE);
- iItemsPerColumn = (rcWork[iWAC].bottom - rcWork[iWAC].top) / (HIWORD(dwSpacing));
- if (iItemsPerColumn)
- icxWidth = ((iCount / iItemsPerColumn) + 1) * (LOWORD(dwSpacing));
- else
- icxWidth = LOWORD(dwSpacing);
- // Don't let it get smaller than half the screen
- if (icxWidth > ((rcWork[iWAC].right - rcWork[iWAC].left) / 2))
- icxWidth = (rcWork[iWAC].right - rcWork[iWAC].left) / 2;
- if (fAdjustListview)
- {
- // Now take the old work area rectangle and shrink it to our new width
- iRightOld = rcWork[iWAC].right;
- rcWork[iWAC].right = rcWork[iWAC].left + icxWidth;
- ListView_SetWorkAreas(hwndLV, icWorkAreas, &rcWork);
- // Finally restore the old work area
- rcWork[iWAC].right = iRightOld;
- ListView_SetWorkAreas(hwndLV, icWorkAreas, &rcWork);
- }
- // Adjust the left coordinate of the zoom rect to reflect our calculated split amount
- // the rest of the screen.
- prcZoom->left += icxWidth;
- } else {
- // Fallback case, if there is no listview use 20% of the screen for the icons.
- prcZoom->left += ((prcZoom->right - prcZoom->left) * 2 / 10);
- }
- }
- return TRUE;
- }
- void ZoomComponent(COMPPOS * pcp, DWORD dwCurItemState, BOOL fAdjustListview)
- {
- RECT rcZoom;
- if (GetZoomRect((dwCurItemState & IS_FULLSCREEN), fAdjustListview, pcp->iLeft, pcp->iTop, pcp->dwWidth, pcp->dwHeight, &rcZoom, NULL))
- {
- // Copy the new Zoom rectangle over and put it on the bottom
- pcp->iLeft = rcZoom.left;
- pcp->iTop = rcZoom.top;
- pcp->dwWidth = rcZoom.right - rcZoom.left;
- pcp->dwHeight = rcZoom.bottom - rcZoom.top;
- pcp->izIndex = 0;
- }
- else
- {
- // Failure implies we couldn't get the zoom rectangle through inter-process calls. Set the
- // COMPONENTS_ZOOMDIRTY bit here so that when the desktop is refreshed we will recalculate
- // the zoom rectangles in-process inside of EnsureUpdateHTML.
- SetDesktopFlags(COMPONENTS_ZOOMDIRTY, COMPONENTS_ZOOMDIRTY);
- }
- }
- //
- // PositionComponent will assign a screen position and
- // make sure it fits on the screen.
- //
- void PositionComponent(COMPONENTA *pcomp, COMPPOS *pcp, int iCompType, BOOL fCheckItemState)
- {
- // vtan: Vastly simplified routine. The work is now done in
- // ValidateComponentPosition.
- if (ISZOOMED(pcomp))
- {
- if (fCheckItemState)
- {
- SetStateInfo(&pcomp->csiRestored, pcp, IS_NORMAL);
- SetStateInfo(&pcomp->csiOriginal, pcp, pcomp->dwCurItemState);
- }
- ZoomComponent(pcp, pcomp->dwCurItemState, FALSE);
- }
- else
- {
- ValidateComponentPosition(pcp, pcomp->dwCurItemState, iCompType, NULL, NULL);
- if (fCheckItemState)
- SetStateInfo(&pcomp->csiOriginal, pcp, pcomp->dwCurItemState);
- }
- }
- typedef struct _tagFILETYPEENTRY {
- DWORD dwFlag;
- int iFilterId;
- } FILETYPEENTRY;
- FILETYPEENTRY afte[] = {
- { GFN_URL, IDS_URL_FILTER, },
- { GFN_CDF, IDS_CDF_FILTER, },
- { GFN_LOCALHTM, IDS_HTMLDOC_FILTER, },
- { GFN_PICTURE, IDS_IMAGES_FILTER, },
- { GFN_LOCALMHTML, IDS_MHTML_FILTER, },
- };
- //
- // Opens either an HTML page or a picture.
- //
- BOOL GetFileName(HWND hdlg, LPTSTR pszFileName, int iSize, int iTypeId[], DWORD dwFlags[])
- {
- BOOL fRet = FALSE;
- if (dwFlags)
- {
- int i, iIndex, cchRead;
- TCHAR szFilter[MAX_PATH*4];
- //
- // Set the friendly name.
- //
- LPTSTR pchFilter = szFilter;
- int cchFilter = ARRAYSIZE(szFilter) - 2; // room for term chars
- for(iIndex = 0; dwFlags[iIndex]; iIndex++)
- {
- cchRead = LoadString(HINST_THISDLL, iTypeId[iIndex], pchFilter, cchFilter);
- pchFilter += cchRead + 1;
- cchFilter -= cchRead + 1;
- //
- // Append the file filters.
- //
- BOOL fAddedToString = FALSE;
- for (i=0; (cchFilter>0) && (i<ARRAYSIZE(afte)); i++)
- {
- if (dwFlags[iIndex] & afte[i].dwFlag)
- {
- if (fAddedToString)
- {
- *pchFilter++ = TEXT(';');
- cchFilter--;
- }
- cchRead = LoadString(HINST_THISDLL, afte[i].iFilterId,
- pchFilter, cchFilter);
- pchFilter += cchRead;
- cchFilter -= cchRead;
- fAddedToString = TRUE;
- }
- }
- *pchFilter++ = TEXT('');
- }
- //
- // Double-NULL terminate the string.
- //
- *pchFilter = TEXT('');
- TCHAR szBrowserDir[MAX_PATH];
- lstrcpy(szBrowserDir, pszFileName);
- PathRemoveArgs(szBrowserDir);
- PathRemoveFileSpec(szBrowserDir);
- TCHAR szBuf[MAX_PATH];
- LoadString(HINST_THISDLL, IDS_BROWSE, szBuf, ARRAYSIZE(szBuf));
- *pszFileName = TEXT('');
- OPENFILENAME ofn;
- ofn.lStructSize = SIZEOF(ofn);
- ofn.hwndOwner = hdlg;
- ofn.hInstance = NULL;
- ofn.lpstrFilter = szFilter;
- ofn.lpstrCustomFilter = NULL;
- ofn.nFilterIndex = 1;
- ofn.nMaxCustFilter = 0;
- ofn.lpstrFile = pszFileName;
- ofn.nMaxFile = iSize;
- ofn.lpstrInitialDir = szBrowserDir;
- ofn.lpstrTitle = szBuf;
- ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NODEREFERENCELINKS;
- ofn.lpfnHook = NULL;
- ofn.lpstrDefExt = NULL;
- ofn.lpstrFileTitle = NULL;
- fRet = GetOpenFileName(&ofn);
- }
- return fRet;
- }
- //
- // Convert a pattern string to a bottom-up array of DWORDs,
- // useful for BMP format files.
- //
- void PatternToDwords(LPTSTR psz, DWORD *pdwBits)
- {
- DWORD i, dwVal;
- //
- // Get eight groups of numbers separated by non-numeric characters.
- //
- for (i=0; i<8; i++)
- {
- dwVal = 0;
- if (*psz != TEXT(''))
- {
- //
- // Skip over any non-numeric characters.
- //
- while (*psz && (!(*psz >= TEXT('0') && *psz <= TEXT('9'))))
- {
- psz++;
- }
- //
- // Get the next series of digits.
- //
- while (*psz && (*psz >= TEXT('0') && *psz <= TEXT('9')))
- {
- dwVal = dwVal*10 + *psz++ - TEXT('0');
- }
- }
- pdwBits[7-i] = dwVal;
- }
- }
- //
- // Convert a pattern string to a top-down array of WORDs,
- // useful for CreateBitmap().
- //
- void PatternToWords(LPTSTR psz, WORD *pwBits)
- {
- WORD i, wVal;
- //
- // Get eight groups of numbers separated by non-numeric characters.
- //
- for (i=0; i<8; i++)
- {
- wVal = 0;
- if (*psz != TEXT(''))
- {
- //
- // Skip over any non-numeric characters.
- //
- while (*psz && (!(*psz >= TEXT('0') && *psz <= TEXT('9'))))
- {
- psz++;
- }
- //
- // Get the next series of digits.
- //
- while (*psz && ((*psz >= TEXT('0') && *psz <= TEXT('9'))))
- {
- wVal = wVal*10 + *psz++ - TEXT('0');
- }
- }
- pwBits[i] = wVal;
- }
- }
- BOOL IsValidPattern(LPCTSTR pszPat)
- {
- BOOL fSawANumber = FALSE;
- //
- // We're mainly trying to filter multilingual upgrade cases
- // where the text for "(None)" is unpredictable.
- // Yes, I want to strangle the bastard who decided to
- // write out the none entry.
- //
- while (*pszPat)
- {
- if ((*pszPat < TEXT('0')) || (*pszPat > TEXT('9')))
- {
- //
- // It's not a number, it better be a space.
- //
- if (*pszPat != TEXT(' '))
- {
- return FALSE;
- }
- }
- else
- {
- fSawANumber = TRUE;
- }
- //
- // We avoid the need for AnsiNext by only advancing on US TCHARs.
- //
- pszPat++;
- }
- //
- // TRUE if we saw at least one digit and there were only digits and spaces.
- //
- return fSawANumber;
- }
- //
- // Determines if the wallpaper can be supported in non-active desktop mode.
- //
- BOOL IsNormalWallpaper(LPCTSTR pszFileName)
- {
- BOOL fRet = TRUE;
- if (pszFileName[0] == TEXT(''))
- {
- fRet = TRUE;
- }
- else
- {
- LPTSTR pszExt = PathFindExtension(pszFileName);
- //Check for specific files that can be shown only in ActiveDesktop mode!
- if((lstrcmpi(pszExt, TEXT(".GIF")) == 0) ||
- (lstrcmpi(pszExt, TEXT(".JPG")) == 0) ||
- (lstrcmpi(pszExt, TEXT(".JPE")) == 0) ||
- (lstrcmpi(pszExt, TEXT(".JPEG")) == 0) ||
- (lstrcmpi(pszExt, TEXT(".PNG")) == 0) ||
- (lstrcmpi(pszExt, TEXT(".HTM")) == 0) ||
- (lstrcmpi(pszExt, TEXT(".HTML")) == 0) ||
- (lstrcmpi(pszExt, TEXT(".HTT")) == 0))
- return FALSE;
- //Everything else (including *.BMP files) are "normal" wallpapers
- }
- return fRet;
- }
- //
- // Determines if the wallpaper is a picture (vs. HTML).
- //
- BOOL IsWallpaperPicture(LPCTSTR pszWallpaper)
- {
- BOOL fRet = TRUE;
- if (pszWallpaper[0] == TEXT(''))
- {
- //
- // Empty wallpapers count as empty pictures.
- //
- fRet = TRUE;
- }
- else
- {
- LPTSTR pszExt = PathFindExtension(pszWallpaper);
- if ((lstrcmpi(pszExt, TEXT(".HTM")) == 0) ||
- (lstrcmpi(pszExt, TEXT(".HTML")) == 0) ||
- (lstrcmpi(pszExt, TEXT(".HTT")) == 0))
- {
- fRet = FALSE;
- }
- }
- return fRet;
- }
- void OnDesktopSysColorChange(void)
- {
- static COLORREF clrBackground = 0xffffffff;
- static COLORREF clrWindowText = 0xffffffff;
- //Get the new colors!
- COLORREF clrNewBackground = GetSysColor(COLOR_BACKGROUND);
- COLORREF clrNewWindowText = GetSysColor(COLOR_WINDOWTEXT);
- //Have we initialized these before?
- if(clrBackground != 0xffffffff) //Have we initialized the statics yet?
- {
- // Our HTML file depends only on these two system colors.
- // Check if either of them has changed!
- // If not, no need to regenerate HTML file.
- // This avoids infinite loop. And this is a nice optimization.
- if((clrBackground == clrNewBackground) &&
- (clrWindowText == clrNewWindowText))
- return; //No need to do anything. Just return.
- }
- // Remember the new colors in the statics.
- clrBackground = clrNewBackground;
- clrWindowText = clrNewWindowText;
- //
- // The desktop got a WM_SYSCOLORCHANGE. We need to
- // regenerate the HTML if there are any system colors
- // showing on the desktop. Patterns and the desktop
- // color are both based on system colors.
- //
- IActiveDesktop *pad;
- if (SUCCEEDED(CActiveDesktop_InternalCreateInstance((LPUNKNOWN *)&pad, IID_IActiveDesktop)))
- {
- BOOL fRegenerateHtml = FALSE;
- WCHAR szWallpaperW[INTERNET_MAX_URL_LENGTH];
- if (SUCCEEDED(pad->GetWallpaper(szWallpaperW, ARRAYSIZE(szWallpaperW), 0)))
- {
- if (!*szWallpaperW)
- {
- //
- // No wallpaper means the desktop color
- // or a pattern is showing - we need to
- // regenerate the desktop HTML.
- //
- fRegenerateHtml = TRUE;
- }
- else
- {
- TCHAR *pszWallpaper;
- #ifdef UNICODE
- pszWallpaper = szWallpaperW;
- #else
- CHAR szWallpaperA[INTERNET_MAX_URL_LENGTH];
- SHUnicodeToAnsi(szWallpaperW, szWallpaperA, ARRAYSIZE(szWallpaperA));
- pszWallpaper = szWallpaperA;
- #endif
- if (IsWallpaperPicture(pszWallpaper))
- {
- WALLPAPEROPT wpo = { SIZEOF(wpo) };
- if (SUCCEEDED(pad->GetWallpaperOptions(&wpo, 0)))
- {
- if (wpo.dwStyle == WPSTYLE_CENTER)
- {
- //
- // We have a centered picture,
- // the pattern or desktop color
- // could be leaking around the edges.
- // We need to regenerate the desktop
- // HTML.
- //
- fRegenerateHtml = TRUE;
- }
- }
- else
- {
- TraceMsg(TF_WARNING, "SYSCLRCHG: Could not get wallpaper options!");
- }
- }
- }
- }
- else
- {
- TraceMsg(TF_WARNING, "SYSCLRCHG: Could not get selected wallpaper!");
- }
- if (fRegenerateHtml)
- {
- DWORD dwFlags = AD_APPLY_FORCE | AD_APPLY_HTMLGEN | AD_APPLY_REFRESH | AD_APPLY_DYNAMICREFRESH;
- WCHAR wszPattern[MAX_PATH];
- //If we have a pattern, then we need to force a AD_APPLY_COMPLETEREFRESH
- // because we need to re-generate the pattern.bmp file which can not be
- // done through dynamic HTML.
- if(SUCCEEDED(pad->GetPattern(wszPattern, sizeof(wszPattern), 0)))
- {
- #ifdef UNICODE
- LPTSTR szPattern = (LPTSTR)wszPattern;
- #else
- CHAR szPattern[MAX_PATH];
- SHUnicodeToAnsi(wszPattern, szPattern, sizeof(szPattern));
- #endif //UNICODE
- if(IsValidPattern(szPattern)) //Does this have a pattern?
- dwFlags &= ~(AD_APPLY_DYNAMICREFRESH); //Then force a complete refresh!
- }
- pad->ApplyChanges(dwFlags);
- }
- pad->Release();
- }
- else
- {
- TraceMsg(TF_WARNING, "SYSCLRCHG: Could not create CActiveDesktop!");
- }
- }
- //
- // Convert a .URL file into its target.
- //
- void CheckAndResolveLocalUrlFile(LPTSTR pszFileName, int cchFileName)
- {
- //
- // This function only works on *.URL files.
- //
- if (!PathIsURL(pszFileName))
- {
- LPTSTR pszExt;
- //
- // Check if the extension of this file is *.URL
- //
- pszExt = PathFindExtension(pszFileName);
- if (pszExt && *pszExt)
- {
- TCHAR szUrl[15];
- LoadString(HINST_THISDLL, IDS_URL_EXTENSION, szUrl, ARRAYSIZE(szUrl));
- if (lstrcmpi(pszExt, szUrl) == 0)
- {
- HRESULT hr;
- IUniformResourceLocator *purl;
- hr = CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
- IID_IUniformResourceLocator,
- (LPVOID *)&purl);
- if (EVAL(SUCCEEDED(hr))) // This works for both Ansi and Unicode
- {
- ASSERT(purl);
- IPersistFile *ppf;
- hr = purl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
- if (SUCCEEDED(hr))
- {
- WCHAR szFileW[MAX_PATH];
- LPTSTR pszTemp;
- SHTCharToUnicode(pszFileName, szFileW, ARRAYSIZE(szFileW));
- ppf->Load(szFileW, STGM_READ);
- hr = purl->GetURL(&pszTemp); // Wow, an ANSI/UNICODE COM interface!
- if (EVAL(SUCCEEDED(hr)))
- {
- StrCpyN(pszFileName, pszTemp, cchFileName);
- CoTaskMemFree(pszTemp);
- }
- ppf->Release();
- }
- purl->Release();
- }
- }
- }
- }
- }
- void GetMyCurHomePageStartPos(int *piLeft, int *piTop, DWORD *pdwWidth, DWORD *pdwHeight)
- {
- #define INVALID_POS 0x80000000
- HKEY hkey;
- //
- // Assume nothing.
- //
- *piLeft = INVALID_POS;
- *piTop = INVALID_POS;
- *pdwWidth = INVALID_POS;
- *pdwHeight = INVALID_POS;
- //
- // Read from registry first.
- //
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\Microsoft\Internet Explorer\Main"), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)
- {
- DWORD dwType, cbData;
- cbData = SIZEOF(*piLeft);
- SHQueryValueEx(hkey, TEXT("MyCurHome_Left"), NULL, &dwType, (LPBYTE)piLeft, &cbData);
- cbData = SIZEOF(*piTop);
- SHQueryValueEx(hkey, TEXT("MyCurHome_Top"), NULL, &dwType, (LPBYTE)piTop, &cbData);
- cbData = SIZEOF(*pdwWidth);
- SHQueryValueEx(hkey, TEXT("MyCurHome_Width"), NULL, &dwType, (LPBYTE)pdwWidth, &cbData);
- cbData = SIZEOF(*pdwHeight);
- SHQueryValueEx(hkey, TEXT("MyCurHome_Height"), NULL, &dwType, (LPBYTE)pdwHeight, &cbData);
- RegCloseKey(hkey);
- }
- //
- // Fill in defaults when registry provides no info.
- //
- if (*piLeft == INVALID_POS)
- {
- *piLeft = -MYCURHOME_WIDTH;
- }
- if (*piTop == INVALID_POS)
- {
- *piTop = MYCURHOME_TOP;
- }
- if (*pdwWidth == INVALID_POS)
- {
- *pdwWidth = MYCURHOME_WIDTH;
- }
- if (*pdwHeight == INVALID_POS)
- {
- *pdwHeight = MYCURHOME_HEIGHT;
- }
- //
- // Convert negative values into positive ones.
- //
- RECT rect;
- SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, FALSE);
- if (*piLeft < 0)
- {
- *piLeft += (rect.right - rect.left) - *pdwWidth;
- }
- if (*piTop < 0)
- {
- *piTop += (rect.bottom - rect.top) - *pdwHeight;
- }
- // Find the virtual dimensions.
- EnumMonitorsArea ema;
- GetMonitorSettings(&ema);
- // Position it in the primary monitor.
- *piLeft -= ema.rcVirtualMonitor.left;
- *piTop -= ema.rcVirtualMonitor.top;
- #undef INVALID_POS
- }
- //
- // Silently adds a specified component to the desktop and use the given
- // apply flags using which you can avoid nested unnecessary HTML generation,
- // or refreshing which may lead to racing conditions.
- //
- //
- BOOL AddDesktopComponentNoUI(DWORD dwApplyFlags, LPCTSTR pszUrl, LPCTSTR pszFriendlyName, int iCompType, int iLeft, int iTop, int iWidth, int iHeight, BOOL fChecked, DWORD dwCurItemState, BOOL fNoScroll, BOOL fCanResize)
- {
- COMPONENTA Comp;
- BOOL fRet = FALSE;
- HRESULT hres;
- //
- // Build the pcomp structure.
- //
- Comp.dwSize = sizeof(COMPONENTA);
- Comp.dwID = -1;
- Comp.iComponentType = iCompType;
- Comp.fChecked = fChecked;
- Comp.fDirty = FALSE;
- Comp.fNoScroll = fNoScroll;
- Comp.cpPos.dwSize = SIZEOF(COMPPOS);
- Comp.cpPos.iLeft = iLeft;
- Comp.cpPos.iTop = iTop;
- Comp.cpPos.dwWidth = iWidth;
- Comp.cpPos.dwHeight = iHeight;
- Comp.cpPos.izIndex = (dwCurItemState & IS_NORMAL) ? COMPONENT_TOP : 0;
- Comp.cpPos.fCanResize = fCanResize;
- Comp.cpPos.fCanResizeX = fCanResize;
- Comp.cpPos.fCanResizeY = fCanResize;
- Comp.cpPos.iPreferredLeftPercent = 0;
- Comp.cpPos.iPreferredTopPercent = 0;
- Comp.dwCurItemState = dwCurItemState;
- lstrcpyn(Comp.szSource, pszUrl, ARRAYSIZE(Comp.szSource));
- lstrcpyn(Comp.szSubscribedURL, pszUrl, ARRAYSIZE(Comp.szSource));
- if (pszFriendlyName)
- {
- lstrcpyn(Comp.szFriendlyName, pszFriendlyName, ARRAYSIZE(Comp.szFriendlyName));
- }
- else
- {
- Comp.szFriendlyName[0] = TEXT('');
- }
- IActiveDesktop *pActiveDesk;
- //
- // Add it to the system.
- //
- hres = CActiveDesktop_InternalCreateInstance((LPUNKNOWN *)&pActiveDesk, IID_IActiveDesktop);
- if (SUCCEEDED(hres))
- {
- COMPONENT CompW;
- CompW.dwSize = sizeof(CompW); //Required for the MultiCompToWideComp to work properly.
- MultiCompToWideComp(&Comp, &CompW);
- pActiveDesk->AddDesktopItem(&CompW, 0);
- pActiveDesk->ApplyChanges(dwApplyFlags);
- pActiveDesk->Release();
- fRet = TRUE;
- }
- return fRet;
- }
- // Little helper function used to change the safemode state
- void SetSafeMode(DWORD dwFlags)
- {
- IActiveDesktopP * piadp;
- if (SUCCEEDED(CActiveDesktop_InternalCreateInstance((LPUNKNOWN *)&piadp, IID_IActiveDesktopP)))
- {
- piadp->SetSafeMode(dwFlags);
- piadp->Release();
- }
- }
- /****************************************************************************
- *
- * RefreshWebViewDesktop - regenerates desktop HTML from registry and updates
- * the screen
- *
- * ENTRY:
- * none
- *
- * RETURNS:
- * TRUE on success
- *
- ****************************************************************************/
- BOOL PokeWebViewDesktop(DWORD dwFlags)
- {
- IActiveDesktop *pad;
- HRESULT hres;
- BOOL fRet = FALSE;
- hres = CActiveDesktop_InternalCreateInstance((LPUNKNOWN *)&pad, IID_IActiveDesktop);
- if (SUCCEEDED(hres))
- {
- pad->ApplyChanges(dwFlags);
- pad->Release();
- fRet = TRUE;
- }
- return (fRet);
- }
- #ifdef WE_WANT_DEFAULT_WALLPAPER
- //The following is needed only if we add a default wallpaper.
- void SetDefaultWallpaper()
- {
- IActiveDesktop *pad;
- if (SUCCEEDED(CActiveDesktop_InternalCreateInstance((LPUNKNOWN *)&pad, IID_IActiveDesktop)))
- {
- DWORD dwWallpaperStyle;
- WALLPAPEROPT wpo;
- // If we have a wallpaper at the old location in the registry, we use it as the default
- TCHAR szWallpaper[INTERNET_MAX_URL_LENGTH];
- // Read the Wallpaper from the Old location.
- if(!GetStringFromReg(HKEY_CURRENT_USER, REGSTR_PATH_DESKTOP, REG_VAL_GENERAL_WALLPAPER, c_szNULL, szWallpaper, ARRAYSIZE(szWallpaper)))
- szWallpaper[0] = TEXT('');
- TrimWhiteSpace(szWallpaper);
- // Read the wallpaper style
- ReadWallpaperStyleFromReg(REGSTR_PATH_DESKTOP, &dwWallpaperStyle, FALSE);
- wpo.dwSize = SIZEOF(WALLPAPEROPT);
- pad->GetWallpaperOptions(&wpo, 0);
- wpo.dwStyle = dwWallpaperStyle; //Set the wallpaper style!
- pad->SetWallpaperOptions(&wpo, 0); //Set the wallpaper style options.
- TCHAR szDefaultWallpaper[MAX_PATH];
- GetDefaultWallpaper(szDefaultWallpaper, SIZECHARS(szDefaultWallpaper));
- if(szWallpaper[0] == TEXT('') || lstrcmpi(szWallpaper, g_szNone) == 0)
- {
- lstrcpy(szWallpaper, szDefaultWallpaper);
- }
- WCHAR *pwszWallpaper;
- #ifndef UNICODE
- WCHAR wszWallpaper[INTERNET_MAX_URL_LENGTH];
- SHAnsiToUnicode(szWallpaper, wszWallpaper, ARRAYSIZE(wszWallpaper));
- pwszWallpaper = wszWallpaper;
- #else
- pwszWallpaper = szWallpaper;
- #endif
- pad->SetWallpaper(pwszWallpaper, 0);
- pad->ApplyChanges(AD_APPLY_SAVE);
- pad->Release();
- // This is a kinda hack, but the best possible solution right now. The scenario is as follows.
- // The Memphis setup guys replace what the user specifies as the wallpaper in the old location
- // and restore it after setup is complete. But, SetDefaultWallpaper() gets called bet. these
- // two times and we are supposed to take a decision on whether to set the default htm wallpaper or not,
- // depending on what the user had set before the installation. The solution is to delay making
- // this decision until after the setup guys have restored the user's wallpaper. We do this in
- // CActiveDesktop::_ReadWallpaper(). We specify that SetDefaultWallpaper() was called by setting
- // the backup wallpaper in the new location to the default wallpaper.
- TCHAR szDeskcomp[MAX_PATH];
- wsprintf(szDeskcomp, REG_DESKCOMP_GENERAL, TEXT("\"));
- SHSetValue(HKEY_CURRENT_USER, szDeskcomp,
- REG_VAL_GENERAL_BACKUPWALLPAPER, REG_SZ, (LPBYTE)szDefaultWallpaper,
- SIZEOF(TCHAR)*(lstrlen(szDefaultWallpaper)+1));
- }
- }
- #endif // IF_WE_WANT_DEFAULT_WALLPAPER
- #define CCH_NONE 20 //big enough for "(None)" in german
- TCHAR g_szNone[CCH_NONE] = {0};
- void InitDeskHtmlGlobals(void)
- {
- static fGlobalsInited = FALSE;
- if (fGlobalsInited == FALSE)
- {
- LoadString(HINST_THISDLL, IDS_WPNONE, g_szNone, ARRAYSIZE(g_szNone));
- fGlobalsInited = TRUE;
- }
- }
- //
- // Loads the preview bitmap for property sheet pages.
- //
- HBITMAP LoadMonitorBitmap(void)
- {
- HBITMAP hbm,hbmT;
- BITMAP bm;
- HBRUSH hbrT;
- HDC hdc;
- COLORREF c3df = GetSysColor(COLOR_3DFACE);
- hbm = LoadBitmap(HINST_THISDLL, MAKEINTRESOURCE(IDB_MONITOR));
- if (hbm == NULL)
- {
- return NULL;
- }
- //
- // Convert the "base" of the monitor to the right color.
- //
- // The lower left of the bitmap has a transparent color
- // we fixup using FloodFill
- //
- hdc = CreateCompatibleDC(NULL);
- hbmT = (HBITMAP)SelectObject(hdc, hbm);
- hbrT = (HBRUSH)SelectObject(hdc, GetSysColorBrush(COLOR_3DFACE));
- GetObject(hbm, sizeof(bm), &bm);
- ExtFloodFill(hdc, 0, bm.bmHeight-1, GetPixel(hdc, 0, bm.bmHeight-1), FLOODFILLSURFACE);
- //
- // Round off the corners.
- // The bottom two were done by the floodfill above.
- // The top left is important since SS_CENTERIMAGE uses it to fill gaps.
- // The top right should be rounded because the other three are.
- //
- SetPixel( hdc, 0, 0, c3df );
- SetPixel( hdc, bm.bmWidth-1, 0, c3df );
- //
- // Fill in the desktop here.
- //
- HBRUSH hbrOld = (HBRUSH)SelectObject(hdc, GetSysColorBrush(COLOR_DESKTOP));
- PatBlt(hdc, MON_X, MON_Y, MON_DX, MON_DY, PATCOPY);
- SelectObject(hdc, hbrOld);
- //
- // Clean up after ourselves.
- //
- SelectObject(hdc, hbrT);
- SelectObject(hdc, hbmT);
- DeleteDC(hdc);
- return hbm;
- }
- STDAPI_(DWORD) GetDesktopFlags(void)
- {
- DWORD dwFlags = 0, dwType, cbSize = SIZEOF(dwFlags);
- TCHAR lpszDeskcomp[MAX_PATH];
- GetRegLocation(lpszDeskcomp, SIZECHARS(lpszDeskcomp), REG_DESKCOMP_COMPONENTS, NULL);
- SHGetValue(HKEY_CURRENT_USER, lpszDeskcomp, REG_VAL_COMP_GENFLAGS, &dwType, &dwFlags, &cbSize);
- return dwFlags;
- }
- STDAPI_(BOOL) SetDesktopFlags(DWORD dwMask, DWORD dwNewFlags)
- {
- BOOL fRet = FALSE;
- HKEY hkey;
- DWORD dwDisposition;
- TCHAR lpszDeskcomp[MAX_PATH];
- GetRegLocation(lpszDeskcomp, SIZECHARS(lpszDeskcomp), REG_DESKCOMP_COMPONENTS, NULL);
- if (RegCreateKeyEx(HKEY_CURRENT_USER, (LPCTSTR)lpszDeskcomp,
- 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hkey,
- &dwDisposition) == ERROR_SUCCESS)
- {
- DWORD dwFlags;
- DWORD cbSize = SIZEOF(dwFlags);
- DWORD dwType;
- if (SHQueryValueEx(hkey, REG_VAL_COMP_GENFLAGS, NULL, &dwType,
- (LPBYTE)&dwFlags, &cbSize) != ERROR_SUCCESS)
- {
- dwFlags = 0;
- }
- dwFlags = (dwFlags & ~dwMask) | (dwNewFlags & dwMask);
- if (RegSetValueEx(hkey, REG_VAL_COMP_GENFLAGS, 0, REG_DWORD,
- (LPBYTE)&dwFlags, sizeof(dwFlags)) == ERROR_SUCCESS)
- {
- fRet = TRUE;
- }
- RegCloseKey(hkey);
- }
- return fRet;
- }
- BOOL UpdateComponentFlags(LPCTSTR pszCompId, DWORD dwMask, DWORD dwNewFlags)
- {
- BOOL fRet = FALSE;
- TCHAR szRegPath[MAX_PATH];
- HKEY hkey;
- GetRegLocation(szRegPath, SIZECHARS(szRegPath), REG_DESKCOMP_COMPONENTS, NULL);
- lstrcat(szRegPath, TEXT("\"));
- lstrcat(szRegPath, pszCompId);
- //Don't use RegCreateKeyEx here. It will result in Null components to be added.
- if (RegOpenKeyEx(HKEY_CURRENT_USER, szRegPath, 0,
- KEY_READ | KEY_WRITE, &hkey) == ERROR_SUCCESS)
- {
- DWORD dwType, dwFlags, dwDataLength;
- dwDataLength = sizeof(DWORD);
- if(SHQueryValueEx(hkey, REG_VAL_COMP_FLAGS, NULL, &dwType, (LPBYTE)&dwFlags, &dwDataLength) != ERROR_SUCCESS)
- {
- dwFlags = 0;
- }
- dwNewFlags = (dwFlags & ~dwMask) | (dwNewFlags & dwMask);
- if (RegSetValueEx(hkey, REG_VAL_COMP_FLAGS, 0, REG_DWORD, (LPBYTE)&dwNewFlags,
- SIZEOF(DWORD)) == ERROR_SUCCESS)
- {
- fRet = TRUE;
- }
- SetDesktopFlags(COMPONENTS_DIRTY, COMPONENTS_DIRTY);
- RegCloseKey(hkey);
- }
- else
- {
- TraceMsg(TF_WARNING, "DS: Unable to UpdateComponentFlags");
- }
- return fRet;
- }
- DWORD GetCurrentState(LPTSTR pszCompId)
- {
- TCHAR szRegPath[MAX_PATH];
- DWORD cbSize, dwType, dwCurState;
- GetRegLocation(szRegPath, SIZECHARS(szRegPath), REG_DESKCOMP_COMPONENTS, NULL);
- lstrcat(szRegPath, TEXT("\"));
- lstrcat(szRegPath, pszCompId);
- cbSize = sizeof(dwCurState);
- if (SHGetValue(HKEY_CURRENT_USER, szRegPath, REG_VAL_COMP_CURSTATE, &dwType, &dwCurState, &cbSize) != ERROR_SUCCESS)
- dwCurState = IS_NORMAL;
- return dwCurState;
- }
- BOOL GetSavedStateInfo(LPTSTR pszCompId, LPCOMPSTATEINFO pCompState, BOOL fRestoredState)
- {
- BOOL fRet = FALSE;
- TCHAR szRegPath[MAX_PATH];
- HKEY hkey;
- LPTSTR lpValName = (fRestoredState ? REG_VAL_COMP_RESTOREDSTATEINFO : REG_VAL_COMP_ORIGINALSTATEINFO);
- GetRegLocation(szRegPath, SIZECHARS(szRegPath), REG_DESKCOMP_COMPONENTS, NULL);
- lstrcat(szRegPath, TEXT("\"));
- lstrcat(szRegPath, pszCompId);
- //No need to use RegCreateKeyEx here. Use RegOpenKeyEx instead.
- if (RegOpenKeyEx(HKEY_CURRENT_USER, szRegPath, 0,
- KEY_READ, &hkey) == ERROR_SUCCESS)
- {
- DWORD cbSize, dwType;
- cbSize = SIZEOF(*pCompState);
- dwType = REG_BINARY;
- if (SHQueryValueEx(hkey, lpValName, NULL, &dwType, (LPBYTE)pCompState, &cbSize) != ERROR_SUCCESS)
- {
- //If the item state is missing, read the item current position and
- // and return that as the saved state.
- COMPPOS cpPos;
- cbSize = SIZEOF(cpPos);
- dwType = REG_BINARY;
- if (SHQueryValueEx(hkey, REG_VAL_COMP_POSITION, NULL, &dwType, (LPBYTE)&cpPos, &cbSize) != ERROR_SUCCESS)
- {
- ZeroMemory(&cpPos, SIZEOF(cpPos));
- }
- SetStateInfo(pCompState, &cpPos, IS_NORMAL);
- }
- RegCloseKey(hkey);
- }
- else
- TraceMsg(TF_WARNING, "DS: Unable to get SavedStateInfo()");
- return fRet;
- }
- BOOL UpdateDesktopPosition(LPTSTR pszCompId, int iLeft, int iTop, DWORD dwWidth, DWORD dwHeight, int izIndex,
- BOOL fSaveRestorePos, BOOL fSaveOriginal, DWORD dwCurState)
- {
- BOOL fRet = FALSE;
- TCHAR szRegPath[MAX_PATH];
- HKEY hkey;
- GetRegLocation(szRegPath, SIZECHARS(szRegPath), REG_DESKCOMP_COMPONENTS, NULL);
- lstrcat(szRegPath, TEXT("\"));
- lstrcat(szRegPath, pszCompId);
- //Don't use RegCreateKeyEx here; It will result in a NULL component being added.
- if (RegOpenKeyEx(HKEY_CURRENT_USER, szRegPath, 0,
- KEY_READ | KEY_WRITE, &hkey) == ERROR_SUCCESS)
- {
- COMPPOS cp;
- DWORD dwType;
- DWORD dwDataLength;
- COMPSTATEINFO csi;
- dwType = REG_BINARY;
- dwDataLength = sizeof(COMPPOS);
- if(SHQueryValueEx(hkey, REG_VAL_COMP_POSITION, NULL, &dwType, (LPBYTE)&cp, &dwDataLength) != ERROR_SUCCESS)
- {
- cp.fCanResize = cp.fCanResizeX = cp.fCanResizeY = TRUE;
- cp.iPreferredLeftPercent = cp.iPreferredTopPercent = 0;
- }
- //Read the current State
- dwType = REG_DWORD;
- dwDataLength = SIZEOF(csi.dwItemState);
- if (SHQueryValueEx(hkey, REG_VAL_COMP_CURSTATE, NULL, &dwType, (LPBYTE)&csi.dwItemState, &dwDataLength) != ERROR_SUCCESS)
- {
- csi.dwItemState = IS_NORMAL;
- }
- if(fSaveRestorePos)
- {
- //We have just read the current position; Let's save it as the restore position.
- SetStateInfo(&csi, &cp, csi.dwItemState);
- //Now that we know the complete current state, save it as the restore state!
- RegSetValueEx(hkey, REG_VAL_COMP_RESTOREDSTATEINFO, 0, REG_BINARY, (LPBYTE)&csi, SIZEOF(csi));
- }
- //Save the current state too!
- if(dwCurState)
- RegSetValueEx(hkey, REG_VAL_COMP_CURSTATE, 0, REG_DWORD, (LPBYTE)&dwCurState, SIZEOF(dwCurState));
- cp.dwSize = sizeof(COMPPOS);
- cp.iLeft = iLeft;
- cp.iTop = iTop;
- cp.dwWidth = dwWidth;
- cp.dwHeight = dwHeight;
- cp.izIndex = izIndex;
- if (fSaveOriginal) {
- SetStateInfo(&csi, &cp, csi.dwItemState);
- RegSetValueEx(hkey, REG_VAL_COMP_ORIGINALSTATEINFO, 0, REG_BINARY, (LPBYTE)&csi, SIZEOF(csi));
- }
- if (RegSetValueEx(hkey, REG_VAL_COMP_POSITION, 0, REG_BINARY, (LPBYTE)&cp,
- SIZEOF(cp)) == ERROR_SUCCESS)
- {
- fRet = TRUE;
- }
- // Don't need to mark as dirty if we're just saving the original pos
- if (!fSaveOriginal)
- SetDesktopFlags(COMPONENTS_DIRTY, COMPONENTS_DIRTY);
- RegCloseKey(hkey);
- }
- else
- {
- TraceMsg(TF_WARNING, "DS: Unable to UpdateDesktopPosition");
- }
- return fRet;
- }
- void EnsureFilePathIsPresent (LPCTSTR pszFilePath)
- // Recursively process (in reverse) a path and create the first
- // directory that does not exist and when unwinding the calling
- // chain create each subsequent directory in the path until the
- // whole original path is created.
- {
- TCHAR szDesktopFileDirectory[MAX_PATH];
- lstrcpy(szDesktopFileDirectory, pszFilePath);
- ASSERT(lstrlen(szDesktopFileDirectory) > lstrlen(TEXT("C:\"))); // something wrong if the root directory is hit
- if ((PathRemoveFileSpec(szDesktopFileDirectory) != 0) && (GetFileAttributes(szDesktopFileDirectory) == 0xFFFFFFFF) && (CreateDirectory(szDesktopFileDirectory, NULL) == 0))
- {
- EnsureFilePathIsPresent(szDesktopFileDirectory);
- TBOOL(CreateDirectory(szDesktopFileDirectory, NULL));
- }
- }
- void GetPerUserFileName(LPTSTR pszOutputFileName, DWORD dwSize, LPTSTR pszPartialFileName)
- {
- LPITEMIDLIST pidlAppData;
- *pszOutputFileName = TEXT('');
- if(dwSize < MAX_PATH)
- {
- ASSERT(FALSE);
- return;
- }
- if(EVAL(SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidlAppData))))
- {
- SHGetPathFromIDList(pidlAppData, pszOutputFileName);
- PathAppend(pszOutputFileName, pszPartialFileName);
- ILFree(pidlAppData);
- }
- EnsureFilePathIsPresent(pszOutputFileName);
- }
- void GetRegLocation(LPTSTR lpszResult, DWORD cchResult, LPCTSTR lpszKey, LPCTSTR lpszScheme)
- {
- TCHAR szSubkey[MAX_PATH];
- DWORD dwDataLength = sizeof(szSubkey) - 2 * sizeof(TCHAR);
- DWORD dwType;
- lstrcpy(szSubkey, TEXT("\"));
- // use what was given or get it from the registry
- if (lpszScheme)
- StrCatBuff(szSubkey, lpszScheme, SIZECHARS(szSubkey));
- else
- SHGetValue(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME, REG_VAL_SCHEME_DISPLAY, &dwType,
- (LPBYTE)(szSubkey) + sizeof(TCHAR), &dwDataLength);
- if (szSubkey[1])
- StrCatBuff(szSubkey, TEXT("\"), SIZECHARS(szSubkey));
- wnsprintf(lpszResult, cchResult, lpszKey, szSubkey);
- }
- BOOL ValidateFileName(HWND hwnd, LPCTSTR pszFilename, int iTypeString)
- {
- BOOL fRet = TRUE;
- DWORD dwAttributes = GetFileAttributes(pszFilename);
- if ((dwAttributes != 0xFFFFFFFF) &&
- (dwAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
- {
- TCHAR szType1[64];
- TCHAR szType2[64];
- LoadString(HINST_THISDLL, iTypeString, szType1, ARRAYSIZE(szType1));
- LoadString(HINST_THISDLL, iTypeString+1, szType2, ARRAYSIZE(szType2));
- if (ShellMessageBox(HINST_THISDLL, hwnd,
- MAKEINTRESOURCE(IDS_VALIDFN_FMT),
- MAKEINTRESOURCE(IDS_VALIDFN_TITLE),
- MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2,
- szType1, szType2) == IDNO)
- {
- fRet = FALSE;
- }
- }
- return fRet;
- }
- void GetWallpaperDirName(LPTSTR lpszWallPaperDir, int iBuffSize)
- {
- //Compute the default wallpaper name.
- GetWindowsDirectory(lpszWallPaperDir, iBuffSize);
- lstrcat(lpszWallPaperDir, DESKTOPHTML_WEB_DIR);
- //Read it from the registry key, if it is set!
- DWORD dwType;
- DWORD cbData = (DWORD)iBuffSize;
- SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP, c_szWallPaperDir, &dwType, (LPVOID)lpszWallPaperDir, &cbData);
- // BUGBUG: Currently the type is wrongly being set to REG_SZ. When this is changed by setup, uncomment the if() below.
- // if (dwType == REG_EXPAND_SZ)
- {
- TCHAR szExp[MAX_PATH];
- SHExpandEnvironmentStrings(lpszWallPaperDir, szExp, ARRAYSIZE(szExp));
- lstrcpyn(lpszWallPaperDir, szExp, iBuffSize);
- }
- }
- BOOL CALLBACK MultiMonEnumAreaCallBack(HMONITOR hMonitor, HDC hdc, LPRECT lprc, LPARAM lData)
- {
- EnumMonitorsArea* pEMA = (EnumMonitorsArea*)lData;
- if (pEMA->iMonitors > LV_MAX_WORKAREAS - 1)
- {
- //ignore the other monitors because we can only handle up to LV_MAX_WORKAREAS
- //BUGBUG: should we dynamically allocate this?
- return FALSE;
- }
- GetMonitorRect(hMonitor, &pEMA->rcMonitor[pEMA->iMonitors]);
- GetMonitorWorkArea(hMonitor, &pEMA->rcWorkArea[pEMA->iMonitors]);
- if(pEMA->iMonitors == 0)
- {
- pEMA->rcVirtualMonitor.left = pEMA->rcMonitor[0].left;
- pEMA->rcVirtualMonitor.top = pEMA->rcMonitor[0].top;
- pEMA->rcVirtualMonitor.right = pEMA->rcMonitor[0].right;
- pEMA->rcVirtualMonitor.bottom = pEMA->rcMonitor[0].bottom;
- pEMA->rcVirtualWorkArea.left = pEMA->rcWorkArea[0].left;
- pEMA->rcVirtualWorkArea.top = pEMA->rcWorkArea[0].top;
- pEMA->rcVirtualWorkArea.right = pEMA->rcWorkArea[0].right;
- pEMA->rcVirtualWorkArea.bottom = pEMA->rcWorkArea[0].bottom;
- }
- else
- {
- if(pEMA->rcMonitor[pEMA->iMonitors].left < pEMA->rcVirtualMonitor.left)
- {
- pEMA->rcVirtualMonitor.left = pEMA->rcMonitor[pEMA->iMonitors].left;
- }
- if(pEMA->rcMonitor[pEMA->iMonitors].top < pEMA->rcVirtualMonitor.top)
- {
- pEMA->rcVirtualMonitor.top = pEMA->rcMonitor[pEMA->iMonitors].top;
- }
- if(pEMA->rcMonitor[pEMA->iMonitors].right > pEMA->rcVirtualMonitor.right)
- {
- pEMA->rcVirtualMonitor.right = pEMA->rcMonitor[pEMA->iMonitors].right;
- }
- if(pEMA->rcMonitor[pEMA->iMonitors].bottom > pEMA->rcVirtualMonitor.bottom)
- {
- pEMA->rcVirtualMonitor.bottom = pEMA->rcMonitor[pEMA->iMonitors].bottom;
- }
- if(pEMA->rcWorkArea[pEMA->iMonitors].left < pEMA->rcVirtualWorkArea.left)
- {
- pEMA->rcVirtualWorkArea.left = pEMA->rcWorkArea[pEMA->iMonitors].left;
- }
- if(pEMA->rcWorkArea[pEMA->iMonitors].top < pEMA->rcVirtualWorkArea.top)
- {
- pEMA->rcVirtualWorkArea.top = pEMA->rcWorkArea[pEMA->iMonitors].top;
- }
- if(pEMA->rcWorkArea[pEMA->iMonitors].right > pEMA->rcVirtualWorkArea.right)
- {
- pEMA->rcVirtualWorkArea.right = pEMA->rcWorkArea[pEMA->iMonitors].right;
- }
- if(pEMA->rcWorkArea[pEMA->iMonitors].bottom > pEMA->rcVirtualWorkArea.bottom)
- {
- pEMA->rcVirtualWorkArea.bottom = pEMA->rcWorkArea[pEMA->iMonitors].bottom;
- }
- }
- pEMA->iMonitors++;
- return TRUE;
- }
- void GetMonitorSettings(EnumMonitorsArea* ema)
- {
- ema->iMonitors = 0;
- ema->rcVirtualMonitor.left = 0;
- ema->rcVirtualMonitor.top = 0;
- ema->rcVirtualMonitor.right = 0;
- ema->rcVirtualMonitor.bottom = 0;
- ema->rcVirtualWorkArea.left = 0;
- ema->rcVirtualWorkArea.top = 0;
- ema->rcVirtualWorkArea.right = 0;
- ema->rcVirtualWorkArea.bottom = 0;
- EnumDisplayMonitors(NULL, NULL, MultiMonEnumAreaCallBack, (LPARAM)ema);
- }
- int _GetWorkAreaIndexWorker(POINT pt, LPCRECT prect, int crect)
- {
- int iIndex;
- for (iIndex = 0; iIndex < crect; iIndex++)
- {
- if (PtInRect(&prect[iIndex], pt))
- {
- return iIndex;
- }
- }
- return -1;
- }
- int GetWorkAreaIndexFromPoint(POINT pt, LPCRECT prect, int crect)
- {
- ASSERT(crect);
- // Map to correct coords...
- pt.x += prect[0].left;
- pt.y += prect[0].top;
- return _GetWorkAreaIndexWorker(pt, prect, crect);
- }
- int GetWorkAreaIndex(COMPPOS *pcp, LPCRECT prect, int crect, LPPOINT lpptVirtualTopLeft)
- {
- POINT ptComp;
- ptComp.x = pcp->iLeft + lpptVirtualTopLeft->x;
- ptComp.y = pcp->iTop + lpptVirtualTopLeft->y;
- return _GetWorkAreaIndexWorker(ptComp, prect, crect);
- }
- // Prepends the Web wallpaper directory or the system directory to szWallpaper, if necessary
- // (i.e., if the path is not specified). The return value is in szWallpaperWithPath, which is iBufSize
- // bytes long
- void GetWallpaperWithPath(LPCTSTR szWallpaper, LPTSTR szWallpaperWithPath, int iBufSize)
- {
- if(szWallpaper[0] && lstrcmpi(szWallpaper, g_szNone) != 0 && !StrChr(szWallpaper, TEXT('\'))
- && !StrChr(szWallpaper, TEXT(':'))) // The file could be d:foo.bmp
- {
- // If the file is a normal wallpaper, we prepend the windows directory to the filename
- if(IsNormalWallpaper(szWallpaper))
- {
- GetWindowsDirectory(szWallpaperWithPath, iBufSize);
- }
- // else we prepend the wallpaper directory to the filename
- else
- {
- GetWallpaperDirName(szWallpaperWithPath, iBufSize);
- }
- lstrcat(szWallpaperWithPath, TEXT("\"));
- lstrcat(szWallpaperWithPath, szWallpaper);
- }
- else
- {
- lstrcpyn(szWallpaperWithPath, szWallpaper, iBufSize);
- }
- }
- #ifdef WE_WANT_DEFAULT_WALLPAPER
- // The default wallpaper's name might be different depending on the platform. Hence this function.
- void GetDefaultWallpaper(LPTSTR psz, DWORD cch)
- {
- GetWallpaperDirName(psz, cch);
- StrCatBuff(psz, TEXT("\"), cch);
- if (g_bRunOnMemphis)
- {
- StrCatBuff(psz, DESKTOPHTML_DEFAULT_MEMPHIS_WALLPAPER, cch);
- }
- else if (g_bRunOnNT5)
- {
- StrCatBuff(psz, DESKTOPHTML_DEFAULT_NT5_WALLPAPER, cch);
- }
- else
- {
- StrCatBuff(psz, DESKTOPHTML_DEFAULT_WALLPAPER, cch);
- }
- }
- #endif //WE_WANT_DEFAULT_WALLPAPER
- BOOL GetViewAreas(LPRECT lprcViewAreas, int* pnViewAreas)
- {
- BOOL bRet = FALSE;
- HWND hwndDesktop = GetShellWindow(); // This is the "normal" desktop
- if (hwndDesktop && IsWindow(hwndDesktop))
- {
- DWORD dwProcID, dwCurrentProcID;
- GetWindowThreadProcessId(hwndDesktop, &dwProcID);
- dwCurrentProcID = GetCurrentProcessId();
- if (dwCurrentProcID == dwProcID) {
- SendMessage(hwndDesktop, DTM_GETVIEWAREAS, (WPARAM)pnViewAreas, (LPARAM)lprcViewAreas);
- if (*pnViewAreas <= 0)
- {
- bRet = FALSE;
- }
- else
- {
- bRet = TRUE;
- }
- }
- else
- {
- bRet = FALSE;
- }
- }
- return bRet;
- }
- // We need to enforce a minimum size for the deskmovr caption since it doesn't look
- // right drawn any smaller
- int GetcyCaption()
- {
- int cyCaption = GetSystemMetrics(SM_CYSMCAPTION);
- if (cyCaption < 15)
- cyCaption = 15;
- cyCaption -= GetSystemMetrics(SM_CYBORDER);
- return cyCaption;
- }