mirror of
https://github.com/reactos/reactos.git
synced 2025-01-05 22:12:46 +00:00
Display advanced display settings and allow shell extensions to extend it. Not yet fully functional/working
svn path=/trunk/; revision=29210
This commit is contained in:
parent
ad47c9b3a9
commit
3b6747e11c
8 changed files with 1277 additions and 69 deletions
187
reactos/dll/cpl/desk/advmon.c
Normal file
187
reactos/dll/cpl/desk/advmon.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef __CPL_DESK_H__
|
||||
#define __CPL_DESK_H__
|
||||
|
||||
#define COBJMACROS
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <commdlg.h>
|
||||
|
@ -8,6 +9,9 @@
|
|||
#include <tchar.h>
|
||||
#include <setupapi.h>
|
||||
#include <stdio.h>
|
||||
#include <shlobj.h>
|
||||
#include <regstr.h>
|
||||
#include <cplext.h>
|
||||
|
||||
#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__ */
|
||||
|
||||
|
|
|
@ -15,15 +15,19 @@
|
|||
<library>gdi32</library>
|
||||
<library>comctl32</library>
|
||||
<library>comdlg32</library>
|
||||
<library>ole32</library>
|
||||
<library>setupapi</library>
|
||||
<library>shell32</library>
|
||||
<library>ntdll</library>
|
||||
<library>msimg32</library>
|
||||
<library>msvcrt</library>
|
||||
<library>uuid</library>
|
||||
<file>advmon.c</file>
|
||||
<file>appearance.c</file>
|
||||
<file>background.c</file>
|
||||
<file>classinst.c</file>
|
||||
<file>desk.c</file>
|
||||
<file>devsett.c</file>
|
||||
<file>dibitmap.c</file>
|
||||
<file>misc.c</file>
|
||||
<file>preview.c</file>
|
||||
|
|
910
reactos/dll/cpl/desk/devsett.c
Normal file
910
reactos/dll/cpl/desk/devsett.c
Normal file
|
@ -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 <debug.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue