Something went wrong. Try again.
Reactos
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Display Control Panel * FILE: dll/cpl/desk/devsett.c * PURPOSE: ReactOS Display Control Panel Shell Extension Support */
#include "desk.h"
#include <cfgmgr32.h>
#define NDEBUG#include <debug.h>
#define DEBUG_DEVSETTINGS
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 cfDisplayKey; /* "Display Key" */ CLIPFORMAT cfDisplayStateFlags; /* "Display State Flags" */ CLIPFORMAT cfPruningMode; /* "Pruning Mode" */
PWSTR pDisplayDevice; PWSTR pDisplayName; PWSTR pDisplayKey; PWSTR pDisplayId; PWSTR pMonitorName; PWSTR pMonitorDevice;
DESK_EXT_INTERFACE ExtInterface;
PDEVMODEW lpOrigDevMode; PDEVMODEW lpCurDevMode; PDEVMODEW * DevModes; DWORD nDevModes; 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 PCDevSettingsimpl_from_IDataObject(struct IDataObject *iface){ return (PCDevSettings)((ULONG_PTR)iface - FIELD_OFFSET(CDevSettings, lpIDataObjectVtbl));}
static __inline VOIDpCDevSettings_FreeString(PWCHAR *psz){ if (*psz != NULL) { LocalFree((HLOCAL)*psz); *psz = NULL; }}
static PWSTRpCDevSettings_AllocAndCopyString(const TCHAR *pszSrc){ SIZE_T c; PWSTR str;
c = _tcslen(pszSrc) + 1; str = (PWSTR)LocalAlloc(LMEM_FIXED, c * sizeof(WCHAR)); if (str != NULL) {#ifdef UNICODE StringCbCopyW(str, c * sizeof(WCHAR), pszSrc);#else MultiByteToWideChar(CP_ACP, 0, pszSrc, -1, str, c);#endif }
return str;}
static PWSTRpCDevSettings_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 PWSTRpCDevSettings_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;}
/** * @brief * Converts a Hardware ID (DeviceID from EnumDisplayDevices) * to an unique Device Instance ID. * * @param[in] pszDevice * A pointer to a null-terminated Unicode string * containing a Hardware ID. * e.g. "PCI\VEN_80EE&DEV_BEEF&SUBSYS_00000000&REV_00" * * @return * A pointer to a null-terminated Unicode string * containing an unique Device Instance ID * or NULL in case of error. * e.g. "PCI\VEN_80EE&DEV_BEEF&SUBSYS_00000000&REV_00\3&267A616A&0&10" * * @remarks * The caller must free the returned string with LocalFree. */static PWSTRpCDevSettings_GetDeviceInstanceId(const WCHAR *pszDevice){ HDEVINFO DevInfo; SP_DEVINFO_DATA InfoData; ULONG BufLen; LPWSTR lpDevInstId = NULL;
DPRINT("CDevSettings::GetDeviceInstanceId(%ws)!\n", pszDevice);
DevInfo = SetupDiGetClassDevsW(NULL, pszDevice, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT); if (DevInfo == INVALID_HANDLE_VALUE) { DPRINT1("SetupDiGetClassDevsW(\"%ws\") failed: %d\n", pszDevice, GetLastError()); return NULL; }
ZeroMemory(&InfoData, sizeof(InfoData)); InfoData.cbSize = sizeof(InfoData);
/* Try to enumerate the first matching device */ if (!SetupDiEnumDeviceInfo(DevInfo, 0, &InfoData)) { DPRINT1("SetupDiEnumDeviceInfo failed: %d\n", GetLastError()); return NULL; }
if (SetupDiGetDeviceInstanceId(DevInfo, &InfoData, NULL, 0, &BufLen) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { DPRINT1("SetupDiGetDeviceInstanceId failed: %d\n", GetLastError()); return NULL; }
lpDevInstId = LocalAlloc(LMEM_FIXED, (BufLen + 1) * sizeof(WCHAR));
if (lpDevInstId == NULL) { DPRINT1("LocalAlloc failed\n"); return NULL; }
if (!SetupDiGetDeviceInstanceId(DevInfo, &InfoData, lpDevInstId, BufLen, NULL)) { DPRINT1("SetupDiGetDeviceInstanceId failed: %d\n", GetLastError()); LocalFree((HLOCAL)lpDevInstId); lpDevInstId = NULL; } else { DPRINT("instance id: %ws\n", lpDevInstId); }
return lpDevInstId;}
static HKEYpCDevSettings_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_CALLBACKCDevSettings_EnumAllModes(PVOID Context, DWORD Index){ PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); DWORD i, idx = 0;
DPRINT1("CDevSettings::EnumAllModes(%u)\n", Index);
if (!This->DevModes) return NULL;
for (i = 0; i < This->nDevModes; i++) { /* FIXME: Add more sanity checks */ if (!This->DevModes[i]) continue;
if (idx == Index) return This->DevModes[i];
idx++; }
return NULL;}
PDEVMODEW DESK_EXT_CALLBACKCDevSettings_GetCurrentMode(PVOID Context){ PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
DPRINT1("CDevSettings::GetCurrentMode\n"); return This->lpCurDevMode;}
BOOL DESK_EXT_CALLBACKCDevSettings_SetCurrentMode(PVOID Context, DEVMODEW *pDevMode){ PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); DWORD i;
DPRINT1("CDevSettings::SetCurrentMode(0x%p)\n", pDevMode);
if (!This->DevModes) return FALSE;
for (i = 0; i < This->nDevModes; i++) { /* FIXME: Add more sanity checks */ if (!This->DevModes[i]) continue;
if (This->DevModes[i] == pDevMode) { This->lpCurDevMode = pDevMode; return TRUE; } }
return FALSE;}
VOID DESK_EXT_CALLBACKCDevSettings_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_CALLBACKCDevSettings_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 VOIDpCDevSettings_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 VOIDpCDevSettings_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 HRESULTpCDevSettings_Initialize(PCDevSettings This, PDISPLAY_DEVICE_ENTRY DisplayDeviceInfo){ HKEY hKey; DWORD i = 0, dwSize; DEVMODEW devmode;
This->lpOrigDevMode = NULL; This->lpCurDevMode = NULL; This->DevModes = NULL; This->nDevModes = 0; This->Flags = 0; This->StateFlags = DisplayDeviceInfo->DeviceStateFlags; DPRINT1("This->StateFlags: %x\n", This->StateFlags);
/* Register clipboard formats */ This->cfExtInterface = RegisterClipboardFormat(DESK_EXT_EXTINTERFACE); This->cfDisplayDevice = RegisterClipboardFormat(DESK_EXT_DISPLAYDEVICE); This->cfDisplayName = RegisterClipboardFormat(DESK_EXT_DISPLAYNAME); This->cfDisplayId = RegisterClipboardFormat(DESK_EXT_DISPLAYID); This->cfDisplayKey = RegisterClipboardFormat(DESK_EXT_DISPLAYKEY); This->cfDisplayStateFlags = RegisterClipboardFormat(DESK_EXT_DISPLAYSTATEFLAGS); This->cfMonitorName = RegisterClipboardFormat(DESK_EXT_MONITORNAME); This->cfMonitorDevice = RegisterClipboardFormat(DESK_EXT_MONITORDEVICE); This->cfPruningMode = RegisterClipboardFormat(DESK_EXT_PRUNINGMODE);
/* 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(DisplayDeviceInfo->DeviceID); 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);
/* 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 = 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 display modes */ ZeroMemory(&devmode, sizeof(devmode)); devmode.dmSize = (WORD)sizeof(devmode); while (EnumDisplaySettingsExW(This->pDisplayDevice, i, &devmode, EDS_RAWMODE)) { dwSize = devmode.dmSize + devmode.dmDriverExtra; PDEVMODEW pDevMode = LocalAlloc(LMEM_FIXED, dwSize); PDEVMODEW * DevModesNew = NULL;
if (pDevMode) { CopyMemory(pDevMode, &devmode, dwSize);
dwSize = (This->nDevModes + 1) * sizeof(pDevMode); DevModesNew = LocalAlloc(LMEM_FIXED, dwSize); if (DevModesNew) { if (This->DevModes) { CopyMemory(DevModesNew, This->DevModes, This->nDevModes * sizeof(pDevMode));
LocalFree(This->DevModes); }
This->DevModes = DevModesNew; This->DevModes[This->nDevModes++] = pDevMode; } else { DPRINT1("LocalAlloc failed to allocate %d bytes\n", dwSize); return E_OUTOFMEMORY; } } else { DPRINT1("LocalAlloc failed to allocate %d bytes\n", dwSize); return E_OUTOFMEMORY; }
devmode.dmDriverExtra = 0; i++; }
/* FIXME: Detect duplicated modes and mark them. * Enumeration functions should check these marks * and skip corresponding array entries. */
/* Get current display mode */ ZeroMemory(&devmode, sizeof(devmode)); devmode.dmSize = (WORD)sizeof(devmode); if (EnumDisplaySettingsExW(This->pDisplayDevice, ENUM_CURRENT_SETTINGS, &devmode, 0)) { for (i = 0; i < This->nDevModes; i++) { PDEVMODEW CurMode = This->DevModes[i];
if (!CurMode) continue;
if (((CurMode->dmFields & DM_PELSWIDTH) && devmode.dmPelsWidth == CurMode->dmPelsWidth) && ((CurMode->dmFields & DM_PELSHEIGHT) && devmode.dmPelsHeight == CurMode->dmPelsHeight) && ((CurMode->dmFields & DM_BITSPERPEL) && devmode.dmBitsPerPel == CurMode->dmBitsPerPel) && ((CurMode->dmFields & DM_DISPLAYFREQUENCY) && devmode.dmDisplayFrequency == CurMode->dmDisplayFrequency)) { This->lpOrigDevMode = This->lpCurDevMode = CurMode; break; } } }
/* Initialize the shell extension interface */ pCDevSettings_InitializeExtInterface(This);
return S_OK;}
static VOIDpCDevSettings_Free(PCDevSettings This){ This->lpOrigDevMode = NULL; This->lpCurDevMode = NULL; while (This->nDevModes) { LocalFree(This->DevModes[--This->nDevModes]); } LocalFree(This->DevModes); This->DevModes = NULL;
pCDevSettings_FreeString(&This->pDisplayDevice); pCDevSettings_FreeString(&This->pDisplayName); pCDevSettings_FreeString(&This->pDisplayKey); pCDevSettings_FreeString(&This->pDisplayId); pCDevSettings_FreeString(&This->pMonitorName); pCDevSettings_FreeString(&This->pMonitorDevice);}
static HRESULT STDMETHODCALLTYPECDevSettings_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 STDMETHODCALLTYPECDevSettings_AddRef(IDataObject* iface){ PCDevSettings This = impl_from_IDataObject(iface); return (ULONG)InterlockedIncrement((PLONG)&This->ref);}
static ULONG STDMETHODCALLTYPECDevSettings_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 STDMETHODCALLTYPECDevSettings_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 requested 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->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, (wcslen(pszRet) + 1) * sizeof(WCHAR)); if (pszBuf != NULL) { hr = StringCbCopyW(pszBuf, (wcslen(pszRet) + 1) * sizeof(WCHAR), pszRet); if (FAILED(hr)) { GlobalFree(pszBuf); return hr; }
pmedium->tymed = TYMED_HGLOBAL; pmedium->hGlobal = pszBuf;
hr = S_OK; } else hr = E_OUTOFMEMORY; }
return hr;}
static HRESULT STDMETHODCALLTYPECDevSettings_GetDataHere(IDataObject* iface, FORMATETC* pformatetc, STGMEDIUM* pmedium){ ZeroMemory(pformatetc, sizeof(*pformatetc)); return E_NOTIMPL;}
static HRESULT STDMETHODCALLTYPECDevSettings_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->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 STDMETHODCALLTYPECDevSettings_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 STDMETHODCALLTYPECDevSettings_SetData(IDataObject* iface, FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease){ DPRINT1("CDevSettings::SetData UNIMPLEMENTED\n"); return E_NOTIMPL;}
static __inline VOIDpCDevSettings_FillFormatEtc(FORMATETC *pFormatEtc, CLIPFORMAT cf){ pFormatEtc->cfFormat = cf; pFormatEtc->ptd = NULL; pFormatEtc->dwAspect = DVASPECT_CONTENT; pFormatEtc->lindex = -1; pFormatEtc->tymed = TYMED_HGLOBAL;}
static HRESULT STDMETHODCALLTYPECDevSettings_EnumFormatEtc(IDataObject* iface, DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc){ HRESULT hr; FORMATETC fetc[9]; 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->cfPruningMode);
hr = SHCreateStdEnumFmtEtc(sizeof(fetc) / sizeof(fetc[0]), fetc, ppenumFormatEtc); } else hr = E_NOTIMPL;
return hr;}
static HRESULT STDMETHODCALLTYPECDevSettings_DAdvise(IDataObject* iface, FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection){ *pdwConnection = 0; return OLE_E_ADVISENOTSUPPORTED;}
static HRESULT STDMETHODCALLTYPECDevSettings_DUnadvise(IDataObject* iface, DWORD dwConnection){ return OLE_E_ADVISENOTSUPPORTED;}
static HRESULT STDMETHODCALLTYPECDevSettings_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;}
LONG WINAPIDisplaySaveSettings(PVOID pContext, HWND hwndPropSheet){ PCDevSettings This = impl_from_IDataObject((IDataObject *)pContext); LONG rc = DISP_CHANGE_SUCCESSFUL;
if (This->lpCurDevMode != This->lpOrigDevMode) { SETTINGS_ENTRY seOrig, seCur; BOOL Ret;
seOrig.dmPelsWidth = This->lpOrigDevMode->dmPelsWidth; seOrig.dmPelsHeight = This->lpOrigDevMode->dmPelsHeight; seOrig.dmBitsPerPel = This->lpOrigDevMode->dmBitsPerPel; seOrig.dmDisplayFrequency = This->lpOrigDevMode->dmDisplayFrequency;
seCur.dmPelsWidth = This->lpCurDevMode->dmPelsWidth; seCur.dmPelsHeight = This->lpCurDevMode->dmPelsHeight; seCur.dmBitsPerPel = This->lpCurDevMode->dmBitsPerPel; seCur.dmDisplayFrequency = This->lpCurDevMode->dmDisplayFrequency;
Ret = SwitchDisplayMode(hwndPropSheet, This->pDisplayDevice, &seOrig, &seCur, &rc);
if (rc == DISP_CHANGE_SUCCESSFUL) { if (Ret) This->lpOrigDevMode = This->lpCurDevMode; else This->lpCurDevMode = This->lpOrigDevMode; } }
return rc;}