* Sync up to trunk head (r65074).
[reactos.git] / dll / cpl / desk / devsett.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Display Control Panel
4 * FILE: dll/cpl/desk/devsett.c
5 * PURPOSE: ReactOS Display Control Panel Shell Extension Support
6 */
7
8 #include "desk.h"
9
10 #include <cfgmgr32.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 #define DEBUG_DEVSETTINGS
16
17 typedef struct _CDevSettings
18 {
19 const struct IDataObjectVtbl *lpIDataObjectVtbl;
20 DWORD ref;
21
22 CLIPFORMAT cfExtInterface; /* "Desk.cpl extension interface" */
23 CLIPFORMAT cfDisplayDevice; /* "Display Device" */
24 CLIPFORMAT cfDisplayName; /* "Display Name" */
25 CLIPFORMAT cfDisplayId; /* "Display ID" */
26 CLIPFORMAT cfMonitorName; /* "Monitor Name" */
27 CLIPFORMAT cfMonitorDevice; /* "Monitor Device" */
28 CLIPFORMAT cfDisplayKey; /* "Display Key" */
29 CLIPFORMAT cfDisplayStateFlags; /* "Display State Flags" */
30 CLIPFORMAT cfPruningMode; /* "Pruning Mode" */
31
32 PWSTR pDisplayDevice;
33 PWSTR pDisplayName;
34 PWSTR pDisplayKey;
35 PWSTR pDisplayId;
36 PWSTR pMonitorName;
37 PWSTR pMonitorDevice;
38
39 DESK_EXT_INTERFACE ExtInterface;
40
41 DWORD StateFlags;
42
43 union
44 {
45 DWORD Flags;
46 struct
47 {
48 DWORD bModesPruned : 1;
49 DWORD bKeyIsReadOnly : 1;
50 DWORD bPruningOn : 1;
51 };
52 };
53 } CDevSettings, *PCDevSettings;
54
55 #define impl_to_interface(impl,iface) (struct iface *)(&(impl)->lp##iface##Vtbl)
56
57 static __inline PCDevSettings
58 impl_from_IDataObject(struct IDataObject *iface)
59 {
60 return (PCDevSettings)((ULONG_PTR)iface - FIELD_OFFSET(CDevSettings,
61 lpIDataObjectVtbl));
62 }
63
64 static __inline VOID
65 pCDevSettings_FreeString(PWCHAR *psz)
66 {
67 if (*psz != NULL)
68 {
69 LocalFree((HLOCAL)*psz);
70 *psz = NULL;
71 }
72 }
73
74 static PWSTR
75 pCDevSettings_AllocAndCopyString(const TCHAR *pszSrc)
76 {
77 INT c;
78 PWSTR str;
79
80 c = _tcslen(pszSrc) + 1;
81 str = (PWSTR)LocalAlloc(LMEM_FIXED,
82 c * sizeof(WCHAR));
83 if (str != NULL)
84 {
85 #ifdef UNICODE
86 StringCbCopyW(str, c * sizeof(WCHAR),
87 pszSrc);
88 #else
89 MultiByteToWideChar(CP_ACP,
90 0,
91 pszSrc,
92 -1,
93 str,
94 c);
95 #endif
96 }
97
98 return str;
99 }
100
101 static PWSTR
102 pCDevSettings_GetMonitorName(const WCHAR *pszDisplayDevice)
103 {
104 DISPLAY_DEVICEW dd, dd2;
105 PWSTR str = NULL;
106
107 dd.cb = sizeof(dd);
108 if (EnumDisplayDevicesW(pszDisplayDevice,
109 0,
110 &dd,
111 0))
112 {
113 dd2.cb = sizeof(dd2);
114 if (EnumDisplayDevicesW(pszDisplayDevice,
115 1,
116 &dd2,
117 0))
118 {
119 /* There's more than one monitor connected... */
120 LoadStringW(hApplet,
121 IDS_MULTIPLEMONITORS,
122 dd.DeviceString,
123 sizeof(dd.DeviceString) / sizeof(dd.DeviceString[0]));
124 }
125 }
126 else
127 {
128 /* We can't enumerate a monitor, make sure this fact is reported
129 to the user! */
130 LoadStringW(hApplet,
131 IDS_UNKNOWNMONITOR,
132 dd.DeviceString,
133 sizeof(dd.DeviceString) / sizeof(dd.DeviceString[0]));
134 }
135
136 str = LocalAlloc(LMEM_FIXED,
137 (wcslen(dd.DeviceString) + 1) * sizeof(WCHAR));
138 if (str != NULL)
139 {
140 wcscpy(str,
141 dd.DeviceString);
142 }
143
144 return str;
145 }
146
147 static PWSTR
148 pCDevSettings_GetMonitorDevice(const WCHAR *pszDisplayDevice)
149 {
150 DISPLAY_DEVICEW dd;
151 PWSTR str = NULL;
152
153 dd.cb = sizeof(dd);
154 if (EnumDisplayDevicesW(pszDisplayDevice,
155 0,
156 &dd,
157 0))
158 {
159 str = LocalAlloc(LMEM_FIXED,
160 (wcslen(dd.DeviceName) + 1) * sizeof(WCHAR));
161 if (str != NULL)
162 {
163 wcscpy(str,
164 dd.DeviceName);
165 }
166 }
167
168 return str;
169 }
170
171 static PWSTR
172 pCDevSettings_GetDeviceInstanceId(const WCHAR *pszDevice)
173 {
174 DEVINST DevInst;
175 CONFIGRET cr;
176 ULONG BufLen;
177 LPWSTR lpDevInstId = NULL;
178
179 DPRINT1("CDevSettings::GetDeviceInstanceId(%ws) UNIMPLEMENTED!\n", pszDevice);
180
181 cr = CM_Locate_DevNodeW(&DevInst,
182 (DEVINSTID_W)pszDevice,
183 CM_LOCATE_DEVNODE_NORMAL);
184 if (cr == CR_SUCCESS)
185 {
186 DPRINT1("Success1\n");
187 cr = CM_Get_Device_ID_Size(&BufLen,
188 DevInst,
189 0);
190 if (cr == CR_SUCCESS)
191 {
192 DPRINT1("Success2\n");
193 lpDevInstId = LocalAlloc(LMEM_FIXED,
194 (BufLen + 1) * sizeof(WCHAR));
195
196 if (lpDevInstId != NULL)
197 {
198 DPRINT1("Success3\n");
199 cr = CM_Get_Device_IDW(DevInst,
200 lpDevInstId,
201 BufLen,
202 0);
203
204 if (cr != CR_SUCCESS)
205 {
206 LocalFree((HLOCAL)lpDevInstId);
207 lpDevInstId = NULL;
208 }
209 DPRINT1("instance id: %ws\n", lpDevInstId);
210 }
211 }
212 }
213
214 return lpDevInstId;
215 }
216
217
218 static HKEY
219 pCDevSettings_OpenDeviceKey(PCDevSettings This,
220 BOOL ReadOnly)
221 {
222 static const WCHAR szRegPrefix[] = L"\\Registry\\Machine\\";
223 PWSTR lpRegKey;
224 REGSAM Access = KEY_READ;
225 HKEY hKey;
226
227 lpRegKey = This->pDisplayKey;
228 if (lpRegKey != NULL)
229 {
230 if (wcslen(lpRegKey) >= wcslen(szRegPrefix) &&
231 !_wcsnicmp(lpRegKey,
232 szRegPrefix,
233 wcslen(szRegPrefix)))
234 {
235 lpRegKey += wcslen(szRegPrefix);
236 }
237
238 if (!ReadOnly)
239 Access |= KEY_WRITE;
240
241 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
242 lpRegKey,
243 0,
244 Access,
245 &hKey) == ERROR_SUCCESS)
246 {
247 return hKey;
248 }
249 }
250
251 return NULL;
252 }
253
254 PDEVMODEW DESK_EXT_CALLBACK
255 CDevSettings_EnumAllModes(PVOID Context,
256 DWORD Index)
257 {
258 //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
259 /* FIXME: Implement */
260 DPRINT1("CDevSettings::EnumAllModes(%u)\n", Index);
261 return NULL;
262 }
263
264 PDEVMODEW DESK_EXT_CALLBACK
265 CDevSettings_GetCurrentMode(PVOID Context)
266 {
267 //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
268 /* FIXME: Implement */
269 DPRINT1("CDevSettings::GetCurrentMode\n");
270 return NULL;
271 }
272
273 BOOL DESK_EXT_CALLBACK
274 CDevSettings_SetCurrentMode(PVOID Context,
275 const DEVMODEW *pDevMode)
276 {
277 //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
278 /* FIXME: Implement */
279 DPRINT1("CDevSettings::SetCurrentMode(0x%p)\n", pDevMode);
280 return FALSE;
281 }
282
283 VOID DESK_EXT_CALLBACK
284 CDevSettings_GetPruningMode(PVOID Context,
285 PBOOL pbModesPruned,
286 PBOOL pbKeyIsReadOnly,
287 PBOOL pbPruningOn)
288 {
289 PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
290
291 DPRINT1("CDevSettings::GetPruningMode(%p,%p,%p)\n", pbModesPruned, pbKeyIsReadOnly, pbPruningOn);
292
293 *pbModesPruned = This->bModesPruned;
294 *pbKeyIsReadOnly = This->bKeyIsReadOnly;
295 *pbPruningOn = This->bPruningOn;
296 }
297
298 VOID DESK_EXT_CALLBACK
299 CDevSettings_SetPruningMode(PVOID Context,
300 BOOL PruningOn)
301 {
302 HKEY hKey;
303 DWORD dwValue;
304 PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
305
306 DPRINT1("CDevSettings::SetPruningMode(%d)\n", PruningOn);
307
308 if (This->bModesPruned && !This->bKeyIsReadOnly &&
309 PruningOn != This->bPruningOn)
310 {
311 This->bPruningOn = (PruningOn != FALSE);
312
313 hKey = pCDevSettings_OpenDeviceKey(This,
314 FALSE);
315 if (hKey != NULL)
316 {
317 dwValue = (DWORD)This->bPruningOn;
318
319 RegSetValueEx(hKey,
320 TEXT("PruningMode"),
321 0,
322 REG_DWORD,
323 (const BYTE *)&dwValue,
324 sizeof(dwValue));
325
326 RegCloseKey(hKey);
327 }
328 }
329 }
330
331 static VOID
332 pCDevSettings_ReadHardwareInfo(HKEY hKey,
333 LPCTSTR lpValueName,
334 LPWSTR lpBuffer)
335 {
336 DWORD type = REG_BINARY;
337 DWORD size = 128 * sizeof(WCHAR);
338 RegQueryValueEx(hKey,
339 lpValueName,
340 NULL,
341 &type,
342 (PBYTE)lpBuffer,
343 &size);
344 }
345
346 static VOID
347 pCDevSettings_InitializeExtInterface(PCDevSettings This)
348 {
349 PDESK_EXT_INTERFACE Interface = &This->ExtInterface;
350 HKEY hKeyDev;
351
352 ZeroMemory(Interface,
353 sizeof(*Interface));
354 Interface->cbSize = sizeof(*Interface);
355
356 /* Initialize the callback table */
357 Interface->Context = impl_to_interface(This, IDataObject);
358 Interface->EnumAllModes = CDevSettings_EnumAllModes;
359 Interface->SetCurrentMode = CDevSettings_SetCurrentMode;
360 Interface->GetCurrentMode = CDevSettings_GetCurrentMode;
361 Interface->SetPruningMode = CDevSettings_SetPruningMode;
362 Interface->GetPruningMode = CDevSettings_GetPruningMode;
363
364 /* Read the HardwareInformation.* values from the registry key */
365 hKeyDev = pCDevSettings_OpenDeviceKey(This,
366 TRUE);
367 if (hKeyDev != NULL)
368 {
369 DWORD dwType, dwMemSize = 0;
370 DWORD dwSize = sizeof(dwMemSize);
371
372 if (RegQueryValueEx(hKeyDev,
373 TEXT("HardwareInformation.MemorySize"),
374 NULL,
375 &dwType,
376 (PBYTE)&dwMemSize,
377 &dwSize) == ERROR_SUCCESS &&
378 (dwType == REG_BINARY || dwType == REG_DWORD) &&
379 dwSize == sizeof(dwMemSize))
380 {
381 dwMemSize /= 1024;
382
383 if (dwMemSize > 1024)
384 {
385 dwMemSize /= 1024;
386 if (dwMemSize > 1024)
387 {
388 wsprintf(Interface->MemorySize,
389 _T("%u GB"),
390 dwMemSize / 1024);
391 }
392 else
393 {
394 wsprintf(Interface->MemorySize,
395 _T("%u MB"),
396 dwMemSize);
397 }
398 }
399 else
400 {
401 wsprintf(Interface->MemorySize,
402 _T("%u KB"),
403 dwMemSize);
404 }
405 }
406
407 pCDevSettings_ReadHardwareInfo(hKeyDev,
408 TEXT("HardwareInformation.ChipType"),
409 Interface->ChipType);
410 pCDevSettings_ReadHardwareInfo(hKeyDev,
411 TEXT("HardwareInformation.DacType"),
412 Interface->DacType);
413 pCDevSettings_ReadHardwareInfo(hKeyDev,
414 TEXT("HardwareInformation.AdapterString"),
415 Interface->AdapterString);
416 pCDevSettings_ReadHardwareInfo(hKeyDev,
417 TEXT("HardwareInformation.BiosString"),
418 Interface->BiosString);
419 RegCloseKey(hKeyDev);
420 }
421 }
422
423 static HRESULT
424 pCDevSettings_Initialize(PCDevSettings This,
425 PDISPLAY_DEVICE_ENTRY DisplayDeviceInfo)
426 {
427 HKEY hKey;
428
429 This->Flags = 0;
430 This->StateFlags = DisplayDeviceInfo->DeviceStateFlags;
431 DPRINT1("This->StateFlags: %x\n", This->StateFlags);
432
433 /* Register clipboard formats */
434 This->cfExtInterface = RegisterClipboardFormat(DESK_EXT_EXTINTERFACE);
435 This->cfDisplayDevice = RegisterClipboardFormat(DESK_EXT_DISPLAYDEVICE);
436 This->cfDisplayName = RegisterClipboardFormat(DESK_EXT_DISPLAYNAME);
437 This->cfDisplayId = RegisterClipboardFormat(DESK_EXT_DISPLAYID);
438 This->cfDisplayKey = RegisterClipboardFormat(DESK_EXT_DISPLAYKEY);
439 This->cfDisplayStateFlags = RegisterClipboardFormat(DESK_EXT_DISPLAYSTATEFLAGS);
440 This->cfMonitorName = RegisterClipboardFormat(DESK_EXT_MONITORNAME);
441 This->cfMonitorDevice = RegisterClipboardFormat(DESK_EXT_MONITORDEVICE);
442 This->cfPruningMode = RegisterClipboardFormat(DESK_EXT_PRUNINGMODE);
443
444 /* Copy the device name */
445 This->pDisplayDevice = pCDevSettings_AllocAndCopyString(DisplayDeviceInfo->DeviceName);
446 DPRINT1("This->pDisplayDevice: %ws\n", This->pDisplayDevice);
447 This->pDisplayName = pCDevSettings_AllocAndCopyString(DisplayDeviceInfo->DeviceDescription);
448 DPRINT1("This->pDisplayName: %ws\n", This->pDisplayName);
449 This->pDisplayKey = pCDevSettings_AllocAndCopyString(DisplayDeviceInfo->DeviceKey);
450 DPRINT1("This->pDisplayKey: %ws\n", This->pDisplayKey);
451 This->pDisplayId = pCDevSettings_GetDeviceInstanceId(DisplayDeviceInfo->DeviceID);
452 DPRINT1("This->pDisplayId: %ws\n", This->pDisplayId);
453 This->pMonitorName = pCDevSettings_GetMonitorName(This->pDisplayDevice);
454 DPRINT1("This->pMonitorName: %ws\n", This->pMonitorName);
455 This->pMonitorDevice = pCDevSettings_GetMonitorDevice(This->pDisplayDevice);
456 DPRINT1("This->pMonitorDevice: %ws\n", This->pMonitorDevice);
457
458 /* Check pruning mode */
459 This->bModesPruned = ((DisplayDeviceInfo->DeviceStateFlags & DISPLAY_DEVICE_MODESPRUNED) != 0);
460 hKey = pCDevSettings_OpenDeviceKey(This,
461 FALSE);
462 if (hKey == NULL)
463 {
464 hKey = pCDevSettings_OpenDeviceKey(This,
465 FALSE);
466 This->bKeyIsReadOnly = TRUE;
467 }
468 if (hKey != NULL)
469 {
470 DWORD dw = 0;
471 DWORD dwType, dwSize;
472
473 dwSize = sizeof(dw);
474 if (RegQueryValueEx(hKey,
475 TEXT("PruningMode"),
476 NULL,
477 &dwType,
478 (PBYTE)&dw,
479 &dwSize) == ERROR_SUCCESS)
480 {
481 if (dwType == REG_DWORD && dwSize == sizeof(dw))
482 This->bPruningOn = (dw != 0);
483 }
484
485 RegCloseKey(hKey);
486 }
487
488 /* Initialize the shell extension interface */
489 pCDevSettings_InitializeExtInterface(This);
490
491 return S_OK;
492 }
493
494 static VOID
495 pCDevSettings_Free(PCDevSettings This)
496 {
497 pCDevSettings_FreeString(&This->pDisplayDevice);
498 pCDevSettings_FreeString(&This->pDisplayName);
499 pCDevSettings_FreeString(&This->pDisplayKey);
500 pCDevSettings_FreeString(&This->pDisplayId);
501 pCDevSettings_FreeString(&This->pMonitorName);
502 pCDevSettings_FreeString(&This->pMonitorDevice);
503 }
504
505 static HRESULT STDMETHODCALLTYPE
506 CDevSettings_QueryInterface(IDataObject* iface,
507 REFIID riid,
508 void** ppvObject)
509 {
510 PCDevSettings This = impl_from_IDataObject(iface);
511
512 *ppvObject = NULL;
513
514 if (IsEqualGUID(riid,
515 &IID_IUnknown) ||
516 IsEqualGUID(riid,
517 &IID_IDataObject))
518 {
519 *ppvObject = (PVOID)impl_to_interface(This, IDataObject);
520 return S_OK;
521 }
522 else
523 {
524 DPRINT1("CDevSettings::QueryInterface: Queried unknown interface\n");
525 }
526
527 return E_NOINTERFACE;
528 }
529
530 static ULONG STDMETHODCALLTYPE
531 CDevSettings_AddRef(IDataObject* iface)
532 {
533 PCDevSettings This = impl_from_IDataObject(iface);
534 return (ULONG)InterlockedIncrement((PLONG)&This->ref);
535 }
536
537 static ULONG STDMETHODCALLTYPE
538 CDevSettings_Release(IDataObject* iface)
539 {
540 ULONG refs;
541 PCDevSettings This = impl_from_IDataObject(iface);
542 refs = (ULONG)InterlockedDecrement((PLONG)&This->ref);
543 if (refs == 0)
544 pCDevSettings_Free(This);
545
546 return refs;
547 }
548
549 static HRESULT STDMETHODCALLTYPE
550 CDevSettings_GetData(IDataObject* iface,
551 FORMATETC* pformatetcIn,
552 STGMEDIUM* pmedium)
553 {
554 static const WCHAR szEmpty[] = {0};
555 HRESULT hr;
556 PCWSTR pszRet = NULL;
557 PWSTR pszBuf;
558 PCDevSettings This = impl_from_IDataObject(iface);
559
560 ZeroMemory(pmedium,
561 sizeof(STGMEDIUM));
562
563 hr = IDataObject_QueryGetData(iface,
564 pformatetcIn);
565 if (SUCCEEDED(hr))
566 {
567 /* Return the reqested data back to the shell extension */
568
569 if (pformatetcIn->cfFormat == This->cfDisplayDevice)
570 {
571 pszRet = This->pDisplayDevice;
572 DPRINT1("CDevSettings::GetData returns display device %ws\n", pszRet);
573 }
574 else if (pformatetcIn->cfFormat == This->cfDisplayName)
575 {
576 pszRet = This->pDisplayName;
577 DPRINT1("CDevSettings::GetData returns display name %ws\n", pszRet);
578 }
579 else if (pformatetcIn->cfFormat == This->cfDisplayKey)
580 {
581 pszRet = This->pDisplayKey;
582 DPRINT1("CDevSettings::GetData returns display key %ws\n", pszRet);
583 }
584 else if (pformatetcIn->cfFormat == This->cfDisplayId)
585 {
586 pszRet = This->pDisplayId;
587 DPRINT1("CDevSettings::GetData returns display id %ws\n", pszRet);
588 }
589 else if (pformatetcIn->cfFormat == This->cfMonitorName)
590 {
591 pszRet = This->pMonitorName;
592 DPRINT1("CDevSettings::GetData returns monitor name %ws\n", pszRet);
593 }
594 else if (pformatetcIn->cfFormat == This->cfMonitorDevice)
595 {
596 pszRet = This->pMonitorDevice;
597 DPRINT1("CDevSettings::GetData returns monitor device %ws\n", pszRet);
598 }
599 else if (pformatetcIn->cfFormat == This->cfExtInterface)
600 {
601 PDESK_EXT_INTERFACE pIface;
602
603 pIface = GlobalAlloc(GPTR,
604 sizeof(*pIface));
605 if (pIface != NULL)
606 {
607 CopyMemory(pIface,
608 &This->ExtInterface,
609 sizeof(This->ExtInterface));
610
611 DPRINT1("CDevSettings::GetData returns the desk.cpl extension interface\n");
612
613 pmedium->tymed = TYMED_HGLOBAL;
614 pmedium->hGlobal = pIface;
615
616 return S_OK;
617 }
618 else
619 return E_OUTOFMEMORY;
620 }
621 else if (pformatetcIn->cfFormat == This->cfDisplayStateFlags)
622 {
623 PDWORD pdw;
624
625 pdw = GlobalAlloc(GPTR,
626 sizeof(*pdw));
627 if (pdw != NULL)
628 {
629 *pdw = This->StateFlags;
630
631 DPRINT1("CDevSettings::GetData returns the display state flags %x\n", This->StateFlags);
632
633 pmedium->tymed = TYMED_HGLOBAL;
634 pmedium->hGlobal = pdw;
635
636 return S_OK;
637 }
638 else
639 return E_OUTOFMEMORY;
640 }
641 else if (pformatetcIn->cfFormat == This->cfPruningMode)
642 {
643 PBYTE pb;
644
645 pb = GlobalAlloc(GPTR,
646 sizeof(*pb));
647 if (pb != NULL)
648 {
649 *pb = (This->bModesPruned && This->bPruningOn);
650
651 pmedium->tymed = TYMED_HGLOBAL;
652 pmedium->hGlobal = pb;
653
654 return S_OK;
655 }
656 else
657 return E_OUTOFMEMORY;
658 }
659
660 /* NOTE: This only returns null-terminated strings! */
661 if (pszRet == NULL)
662 pszRet = szEmpty;
663
664 pszBuf = GlobalAlloc(GPTR,
665 (wcslen(pszRet) + 1) * sizeof(WCHAR));
666 if (pszBuf != NULL)
667 {
668 hr = StringCbCopy(pszBuf, (wcslen(pszRet) + 1) * sizeof(WCHAR), pszRet);
669 if (FAILED(hr))
670 {
671 GlobalFree(pszBuf);
672 return hr;
673 }
674
675 pmedium->tymed = TYMED_HGLOBAL;
676 pmedium->hGlobal = pszBuf;
677
678 hr = S_OK;
679 }
680 else
681 hr = E_OUTOFMEMORY;
682 }
683
684 return hr;
685 }
686
687 static HRESULT STDMETHODCALLTYPE
688 CDevSettings_GetDataHere(IDataObject* iface,
689 FORMATETC* pformatetc,
690 STGMEDIUM* pmedium)
691 {
692 ZeroMemory(pformatetc,
693 sizeof(*pformatetc));
694 return E_NOTIMPL;
695 }
696
697 static HRESULT STDMETHODCALLTYPE
698 CDevSettings_QueryGetData(IDataObject* iface,
699 FORMATETC* pformatetc)
700 {
701 #if DEBUG
702 TCHAR szFormatName[255];
703 #endif
704 PCDevSettings This = impl_from_IDataObject(iface);
705
706 if (pformatetc->dwAspect != DVASPECT_CONTENT)
707 return DV_E_DVASPECT;
708
709 if (pformatetc->lindex != -1)
710 return DV_E_LINDEX;
711
712 if (!(pformatetc->tymed & TYMED_HGLOBAL))
713 return DV_E_TYMED;
714
715 /* Check if the requested data can be provided */
716 if (pformatetc->cfFormat == This->cfExtInterface ||
717 pformatetc->cfFormat == This->cfDisplayDevice ||
718 pformatetc->cfFormat == This->cfDisplayName ||
719 pformatetc->cfFormat == This->cfDisplayId ||
720 pformatetc->cfFormat == This->cfDisplayKey ||
721 pformatetc->cfFormat == This->cfDisplayStateFlags ||
722 pformatetc->cfFormat == This->cfMonitorDevice ||
723 pformatetc->cfFormat == This->cfMonitorName ||
724 pformatetc->cfFormat == This->cfPruningMode)
725 {
726 return S_OK;
727 }
728 #if DEBUG
729 else
730 {
731 if (GetClipboardFormatName(pformatetc->cfFormat,
732 szFormatName,
733 sizeof(szFormatName) / sizeof(szFormatName[0])))
734 {
735 DPRINT1("CDevSettings::QueryGetData(\"%ws\")\n", szFormatName);
736 }
737 else
738 {
739 DPRINT1("CDevSettings::QueryGetData(Format %u)\n", (unsigned int)pformatetc->cfFormat);
740 }
741 }
742 #endif
743
744 return DV_E_FORMATETC;
745 }
746
747 static HRESULT STDMETHODCALLTYPE
748 CDevSettings_GetCanonicalFormatEtc(IDataObject* iface,
749 FORMATETC* pformatectIn,
750 FORMATETC* pformatetcOut)
751 {
752 HRESULT hr;
753
754 DPRINT1("CDevSettings::GetCanonicalFormatEtc\n");
755
756 hr = IDataObject_QueryGetData(iface,
757 pformatectIn);
758 if (SUCCEEDED(hr))
759 {
760 CopyMemory(pformatetcOut,
761 pformatectIn,
762 sizeof(FORMATETC));
763
764 /* Make sure the data is target device independent */
765 if (pformatectIn->ptd == NULL)
766 hr = DATA_S_SAMEFORMATETC;
767 else
768 {
769 pformatetcOut->ptd = NULL;
770 hr = S_OK;
771 }
772 }
773 else
774 {
775 ZeroMemory(pformatetcOut,
776 sizeof(FORMATETC));
777 }
778
779 return hr;
780 }
781
782 static HRESULT STDMETHODCALLTYPE
783 CDevSettings_SetData(IDataObject* iface,
784 FORMATETC* pformatetc,
785 STGMEDIUM* pmedium,
786 BOOL fRelease)
787 {
788 DPRINT1("CDevSettings::SetData UNIMPLEMENTED\n");
789 return E_NOTIMPL;
790 }
791
792 static __inline VOID
793 pCDevSettings_FillFormatEtc(FORMATETC *pFormatEtc,
794 CLIPFORMAT cf)
795 {
796 pFormatEtc->cfFormat = cf;
797 pFormatEtc->ptd = NULL;
798 pFormatEtc->dwAspect = DVASPECT_CONTENT;
799 pFormatEtc->lindex = -1;
800 pFormatEtc->tymed = TYMED_HGLOBAL;
801 }
802
803 static HRESULT STDMETHODCALLTYPE
804 CDevSettings_EnumFormatEtc(IDataObject* iface,
805 DWORD dwDirection,
806 IEnumFORMATETC** ppenumFormatEtc)
807 {
808 HRESULT hr;
809 FORMATETC fetc[9];
810 PCDevSettings This = impl_from_IDataObject(iface);
811
812 *ppenumFormatEtc = NULL;
813
814 if (dwDirection == DATADIR_GET)
815 {
816 pCDevSettings_FillFormatEtc(&fetc[0],
817 This->cfExtInterface);
818 pCDevSettings_FillFormatEtc(&fetc[1],
819 This->cfDisplayDevice);
820 pCDevSettings_FillFormatEtc(&fetc[2],
821 This->cfDisplayName);
822 pCDevSettings_FillFormatEtc(&fetc[3],
823 This->cfDisplayId);
824 pCDevSettings_FillFormatEtc(&fetc[4],
825 This->cfDisplayKey);
826 pCDevSettings_FillFormatEtc(&fetc[5],
827 This->cfDisplayStateFlags);
828 pCDevSettings_FillFormatEtc(&fetc[6],
829 This->cfMonitorName);
830 pCDevSettings_FillFormatEtc(&fetc[7],
831 This->cfMonitorDevice);
832 pCDevSettings_FillFormatEtc(&fetc[8],
833 This->cfPruningMode);
834
835 hr = SHCreateStdEnumFmtEtc(sizeof(fetc) / sizeof(fetc[0]),
836 fetc,
837 ppenumFormatEtc);
838 }
839 else
840 hr = E_NOTIMPL;
841
842 return hr;
843 }
844
845 static HRESULT STDMETHODCALLTYPE
846 CDevSettings_DAdvise(IDataObject* iface,
847 FORMATETC* pformatetc,
848 DWORD advf,
849 IAdviseSink* pAdvSink,
850 DWORD* pdwConnection)
851 {
852 *pdwConnection = 0;
853 return OLE_E_ADVISENOTSUPPORTED;
854 }
855
856 static HRESULT STDMETHODCALLTYPE
857 CDevSettings_DUnadvise(IDataObject* iface,
858 DWORD dwConnection)
859 {
860 return OLE_E_ADVISENOTSUPPORTED;
861 }
862
863 static HRESULT STDMETHODCALLTYPE
864 CDevSettings_EnumDAdvise(IDataObject* iface,
865 IEnumSTATDATA** ppenumAdvise)
866 {
867 *ppenumAdvise = NULL;
868 return OLE_E_ADVISENOTSUPPORTED;
869 }
870
871 static const struct IDataObjectVtbl vtblIDataObject = {
872 CDevSettings_QueryInterface,
873 CDevSettings_AddRef,
874 CDevSettings_Release,
875 CDevSettings_GetData,
876 CDevSettings_GetDataHere,
877 CDevSettings_QueryGetData,
878 CDevSettings_GetCanonicalFormatEtc,
879 CDevSettings_SetData,
880 CDevSettings_EnumFormatEtc,
881 CDevSettings_DAdvise,
882 CDevSettings_DUnadvise,
883 CDevSettings_EnumDAdvise,
884 };
885
886 IDataObject *
887 CreateDevSettings(PDISPLAY_DEVICE_ENTRY DisplayDeviceInfo)
888 {
889 PCDevSettings This;
890
891 This = HeapAlloc(GetProcessHeap(),
892 0,
893 sizeof(*This));
894 if (This != NULL)
895 {
896 This->lpIDataObjectVtbl = &vtblIDataObject;
897 This->ref = 1;
898
899 if (SUCCEEDED(pCDevSettings_Initialize(This,
900 DisplayDeviceInfo)))
901 {
902 return impl_to_interface(This, IDataObject);
903 }
904
905 CDevSettings_Release(impl_to_interface(This, IDataObject));
906 }
907
908 return NULL;
909 }
910
911 LONG WINAPI
912 DisplaySaveSettings(PVOID pContext,
913 HWND hwndPropSheet)
914 {
915 //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
916 DPRINT("DisplaySaveSettings() UNIMPLEMENTED!\n");
917 return DISP_CHANGE_BADPARAM;
918 }