diff --git a/reactos/dll/cpl/desk/advmon.c b/reactos/dll/cpl/desk/advmon.c new file mode 100644 index 00000000000..34bad861459 --- /dev/null +++ b/reactos/dll/cpl/desk/advmon.c @@ -0,0 +1,187 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Display Control Panel + * FILE: dll/cpl/desk/advmon.c + * PURPOSE: Advanced monitor/display settings + */ + +#include "desk.h" + +#define MAX_ADVANCED_PAGES 32 + +static BOOL CALLBACK +PropSheetAddPage(HPROPSHEETPAGE hpage, LPARAM lParam) +{ + PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam; + if (ppsh != NULL && ppsh->nPages < MAX_ADVANCED_PAGES) + { + ppsh->phpage[ppsh->nPages++] = hpage; + return TRUE; + } + + return FALSE; +} + +static BOOL +InitPropSheetPage(PROPSHEETHEADER *ppsh, WORD idDlg, DLGPROC DlgProc, LPARAM lParam) +{ + HPROPSHEETPAGE hPage; + PROPSHEETPAGE psp; + + if (ppsh->nPages < MAX_ADVANCED_PAGES) + { + ZeroMemory(&psp, sizeof(psp)); + psp.dwSize = sizeof(psp); + psp.dwFlags = PSP_DEFAULT; + psp.hInstance = hApplet; + psp.pszTemplate = MAKEINTRESOURCE(idDlg); + psp.pfnDlgProc = DlgProc; + psp.lParam = lParam; + + hPage = CreatePropertySheetPage(&psp); + if (hPage != NULL) + { + return PropSheetAddPage(hPage, (LPARAM)ppsh); + } + } + + return FALSE; +} + +static INT_PTR CALLBACK +AdvGeneralPageProc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + PDISPLAY_DEVICE_ENTRY DispDevice = NULL; + INT_PTR Ret = 0; + + if (uMsg != WM_INITDIALOG) + DispDevice = (PDISPLAY_DEVICE_ENTRY)GetWindowLongPtr(hwndDlg, DWLP_USER); + + switch (uMsg) + { + case WM_INITDIALOG: + DispDevice = (PDISPLAY_DEVICE_ENTRY)(((LPPROPSHEETPAGE)lParam)->lParam); + SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)DispDevice); + + Ret = TRUE; + break; + } + + return Ret; +} + +static LPTSTR +QueryDevSettingsString(IDataObject *pdo, UINT cfFormat) +{ + FORMATETC fetc; + STGMEDIUM medium; + SIZE_T BufLen; + LPWSTR lpRecvBuffer; + LPTSTR lpStr = NULL; + + fetc.cfFormat = (CLIPFORMAT)cfFormat; + fetc.ptd = NULL; + fetc.dwAspect = DVASPECT_CONTENT; + fetc.lindex = -1; + fetc.tymed = TYMED_HGLOBAL; + + if (SUCCEEDED(IDataObject_GetData(pdo, &fetc, &medium)) && medium.hGlobal != NULL) + { + /* We always receive the string in unicode! */ + lpRecvBuffer = (LPWSTR)GlobalLock(medium.hGlobal); + + BufLen = wcslen(lpRecvBuffer) + 1; + lpStr = LocalAlloc(LMEM_FIXED, BufLen * sizeof(TCHAR)); + if (lpStr != NULL) + { +#ifdef UNICODE + wcscpy(lpStr, lpRecvBuffer); +#else + WideCharToMultiByte(CP_APC, 0, lpRecvBuffer, -1, lpStr, BufLen, NULL, NULL); +#endif + } + + GlobalUnlock(medium.hGlobal); + ReleaseStgMedium(&medium); + } + + return lpStr; +} + +static VOID +BuildAdvPropTitle(IDataObject *pdo, LPTSTR lpBuffer, DWORD dwBufferLen) +{ + UINT uiMonitorName, uiDisplayName; + LPTSTR lpMonitorName, lpDisplayName; + TCHAR szFormatBuff[32]; + + if (!LoadString(hApplet, IDS_ADVANCEDTITLEFMT, szFormatBuff, sizeof(szFormatBuff) / sizeof(szFormatBuff[0]))) + { + szFormatBuff[0] = _T('\0'); + } + + uiMonitorName = RegisterClipboardFormat(TEXT("Monitor Name")); + uiDisplayName = RegisterClipboardFormat(TEXT("Display Name")); + + lpMonitorName = QueryDevSettingsString(pdo, uiMonitorName); + lpDisplayName = QueryDevSettingsString(pdo, uiDisplayName); + + _sntprintf(lpBuffer, dwBufferLen, szFormatBuff, lpMonitorName, lpDisplayName); + + if (lpMonitorName != NULL) + LocalFree((HLOCAL)lpMonitorName); + if (lpDisplayName != NULL) + LocalFree((HLOCAL)lpDisplayName); +} + +BOOL +DisplayAdvancedSettings(HWND hWndParent, PDISPLAY_DEVICE_ENTRY DisplayDevice) +{ + TCHAR szCaption[128]; + HPROPSHEETPAGE hpsp[MAX_ADVANCED_PAGES]; + PROPSHEETHEADER psh; + HPSXA hpsxaDev, hpsxaDisp; + BOOL Ret; + IDataObject *pdo; + + /* FIXME: Build the "%s and %s" caption string for the monitor and adapter name */ + szCaption[0] = _T('\0'); + + ZeroMemory(&psh, sizeof(PROPSHEETHEADER)); + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = PSH_PROPTITLE; + psh.hwndParent = hWndParent; + psh.hInstance = hApplet; + psh.pszCaption = szCaption; + psh.phpage = hpsp; + + InitPropSheetPage(&psh, IDD_ADVANCED_GENERAL, AdvGeneralPageProc, (LPARAM)DisplayDevice); + + pdo = CreateDevSettings(DisplayDevice); + + if (pdo != NULL) + BuildAdvPropTitle(pdo, szCaption, sizeof(szCaption) / sizeof(szCaption[0])); + + hpsxaDev = SHCreatePropSheetExtArrayEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Device"), MAX_ADVANCED_PAGES - psh.nPages, pdo); + if (hpsxaDev != NULL) + SHAddFromPropSheetExtArray(hpsxaDev, PropSheetAddPage, (LPARAM)&psh); + + hpsxaDisp = SHCreatePropSheetExtArrayEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Display"), MAX_ADVANCED_PAGES - psh.nPages, pdo); + if (hpsxaDisp != NULL) + SHAddFromPropSheetExtArray(hpsxaDisp, PropSheetAddPage, (LPARAM)&psh); + + Ret = (LONG)(PropertySheet(&psh) != -1); + + if (hpsxaDisp != NULL) + SHDestroyPropSheetExtArray(hpsxaDisp); + + if (hpsxaDev != NULL) + SHDestroyPropSheetExtArray(hpsxaDev); + + IDataObject_Release(pdo); + + return Ret; +} diff --git a/reactos/dll/cpl/desk/desk.c b/reactos/dll/cpl/desk/desk.c index 4fd13d792c0..807dd24c981 100644 --- a/reactos/dll/cpl/desk/desk.c +++ b/reactos/dll/cpl/desk/desk.c @@ -33,26 +33,66 @@ APPLET Applets[NUM_APPLETS] = } }; - -static VOID -InitPropSheetPage(PROPSHEETPAGE *psp, WORD idDlg, DLGPROC DlgProc) +static BOOL CALLBACK +PropSheetAddPage(HPROPSHEETPAGE hpage, LPARAM lParam) { - ZeroMemory(psp, sizeof(PROPSHEETPAGE)); - psp->dwSize = sizeof(PROPSHEETPAGE); - psp->dwFlags = PSP_DEFAULT; - psp->hInstance = hApplet; - psp->pszTemplate = MAKEINTRESOURCE(idDlg); - psp->pfnDlgProc = DlgProc; + PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam; + if (ppsh != NULL && ppsh->nPages < MAX_DESK_PAGES) + { + ppsh->phpage[ppsh->nPages++] = hpage; + return TRUE; + } + + return FALSE; } +static BOOL +InitPropSheetPage(PROPSHEETHEADER *ppsh, WORD idDlg, DLGPROC DlgProc) +{ + HPROPSHEETPAGE hPage; + PROPSHEETPAGE psp; + + if (ppsh->nPages < MAX_DESK_PAGES) + { + ZeroMemory(&psp, sizeof(psp)); + psp.dwSize = sizeof(psp); + psp.dwFlags = PSP_DEFAULT; + psp.hInstance = hApplet; + psp.pszTemplate = MAKEINTRESOURCE(idDlg); + psp.pfnDlgProc = DlgProc; + + hPage = CreatePropertySheetPage(&psp); + if (hPage != NULL) + { + return PropSheetAddPage(hPage, (LPARAM)ppsh); + } + } + + return FALSE; +} + +static const struct +{ + WORD idDlg; + DLGPROC DlgProc; +} PropPages[] = +{ + { IDD_BACKGROUND, BackgroundPageProc }, + { IDD_SCREENSAVER, ScreenSaverPageProc }, + { IDD_APPEARANCE, AppearancePageProc }, + { IDD_SETTINGS, SettingsPageProc }, +}; /* Display Applet */ static LONG APIENTRY DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam) { - PROPSHEETPAGE psp[4]; + HPROPSHEETPAGE hpsp[MAX_DESK_PAGES]; PROPSHEETHEADER psh; + HPSXA hpsxa; TCHAR Caption[1024]; + LONG ret; + UINT i; UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(wParam); @@ -63,21 +103,41 @@ DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam) ZeroMemory(&psh, sizeof(PROPSHEETHEADER)); psh.dwSize = sizeof(PROPSHEETHEADER); - psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK | PSH_PROPTITLE; + psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE; psh.hwndParent = NULL; psh.hInstance = hApplet; psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_DESK_ICON)); psh.pszCaption = Caption; - psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); + psh.nPages = 0; psh.nStartPage = 0; - psh.ppsp = psp; + psh.phpage = hpsp; - InitPropSheetPage(&psp[0], IDD_BACKGROUND, (DLGPROC) BackgroundPageProc); - InitPropSheetPage(&psp[1], IDD_SCREENSAVER, (DLGPROC) ScreenSaverPageProc); - InitPropSheetPage(&psp[2], IDD_APPEARANCE, (DLGPROC) AppearancePageProc); - InitPropSheetPage(&psp[3], IDD_SETTINGS, (DLGPROC) SettingsPageProc); + /* Allow shell extensions to replace the background page */ + hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Desk"), MAX_DESK_PAGES - psh.nPages); - return (LONG)(PropertySheet(&psh) != -1); + for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++) + { + /* Override the background page if requested by a shell extension */ + if (PropPages[i].idDlg == IDD_BACKGROUND && hpsxa != NULL && + SHReplaceFromPropSheetExtArray(hpsxa, CPLPAGE_DISPLAY_BACKGROUND, PropSheetAddPage, (LPARAM)&psh) != 0) + { + /* The shell extension added one or more pages to replace the background page. + Don't create the built-in page anymore! */ + continue; + } + + InitPropSheetPage(&psh, PropPages[i].idDlg, PropPages[i].DlgProc); + } + + /* NOTE: Don;t call SHAddFromPropSheetExtArray here because this applet only allows + replacing the background page but not extending the applet by more pages */ + + ret = (LONG)(PropertySheet(&psh) != -1); + + if (hpsxa != NULL) + SHDestroyPropSheetExtArray(hpsxa); + + return ret; } diff --git a/reactos/dll/cpl/desk/desk.h b/reactos/dll/cpl/desk/desk.h index 3c19499ed6b..892d893da46 100644 --- a/reactos/dll/cpl/desk/desk.h +++ b/reactos/dll/cpl/desk/desk.h @@ -1,6 +1,7 @@ #ifndef __CPL_DESK_H__ #define __CPL_DESK_H__ +#define COBJMACROS #include #include #include @@ -8,6 +9,9 @@ #include #include #include +#include +#include +#include #include "resource.h" @@ -37,7 +41,51 @@ INT AllocAndLoadString(LPTSTR *lpTarget, HINSTANCE hInst, UINT uID); -DWORD DbgPrint(PCH Format,...); +ULONG __cdecl DbgPrint(PCCH Format,...); + +#define MAX_DESK_PAGES 32 + +/* As slider control can't contain user data, we have to keep an + * array of RESOLUTION_INFO to have our own associated data. + */ +typedef struct _RESOLUTION_INFO +{ + DWORD dmPelsWidth; + DWORD dmPelsHeight; +} RESOLUTION_INFO, *PRESOLUTION_INFO; + +typedef struct _SETTINGS_ENTRY +{ + struct _SETTINGS_ENTRY *Blink; + struct _SETTINGS_ENTRY *Flink; + DWORD dmBitsPerPel; + DWORD dmPelsWidth; + DWORD dmPelsHeight; +} SETTINGS_ENTRY, *PSETTINGS_ENTRY; + +typedef struct _DISPLAY_DEVICE_ENTRY +{ + struct _DISPLAY_DEVICE_ENTRY *Flink; + LPTSTR DeviceDescription; + LPTSTR DeviceName; + LPTSTR DeviceKey; + LPTSTR DeviceID; + DWORD DeviceStateFlags; + PSETTINGS_ENTRY Settings; /* sorted by increasing dmPelsHeight, BPP */ + DWORD SettingsCount; + PRESOLUTION_INFO Resolutions; + DWORD ResolutionsCount; + PSETTINGS_ENTRY CurrentSettings; /* Points into Settings list */ + SETTINGS_ENTRY InitialSettings; +} DISPLAY_DEVICE_ENTRY, *PDISPLAY_DEVICE_ENTRY; + +BOOL +DisplayAdvancedSettings(HWND hWndParent, PDISPLAY_DEVICE_ENTRY DisplayDevice); + +IDataObject * +CreateDevSettings(PDISPLAY_DEVICE_ENTRY DisplayDeviceInfo); + +HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY,LPCWSTR,UINT,IDataObject*); #endif /* __CPL_DESK_H__ */ diff --git a/reactos/dll/cpl/desk/desk.rbuild b/reactos/dll/cpl/desk/desk.rbuild index 77e85dfda48..9f97c65defe 100644 --- a/reactos/dll/cpl/desk/desk.rbuild +++ b/reactos/dll/cpl/desk/desk.rbuild @@ -15,15 +15,19 @@ gdi32 comctl32 comdlg32 + ole32 setupapi shell32 ntdll msimg32 msvcrt + uuid + advmon.c appearance.c background.c classinst.c desk.c + devsett.c dibitmap.c misc.c preview.c diff --git a/reactos/dll/cpl/desk/devsett.c b/reactos/dll/cpl/desk/devsett.c new file mode 100644 index 00000000000..9de94e079a0 --- /dev/null +++ b/reactos/dll/cpl/desk/devsett.c @@ -0,0 +1,910 @@ +/* +* COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Display Control Panel + * FILE: lib/cpl/desk/devsett.c + * PURPOSE: ReactOS Display Control Panel Shell Extension Support + */ + +#include "desk.h" + +#define NDEBUG +#include + +#define DEBUG_DEVSETTINGS + +#define DESK_EXT_CALLBACK CALLBACK + +typedef PDEVMODEW (DESK_EXT_CALLBACK *PDESK_EXT_ENUMALLMODES)(PVOID Context, DWORD Index); +typedef PDEVMODEW (DESK_EXT_CALLBACK *PDESK_EXT_GETCURRENTMODE)(PVOID Context); +typedef BOOL (DESK_EXT_CALLBACK *PDESK_EXT_SETCURRENTMODE)(PVOID Context, const DEVMODEW *pDevMode); +typedef VOID (DESK_EXT_CALLBACK *PDESK_EXT_GETPRUNINGMODE)(PVOID Context, PBOOL pbModesPruned, PBOOL pbKeyIsReadOnly, PBOOL pbPruningOn); +typedef VOID (DESK_EXT_CALLBACK *PDESK_EXT_SETPRUNINGMODE)(PVOID Context, BOOL PruningOn); + +typedef struct _DESK_EXT_INTERFACE +{ + /* NOTE: This structure is binary compatible to XP. The windows shell + extensions rely on this structure to be properly filled! */ + DWORD cbSize; + + PVOID Context; /* This value is passed on to the callback routines */ + + /* Callback routines called by the shell extensions */ + PDESK_EXT_ENUMALLMODES EnumAllModes; + PDESK_EXT_SETCURRENTMODE SetCurrentMode; + PDESK_EXT_GETCURRENTMODE GetCurrentMode; + PDESK_EXT_SETPRUNINGMODE SetPruningMode; + PDESK_EXT_GETPRUNINGMODE GetPruningMode; + + /* HardwareInformation.* values provided in the device registry key */ + WCHAR MemorySize[128]; + WCHAR ChipType[128]; + WCHAR DacType[128]; + WCHAR AdapterString[128]; + WCHAR BiosString[128]; +} DESK_EXT_INTERFACE, *PDESK_EXT_INTERFACE; + +typedef struct _CDevSettings +{ + const struct IDataObjectVtbl *lpIDataObjectVtbl; + DWORD ref; + + CLIPFORMAT cfExtInterface; /* "Desk.cpl extension interface" */ + CLIPFORMAT cfDisplayDevice; /* "Display Device" */ + CLIPFORMAT cfDisplayName; /* "Display Name" */ + CLIPFORMAT cfDisplayId; /* "Display ID" */ + CLIPFORMAT cfMonitorName; /* "Monitor Name" */ + CLIPFORMAT cfMonitorDevice; /* "Monitor Device" */ + CLIPFORMAT cfMonitorId; /* "Monitor ID" */ + CLIPFORMAT cfDisplayKey; /* "Display Key" */ + CLIPFORMAT cfDisplayStateFlags; /* "Display State Flags" */ + CLIPFORMAT cfPruningMode; /* "Pruning Mode" */ + + PWSTR pDisplayDevice; + PWSTR pDisplayName; + PWSTR pDisplayKey; + PWSTR pDisplayId; + PWSTR pMonitorName; + PWSTR pMonitorDevice; + PWSTR pMonitorId; + + DESK_EXT_INTERFACE ExtInterface; + + DWORD StateFlags; + + union + { + DWORD Flags; + struct + { + DWORD bModesPruned : 1; + DWORD bKeyIsReadOnly : 1; + DWORD bPruningOn : 1; + }; + }; +} CDevSettings, *PCDevSettings; + +#define impl_to_interface(impl,iface) (struct iface *)(&(impl)->lp##iface##Vtbl) + +static __inline PCDevSettings +impl_from_IDataObject(struct IDataObject *iface) +{ + return (PCDevSettings)((ULONG_PTR)iface - FIELD_OFFSET(CDevSettings, + lpIDataObjectVtbl)); +} + +static __inline VOID +pCDevSettings_FreeString(PWCHAR *psz) +{ + if (*psz != NULL) + { + LocalFree((HLOCAL)*psz); + *psz = NULL; + } +} + +static PWSTR +pCDevSettings_AllocAndCopyString(const TCHAR *pszSrc) +{ + INT c; + PWSTR str; + + c = _tcslen(pszSrc) + 1; + str = (PWSTR)LocalAlloc(LMEM_FIXED, + c * sizeof(WCHAR)); + if (str != NULL) + { +#ifdef UNICODE + wcscpy(str, + pszSrc); +#else + MultiByteToWideChar(CP_APC, + 0, + pszSrc, + -1, + str, + c); +#endif + } + + return str; +} + +static PWSTR +pCDevSettings_GetMonitorName(const WCHAR *pszDisplayDevice) +{ + DISPLAY_DEVICEW dd, dd2; + PWSTR str = NULL; + + dd.cb = sizeof(dd); + if (EnumDisplayDevicesW(pszDisplayDevice, + 0, + &dd, + 0)) + { + dd2.cb = sizeof(dd2); + if (EnumDisplayDevicesW(pszDisplayDevice, + 1, + &dd2, + 0)) + { + /* There's more than one monitor connected... */ + LoadStringW(hApplet, + IDS_MULTIPLEMONITORS, + dd.DeviceString, + sizeof(dd.DeviceString) / sizeof(dd.DeviceString[0])); + } + } + else + { + /* We can't enumerate a monitor, make sure this fact is reported + to the user! */ + LoadStringW(hApplet, + IDS_UNKNOWNMONITOR, + dd.DeviceString, + sizeof(dd.DeviceString) / sizeof(dd.DeviceString[0])); + } + + str = LocalAlloc(LMEM_FIXED, + (wcslen(dd.DeviceString) + 1) * sizeof(WCHAR)); + if (str != NULL) + { + wcscpy(str, + dd.DeviceString); + } + + return str; +} + +static PWSTR +pCDevSettings_GetMonitorDevice(const WCHAR *pszDisplayDevice) +{ + DISPLAY_DEVICEW dd; + PWSTR str = NULL; + + dd.cb = sizeof(dd); + if (EnumDisplayDevicesW(pszDisplayDevice, + 0, + &dd, + 0)) + { + str = LocalAlloc(LMEM_FIXED, + (wcslen(dd.DeviceName) + 1) * sizeof(WCHAR)); + if (str != NULL) + { + wcscpy(str, + dd.DeviceName); + } + } + + return str; +} + +static PWSTR +pCDevSettings_GetDeviceInstanceId(const WCHAR *pszDevice) +{ + /* FIXME: Implement */ + DPRINT1("CDevSettings::GetDeviceInstanceId(%ws) UNIMPLEMENTED!\n", pszDevice); + return NULL; +} + + +static HKEY +pCDevSettings_OpenDeviceKey(PCDevSettings This, + BOOL ReadOnly) +{ + static const WCHAR szRegPrefix[] = L"\\Registry\\Machine\\"; + PWSTR lpRegKey; + REGSAM Access = KEY_READ; + HKEY hKey; + + lpRegKey = This->pDisplayKey; + if (lpRegKey != NULL) + { + if (wcslen(lpRegKey) >= wcslen(szRegPrefix) && + !wcsnicmp(lpRegKey, + szRegPrefix, + wcslen(szRegPrefix))) + { + lpRegKey += wcslen(szRegPrefix); + } + + if (!ReadOnly) + Access |= KEY_WRITE; + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, + lpRegKey, + 0, + Access, + &hKey) == ERROR_SUCCESS) + { + return hKey; + } + } + + return NULL; +} + +PDEVMODEW DESK_EXT_CALLBACK +CDevSettings_EnumAllModes(PVOID Context, + DWORD Index) +{ + //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); + /* FIXME: Implement */ + DPRINT1("CDevSettings::EnumAllModes(%u)\n", Index); + return NULL; +} + +PDEVMODEW DESK_EXT_CALLBACK +CDevSettings_GetCurrentMode(PVOID Context) +{ + //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); + /* FIXME: Implement */ + DPRINT1("CDevSettings::GetCurrentMode\n"); + return NULL; +} + +BOOL DESK_EXT_CALLBACK +CDevSettings_SetCurrentMode(PVOID Context, + const DEVMODEW *pDevMode) +{ + //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); + /* FIXME: Implement */ + DPRINT1("CDevSettings::SetCurrentMode(0x%p)\n", pDevMode); + return FALSE; +} + +VOID DESK_EXT_CALLBACK +CDevSettings_GetPruningMode(PVOID Context, + PBOOL pbModesPruned, + PBOOL pbKeyIsReadOnly, + PBOOL pbPruningOn) +{ + PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); + + DPRINT1("CDevSettings::GetPruningMode(%p,%p,%p)\n", pbModesPruned, pbKeyIsReadOnly, pbPruningOn); + + *pbModesPruned = This->bModesPruned; + *pbKeyIsReadOnly = This->bKeyIsReadOnly; + *pbPruningOn = This->bPruningOn; +} + +VOID DESK_EXT_CALLBACK +CDevSettings_SetPruningMode(PVOID Context, + BOOL PruningOn) +{ + HKEY hKey; + DWORD dwValue; + PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); + + DPRINT1("CDevSettings::SetPruningMode(%d)\n", PruningOn); + + if (This->bModesPruned && !This->bKeyIsReadOnly && + PruningOn != This->bPruningOn) + { + This->bPruningOn = (PruningOn != FALSE); + + hKey = pCDevSettings_OpenDeviceKey(This, + FALSE); + if (hKey != NULL) + { + dwValue = (DWORD)This->bPruningOn; + + RegSetValueEx(hKey, + TEXT("PruningMode"), + 0, + REG_DWORD, + (const BYTE *)&dwValue, + sizeof(dwValue)); + + RegCloseKey(hKey); + } + } +} + +static VOID +pCDevSettings_ReadHardwareInfo(HKEY hKey, + LPCTSTR lpValueName, + LPWSTR lpBuffer) +{ + DWORD type = REG_BINARY; + DWORD size = 128 * sizeof(WCHAR); + RegQueryValueEx(hKey, + lpValueName, + NULL, + &type, + (PBYTE)lpBuffer, + &size); +} + +static VOID +pCDevSettings_InitializeExtInterface(PCDevSettings This) +{ + PDESK_EXT_INTERFACE Interface = &This->ExtInterface; + HKEY hKeyDev; + + ZeroMemory(Interface, + sizeof(*Interface)); + Interface->cbSize = sizeof(*Interface); + + /* Initialize the callback table */ + Interface->Context = impl_to_interface(This, IDataObject); + Interface->EnumAllModes = CDevSettings_EnumAllModes; + Interface->SetCurrentMode = CDevSettings_SetCurrentMode; + Interface->GetCurrentMode = CDevSettings_GetCurrentMode; + Interface->SetPruningMode = CDevSettings_SetPruningMode; + Interface->GetPruningMode = CDevSettings_GetPruningMode; + + /* Read the HardwareInformation.* values from the registry key */ + hKeyDev = pCDevSettings_OpenDeviceKey(This, + TRUE); + if (hKeyDev != NULL) + { + DWORD dwType, dwMemSize = 0; + DWORD dwSize = sizeof(dwMemSize); + + if (RegQueryValueEx(hKeyDev, + TEXT("HardwareInformation.MemorySize"), + NULL, + &dwType, + (PBYTE)&dwMemSize, + &dwSize) == ERROR_SUCCESS && + (dwType == REG_BINARY || dwType == REG_DWORD) && + dwSize == sizeof(dwMemSize)) + { + dwMemSize /= 1024; + + if (dwMemSize > 1024) + { + dwMemSize /= 1024; + if (dwMemSize > 1024) + { + wsprintf(Interface->MemorySize, + _T("%u GB"), + dwMemSize / 1024); + } + else + { + wsprintf(Interface->MemorySize, + _T("%u MB"), + dwMemSize); + } + } + else + { + wsprintf(Interface->MemorySize, + _T("%u KB"), + dwMemSize); + } + } + + pCDevSettings_ReadHardwareInfo(hKeyDev, + TEXT("HardwareInformation.ChipType"), + Interface->ChipType); + pCDevSettings_ReadHardwareInfo(hKeyDev, + TEXT("HardwareInformation.DacType"), + Interface->DacType); + pCDevSettings_ReadHardwareInfo(hKeyDev, + TEXT("HardwareInformation.AdapterString"), + Interface->AdapterString); + pCDevSettings_ReadHardwareInfo(hKeyDev, + TEXT("HardwareInformation.BiosString"), + Interface->BiosString); + RegCloseKey(hKeyDev); + } +} + +static HRESULT +pCDevSettings_Initialize(PCDevSettings This, + PDISPLAY_DEVICE_ENTRY DisplayDeviceInfo) +{ + HKEY hKey; + + This->Flags = 0; + This->StateFlags = DisplayDeviceInfo->DeviceStateFlags; + DPRINT1("This->StateFlags: %x\n", This->StateFlags); + + /* Register clipboard formats */ + This->cfExtInterface = RegisterClipboardFormat(TEXT("Desk.cpl extension interface")); + This->cfDisplayDevice = RegisterClipboardFormat(TEXT("Display Device")); + This->cfDisplayName = RegisterClipboardFormat(TEXT("Display Name")); + This->cfDisplayId = RegisterClipboardFormat(TEXT("Display ID")); + This->cfDisplayKey = RegisterClipboardFormat(TEXT("Display Key")); + This->cfDisplayStateFlags = RegisterClipboardFormat(TEXT("Display State Flags")); + This->cfMonitorName = RegisterClipboardFormat(TEXT("Monitor Name")); + This->cfMonitorDevice = RegisterClipboardFormat(TEXT("Monitor Device")); + This->cfMonitorId = RegisterClipboardFormat(TEXT("Monitor ID")); + This->cfPruningMode = RegisterClipboardFormat(TEXT("Pruning Mode")); + + /* Copy the device name */ + This->pDisplayDevice = pCDevSettings_AllocAndCopyString(DisplayDeviceInfo->DeviceName); + DPRINT1("This->pDisplayDevice: %ws\n", This->pDisplayDevice); + This->pDisplayName = pCDevSettings_AllocAndCopyString(DisplayDeviceInfo->DeviceDescription); + DPRINT1("This->pDisplayName: %ws\n", This->pDisplayName); + This->pDisplayKey = pCDevSettings_AllocAndCopyString(DisplayDeviceInfo->DeviceKey); + DPRINT1("This->pDisplayKey: %ws\n", This->pDisplayKey); + This->pDisplayId = pCDevSettings_GetDeviceInstanceId(This->pDisplayDevice); + DPRINT1("This->pDisplayId: %ws\n", This->pDisplayId); + This->pMonitorName = pCDevSettings_GetMonitorName(This->pDisplayDevice); + DPRINT1("This->pMonitorName: %ws\n", This->pMonitorName); + This->pMonitorDevice = pCDevSettings_GetMonitorDevice(This->pDisplayDevice); + DPRINT1("This->pMonitorDevice: %ws\n", This->pMonitorDevice); + This->pMonitorId = pCDevSettings_GetDeviceInstanceId( This->pMonitorDevice); + DPRINT1("This->pMonitorId: %ws\n", This->pMonitorId); + + /* Check pruning mode */ + This->bModesPruned = ((DisplayDeviceInfo->DeviceStateFlags & DISPLAY_DEVICE_MODESPRUNED) != 0); + hKey = pCDevSettings_OpenDeviceKey(This, + FALSE); + if (hKey == NULL) + { + hKey = pCDevSettings_OpenDeviceKey(This, + FALSE); + This->bKeyIsReadOnly = TRUE; + } + if (hKey != NULL) + { + DWORD dw = 0; + DWORD dwType, dwSize; + + dwSize = sizeof(dw); + if (RegQueryValueEx(hKey, + TEXT("PruningMode"), + NULL, + &dwType, + (PBYTE)&dw, + &dwSize) == ERROR_SUCCESS) + { + if (dwType == REG_DWORD && dwSize == sizeof(dw)) + This->bPruningOn = (dw != 0); + } + + RegCloseKey(hKey); + } + + /* Initialize the shell extension interface */ + pCDevSettings_InitializeExtInterface(This); + + return S_OK; +} + +static VOID +pCDevSettings_Free(PCDevSettings This) +{ + pCDevSettings_FreeString(&This->pDisplayDevice); + pCDevSettings_FreeString(&This->pDisplayName); + pCDevSettings_FreeString(&This->pDisplayKey); + pCDevSettings_FreeString(&This->pDisplayId); + pCDevSettings_FreeString(&This->pMonitorName); + pCDevSettings_FreeString(&This->pMonitorDevice); + pCDevSettings_FreeString(&This->pMonitorId); +} + +static HRESULT STDMETHODCALLTYPE +CDevSettings_QueryInterface(IDataObject* iface, + REFIID riid, + void** ppvObject) +{ + PCDevSettings This = impl_from_IDataObject(iface); + + *ppvObject = NULL; + + if (IsEqualGUID(riid, + &IID_IUnknown) || + IsEqualGUID(riid, + &IID_IDataObject)) + { + *ppvObject = (PVOID)impl_to_interface(This, IDataObject); + return S_OK; + } + else + { + DPRINT1("CDevSettings::QueryInterface: Queried unknown interface\n"); + } + + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE +CDevSettings_AddRef(IDataObject* iface) +{ + PCDevSettings This = impl_from_IDataObject(iface); + return (ULONG)InterlockedIncrement((PLONG)&This->ref); +} + +static ULONG STDMETHODCALLTYPE +CDevSettings_Release(IDataObject* iface) +{ + ULONG refs; + PCDevSettings This = impl_from_IDataObject(iface); + refs = (ULONG)InterlockedDecrement((PLONG)&This->ref); + if (refs == 0) + pCDevSettings_Free(This); + + return refs; +} + +static HRESULT STDMETHODCALLTYPE +CDevSettings_GetData(IDataObject* iface, + FORMATETC* pformatetcIn, + STGMEDIUM* pmedium) +{ + static const WCHAR szEmpty[] = {0}; + HRESULT hr; + PCWSTR pszRet = NULL; + PWSTR pszBuf; + PCDevSettings This = impl_from_IDataObject(iface); + + ZeroMemory(pmedium, + sizeof(STGMEDIUM)); + + hr = IDataObject_QueryGetData(iface, + pformatetcIn); + if (SUCCEEDED(hr)) + { + /* Return the reqested data back to the shell extension */ + + if (pformatetcIn->cfFormat == This->cfDisplayDevice) + { + pszRet = This->pDisplayDevice; + DPRINT1("CDevSettings::GetData returns display device %ws\n", pszRet); + } + else if (pformatetcIn->cfFormat == This->cfDisplayName) + { + pszRet = This->pDisplayName; + DPRINT1("CDevSettings::GetData returns display name %ws\n", pszRet); + } + else if (pformatetcIn->cfFormat == This->cfDisplayKey) + { + pszRet = This->pDisplayKey; + DPRINT1("CDevSettings::GetData returns display key %ws\n", pszRet); + } + else if (pformatetcIn->cfFormat == This->cfDisplayId) + { + pszRet = This->pDisplayId; + DPRINT1("CDevSettings::GetData returns display id %ws\n", pszRet); + } + else if (pformatetcIn->cfFormat == This->cfMonitorName) + { + pszRet = This->pMonitorName; + DPRINT1("CDevSettings::GetData returns monitor name %ws\n", pszRet); + } + else if (pformatetcIn->cfFormat == This->cfMonitorDevice) + { + pszRet = This->pMonitorDevice; + DPRINT1("CDevSettings::GetData returns monitor device %ws\n", pszRet); + } + else if (pformatetcIn->cfFormat == This->cfMonitorId) + { + pszRet = This->pMonitorId; + DPRINT1("CDevSettings::GetData returns monitor id %ws\n", pszRet); + } + else if (pformatetcIn->cfFormat == This->cfExtInterface) + { + PDESK_EXT_INTERFACE pIface; + + pIface = GlobalAlloc(GPTR, + sizeof(*pIface)); + if (pIface != NULL) + { + CopyMemory(pIface, + &This->ExtInterface, + sizeof(This->ExtInterface)); + + DPRINT1("CDevSettings::GetData returns the desk.cpl extension interface\n"); + + pmedium->tymed = TYMED_HGLOBAL; + pmedium->hGlobal = pIface; + + return S_OK; + } + else + return E_OUTOFMEMORY; + } + else if (pformatetcIn->cfFormat == This->cfDisplayStateFlags) + { + PDWORD pdw; + + pdw = GlobalAlloc(GPTR, + sizeof(*pdw)); + if (pdw != NULL) + { + *pdw = This->StateFlags; + + DPRINT1("CDevSettings::GetData returns the display state flags %x\n", This->StateFlags); + + pmedium->tymed = TYMED_HGLOBAL; + pmedium->hGlobal = pdw; + + return S_OK; + } + else + return E_OUTOFMEMORY; + } + else if (pformatetcIn->cfFormat == This->cfPruningMode) + { + PBYTE pb; + + pb = GlobalAlloc(GPTR, + sizeof(*pb)); + if (pb != NULL) + { + *pb = (This->bModesPruned && This->bPruningOn); + + pmedium->tymed = TYMED_HGLOBAL; + pmedium->hGlobal = pb; + + return S_OK; + } + else + return E_OUTOFMEMORY; + } + + /* NOTE: This only returns null-terminated strings! */ + if (pszRet == NULL) + pszRet = szEmpty; + + pszBuf = GlobalAlloc(GPTR, + (_tcslen(pszRet) + 1) * sizeof(WCHAR)); + if (pszBuf != NULL) + { + _tcscpy(pszBuf, + pszRet); + + pmedium->tymed = TYMED_HGLOBAL; + pmedium->hGlobal = pszBuf; + + hr = S_OK; + } + else + hr = E_OUTOFMEMORY; + } + + return hr; +} + +static HRESULT STDMETHODCALLTYPE +CDevSettings_GetDataHere(IDataObject* iface, + FORMATETC* pformatetc, + STGMEDIUM* pmedium) +{ + ZeroMemory(pformatetc, + sizeof(*pformatetc)); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE +CDevSettings_QueryGetData(IDataObject* iface, + FORMATETC* pformatetc) +{ +#if DEBUG + TCHAR szFormatName[255]; +#endif + PCDevSettings This = impl_from_IDataObject(iface); + + if (pformatetc->dwAspect != DVASPECT_CONTENT) + return DV_E_DVASPECT; + + if (pformatetc->lindex != -1) + return DV_E_LINDEX; + + if (!(pformatetc->tymed & TYMED_HGLOBAL)) + return DV_E_TYMED; + + /* Check if the requested data can be provided */ + if (pformatetc->cfFormat == This->cfExtInterface || + pformatetc->cfFormat == This->cfDisplayDevice || + pformatetc->cfFormat == This->cfDisplayName || + pformatetc->cfFormat == This->cfDisplayId || + pformatetc->cfFormat == This->cfDisplayKey || + pformatetc->cfFormat == This->cfDisplayStateFlags || + pformatetc->cfFormat == This->cfMonitorDevice || + pformatetc->cfFormat == This->cfMonitorName || + pformatetc->cfFormat == This->cfMonitorId || + pformatetc->cfFormat == This->cfPruningMode) + { + return S_OK; + } +#if DEBUG + else + { + if (GetClipboardFormatName(pformatetc->cfFormat, + szFormatName, + sizeof(szFormatName) / sizeof(szFormatName[0]))) + { + DPRINT1("CDevSettings::QueryGetData(\"%ws\")\n", szFormatName); + } + else + { + DPRINT1("CDevSettings::QueryGetData(Format %u)\n", (unsigned int)pformatetc->cfFormat); + } + } +#endif + + return DV_E_FORMATETC; +} + +static HRESULT STDMETHODCALLTYPE +CDevSettings_GetCanonicalFormatEtc(IDataObject* iface, + FORMATETC* pformatectIn, + FORMATETC* pformatetcOut) +{ + HRESULT hr; + + DPRINT1("CDevSettings::GetCanonicalFormatEtc\n"); + + hr = IDataObject_QueryGetData(iface, + pformatectIn); + if (SUCCEEDED(hr)) + { + CopyMemory(pformatetcOut, + pformatectIn, + sizeof(FORMATETC)); + + /* Make sure the data is target device independent */ + if (pformatectIn->ptd == NULL) + hr = DATA_S_SAMEFORMATETC; + else + { + pformatetcOut->ptd = NULL; + hr = S_OK; + } + } + else + { + ZeroMemory(pformatetcOut, + sizeof(FORMATETC)); + } + + return hr; +} + +static HRESULT STDMETHODCALLTYPE +CDevSettings_SetData(IDataObject* iface, + FORMATETC* pformatetc, + STGMEDIUM* pmedium, + BOOL fRelease) +{ + DPRINT1("CDevSettings::SetData UNIMPLEMENTED\n"); + return E_NOTIMPL; +} + +static __inline VOID +pCDevSettings_FillFormatEtc(FORMATETC *pFormatEtc, + CLIPFORMAT cf) +{ + pFormatEtc->cfFormat = cf; + pFormatEtc->ptd = NULL; + pFormatEtc->dwAspect = DVASPECT_CONTENT; + pFormatEtc->lindex = -1; + pFormatEtc->tymed = TYMED_HGLOBAL; +} + +static HRESULT STDMETHODCALLTYPE +CDevSettings_EnumFormatEtc(IDataObject* iface, + DWORD dwDirection, + IEnumFORMATETC** ppenumFormatEtc) +{ + HRESULT hr; + FORMATETC fetc[10]; + PCDevSettings This = impl_from_IDataObject(iface); + + *ppenumFormatEtc = NULL; + + if (dwDirection == DATADIR_GET) + { + pCDevSettings_FillFormatEtc(&fetc[0], + This->cfExtInterface); + pCDevSettings_FillFormatEtc(&fetc[1], + This->cfDisplayDevice); + pCDevSettings_FillFormatEtc(&fetc[2], + This->cfDisplayName); + pCDevSettings_FillFormatEtc(&fetc[3], + This->cfDisplayId); + pCDevSettings_FillFormatEtc(&fetc[4], + This->cfDisplayKey); + pCDevSettings_FillFormatEtc(&fetc[5], + This->cfDisplayStateFlags); + pCDevSettings_FillFormatEtc(&fetc[6], + This->cfMonitorName); + pCDevSettings_FillFormatEtc(&fetc[7], + This->cfMonitorDevice); + pCDevSettings_FillFormatEtc(&fetc[8], + This->cfMonitorId); + pCDevSettings_FillFormatEtc(&fetc[9], + This->cfPruningMode); + + hr = SHCreateStdEnumFmtEtc(sizeof(fetc) / sizeof(fetc[0]), + fetc, + ppenumFormatEtc); + } + else + hr = E_NOTIMPL; + + return hr; +} + +static HRESULT STDMETHODCALLTYPE +CDevSettings_DAdvise(IDataObject* iface, + FORMATETC* pformatetc, + DWORD advf, + IAdviseSink* pAdvSink, + DWORD* pdwConnection) +{ + *pdwConnection = 0; + return OLE_E_ADVISENOTSUPPORTED; +} + +static HRESULT STDMETHODCALLTYPE +CDevSettings_DUnadvise(IDataObject* iface, + DWORD dwConnection) +{ + return OLE_E_ADVISENOTSUPPORTED; +} + +static HRESULT STDMETHODCALLTYPE +CDevSettings_EnumDAdvise(IDataObject* iface, + IEnumSTATDATA** ppenumAdvise) +{ + *ppenumAdvise = NULL; + return OLE_E_ADVISENOTSUPPORTED; +} + +static const struct IDataObjectVtbl vtblIDataObject = { + CDevSettings_QueryInterface, + CDevSettings_AddRef, + CDevSettings_Release, + CDevSettings_GetData, + CDevSettings_GetDataHere, + CDevSettings_QueryGetData, + CDevSettings_GetCanonicalFormatEtc, + CDevSettings_SetData, + CDevSettings_EnumFormatEtc, + CDevSettings_DAdvise, + CDevSettings_DUnadvise, + CDevSettings_EnumDAdvise, +}; + +IDataObject * +CreateDevSettings(PDISPLAY_DEVICE_ENTRY DisplayDeviceInfo) +{ + PCDevSettings This; + + This = HeapAlloc(GetProcessHeap(), + 0, + sizeof(*This)); + if (This != NULL) + { + This->lpIDataObjectVtbl = &vtblIDataObject; + This->ref = 1; + + if (SUCCEEDED(pCDevSettings_Initialize(This, + DisplayDeviceInfo))) + { + return impl_to_interface(This, IDataObject); + } + + CDevSettings_Release(impl_to_interface(This, IDataObject)); + } + + return NULL; +} diff --git a/reactos/dll/cpl/desk/lang/en-US.rc b/reactos/dll/cpl/desk/lang/en-US.rc index e2df04b83a8..5b7832d5fcc 100644 --- a/reactos/dll/cpl/desk/lang/en-US.rc +++ b/reactos/dll/cpl/desk/lang/en-US.rc @@ -114,7 +114,14 @@ BEGIN WS_VSCROLL | WS_TABSTOP CONTROL "",1813,"Static",SS_BITMAP | SS_CENTERIMAGE | SS_SUNKEN, 131,148,103,9 - PUSHBUTTON "Ad&vanced...",IDC_SETTINGS_ADVANCED,306,165,56,14 + PUSHBUTTON "Ad&vanced...",IDC_SETTINGS_ADVANCED,170,165,70,14 +END + +IDD_ADVANCED_GENERAL DIALOGEX DISCARDABLE 0, 0, 246, 204 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "General" +FONT 8, "MS Shell Dlg" +BEGIN END IDR_PREVIEW_MENU MENU @@ -124,6 +131,13 @@ BEGIN MENUITEM "Selected", ID_MENU_SELECTED END +STRINGTABLE +BEGIN + IDS_MULTIPLEMONITORS "(Multiple Monitors)" + IDS_UNKNOWNMONITOR "(Unknown Monitor)" + IDS_ADVANCEDTITLEFMT "%s and %s" +END + STRINGTABLE BEGIN IDS_CPLNAME "Display" diff --git a/reactos/dll/cpl/desk/resource.h b/reactos/dll/cpl/desk/resource.h index 34bac9fff6f..052c54fd32b 100644 --- a/reactos/dll/cpl/desk/resource.h +++ b/reactos/dll/cpl/desk/resource.h @@ -22,6 +22,7 @@ #define IDD_APPEARANCE 102 #define IDD_SETTINGS 103 #define IDD_ADVAPPEARANCE 104 +#define IDD_ADVANCED_GENERAL 200 /* Background Page */ #define IDC_BACKGROUND_LIST 1000 @@ -145,6 +146,9 @@ #define IDS_ELEMENT_22 3222 #define IDS_ELEMENT_23 3223 +#define IDS_MULTIPLEMONITORS 3300 +#define IDS_UNKNOWNMONITOR 3301 +#define IDS_ADVANCEDTITLEFMT 3302 #endif /* __CPL_DESK_RESOURCE_H__ */ diff --git a/reactos/dll/cpl/desk/settings.c b/reactos/dll/cpl/desk/settings.c index f27c8efb5d2..c9c3493b6dc 100644 --- a/reactos/dll/cpl/desk/settings.c +++ b/reactos/dll/cpl/desk/settings.c @@ -10,37 +10,6 @@ #include "desk.h" -/* As slider control can't contain user data, we have to keep an - * array of RESOLUTION_INFO to have our own associated data. - */ -typedef struct _RESOLUTION_INFO -{ - DWORD dmPelsWidth; - DWORD dmPelsHeight; -} RESOLUTION_INFO, *PRESOLUTION_INFO; - -typedef struct _SETTINGS_ENTRY -{ - struct _SETTINGS_ENTRY *Blink; - struct _SETTINGS_ENTRY *Flink; - DWORD dmBitsPerPel; - DWORD dmPelsWidth; - DWORD dmPelsHeight; -} SETTINGS_ENTRY, *PSETTINGS_ENTRY; - -typedef struct _DISPLAY_DEVICE_ENTRY -{ - struct _DISPLAY_DEVICE_ENTRY *Flink; - LPTSTR DeviceDescription; - LPTSTR DeviceName; - PSETTINGS_ENTRY Settings; /* sorted by increasing dmPelsHeight, BPP */ - DWORD SettingsCount; - PRESOLUTION_INFO Resolutions; - DWORD ResolutionsCount; - PSETTINGS_ENTRY CurrentSettings; /* Points into Settings list */ - SETTINGS_ENTRY InitialSettings; -} DISPLAY_DEVICE_ENTRY, *PDISPLAY_DEVICE_ENTRY; - typedef struct _GLOBAL_DATA { PDISPLAY_DEVICE_ENTRY DisplayDeviceList; @@ -76,7 +45,7 @@ UpdateDisplay(IN HWND hwndDlg, PGLOBAL_DATA pGlobalData, IN BOOL bUpdateThumb) } static PSETTINGS_ENTRY -GetPossibleSettings(IN LPTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTINGS_ENTRY* CurrentSettings) +GetPossibleSettings(IN LPCTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTINGS_ENTRY* CurrentSettings) { DEVMODE devmode; DWORD NbSettings = 0; @@ -168,13 +137,14 @@ GetPossibleSettings(IN LPTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTIN } static BOOL -AddDisplayDevice(IN PGLOBAL_DATA pGlobalData, IN LPTSTR Description, IN LPTSTR DeviceName) +AddDisplayDevice(IN PGLOBAL_DATA pGlobalData, IN const DISPLAY_DEVICE *DisplayDevice) { PDISPLAY_DEVICE_ENTRY newEntry = NULL; LPTSTR description = NULL; LPTSTR name = NULL; - DWORD descriptionSize; - DWORD nameSize; + LPTSTR key = NULL; + LPTSTR devid = NULL; + DWORD descriptionSize, nameSize, keySize, devidSize; PSETTINGS_ENTRY Current; DWORD ResolutionsCount = 1; DWORD i; @@ -183,7 +153,7 @@ AddDisplayDevice(IN PGLOBAL_DATA pGlobalData, IN LPTSTR Description, IN LPTSTR D memset(newEntry, 0, sizeof(DISPLAY_DEVICE_ENTRY)); if (!newEntry) goto ByeBye; - newEntry->Settings = GetPossibleSettings(DeviceName, &newEntry->SettingsCount, &newEntry->CurrentSettings); + newEntry->Settings = GetPossibleSettings(DisplayDevice->DeviceName, &newEntry->SettingsCount, &newEntry->CurrentSettings); if (!newEntry->Settings) goto ByeBye; newEntry->InitialSettings.dmPelsWidth = newEntry->CurrentSettings->dmPelsWidth; @@ -219,18 +189,31 @@ AddDisplayDevice(IN PGLOBAL_DATA pGlobalData, IN LPTSTR Description, IN LPTSTR D i++; } } - descriptionSize = (_tcslen(Description) + 1) * sizeof(TCHAR); + descriptionSize = (_tcslen(DisplayDevice->DeviceString) + 1) * sizeof(TCHAR); description = HeapAlloc(GetProcessHeap(), 0, descriptionSize); if (!description) goto ByeBye; - nameSize = (_tcslen(DeviceName) + 1) * sizeof(TCHAR); + nameSize = (_tcslen(DisplayDevice->DeviceName) + 1) * sizeof(TCHAR); name = HeapAlloc(GetProcessHeap(), 0, nameSize); if (!name) goto ByeBye; - memcpy(description, Description, descriptionSize); - memcpy(name, DeviceName, nameSize); + keySize = (_tcslen(DisplayDevice->DeviceKey) + 1) * sizeof(TCHAR); + key = HeapAlloc(GetProcessHeap(), 0, keySize); + if (!key) goto ByeBye; + + devidSize = (_tcslen(DisplayDevice->DeviceID) + 1) * sizeof(TCHAR); + devid = HeapAlloc(GetProcessHeap(), 0, devidSize); + if (!devid) goto ByeBye; + + memcpy(description, DisplayDevice->DeviceString, descriptionSize); + memcpy(name, DisplayDevice->DeviceName, nameSize); + memcpy(key, DisplayDevice->DeviceKey, keySize); + memcpy(devid, DisplayDevice->DeviceID, devidSize); newEntry->DeviceDescription = description; newEntry->DeviceName = name; + newEntry->DeviceKey = key; + newEntry->DeviceID = devid; + newEntry->DeviceStateFlags = DisplayDevice->StateFlags; newEntry->Flink = pGlobalData->DisplayDeviceList; pGlobalData->DisplayDeviceList = newEntry; return TRUE; @@ -256,6 +239,10 @@ ByeBye: HeapFree(GetProcessHeap(), 0, description); if (name != NULL) HeapFree(GetProcessHeap(), 0, name); + if (key != NULL) + HeapFree(GetProcessHeap(), 0, key); + if (devid != NULL) + HeapFree(GetProcessHeap(), 0, devid); return FALSE; } @@ -307,11 +294,11 @@ OnInitDialog(IN HWND hwndDlg) /* Get video cards list */ displayDevice.cb = (DWORD)sizeof(DISPLAY_DEVICE); - while (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0)) + while (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0x1)) { if ((displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0) { - if (AddDisplayDevice(pGlobalData, displayDevice.DeviceString, displayDevice.DeviceName)) + if (AddDisplayDevice(pGlobalData, &displayDevice)) Result++; } iDevNum++; @@ -518,12 +505,6 @@ OnResolutionChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData, IN DWORD NewPo /* we shouldn't go there */ } -static VOID -OnAdvancedButton() -{ - MessageBox(NULL, TEXT("That button doesn't do anything yet"), TEXT("Whoops"), MB_OK); -} - /* Property page dialog callback */ INT_PTR CALLBACK SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) @@ -543,7 +524,7 @@ SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lPar DWORD command = HIWORD(wParam); if (controlId == IDC_SETTINGS_ADVANCED && command == BN_CLICKED) - OnAdvancedButton(); + DisplayAdvancedSettings(hwndDlg, pGlobalData->CurrentDisplayDevice); else if (controlId == IDC_SETTINGS_BPP && command == CBN_SELCHANGE) OnBPPChanged(hwndDlg, pGlobalData); break;