Merge to trunk head (r46631)
[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: lib/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 wcscpy(str,
87 pszSrc);
88 #else
89 MultiByteToWideChar(CP_APC,
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 DbgPrint("Success1\n");
187 cr = CM_Get_Device_ID_Size(&BufLen,
188 DevInst,
189 0);
190 if (cr == CR_SUCCESS)
191 {
192 DbgPrint("Success2\n");
193 lpDevInstId = LocalAlloc(LMEM_FIXED,
194 (BufLen + 1) * sizeof(WCHAR));
195
196 if (lpDevInstId != NULL)
197 {
198 DbgPrint("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 DbgPrint("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 (_tcslen(pszRet) + 1) * sizeof(WCHAR));
666 if (pszBuf != NULL)
667 {
668 _tcscpy(pszBuf,
669 pszRet);
670
671 pmedium->tymed = TYMED_HGLOBAL;
672 pmedium->hGlobal = pszBuf;
673
674 hr = S_OK;
675 }
676 else
677 hr = E_OUTOFMEMORY;
678 }
679
680 return hr;
681 }
682
683 static HRESULT STDMETHODCALLTYPE
684 CDevSettings_GetDataHere(IDataObject* iface,
685 FORMATETC* pformatetc,
686 STGMEDIUM* pmedium)
687 {
688 ZeroMemory(pformatetc,
689 sizeof(*pformatetc));
690 return E_NOTIMPL;
691 }
692
693 static HRESULT STDMETHODCALLTYPE
694 CDevSettings_QueryGetData(IDataObject* iface,
695 FORMATETC* pformatetc)
696 {
697 #if DEBUG
698 TCHAR szFormatName[255];
699 #endif
700 PCDevSettings This = impl_from_IDataObject(iface);
701
702 if (pformatetc->dwAspect != DVASPECT_CONTENT)
703 return DV_E_DVASPECT;
704
705 if (pformatetc->lindex != -1)
706 return DV_E_LINDEX;
707
708 if (!(pformatetc->tymed & TYMED_HGLOBAL))
709 return DV_E_TYMED;
710
711 /* Check if the requested data can be provided */
712 if (pformatetc->cfFormat == This->cfExtInterface ||
713 pformatetc->cfFormat == This->cfDisplayDevice ||
714 pformatetc->cfFormat == This->cfDisplayName ||
715 pformatetc->cfFormat == This->cfDisplayId ||
716 pformatetc->cfFormat == This->cfDisplayKey ||
717 pformatetc->cfFormat == This->cfDisplayStateFlags ||
718 pformatetc->cfFormat == This->cfMonitorDevice ||
719 pformatetc->cfFormat == This->cfMonitorName ||
720 pformatetc->cfFormat == This->cfPruningMode)
721 {
722 return S_OK;
723 }
724 #if DEBUG
725 else
726 {
727 if (GetClipboardFormatName(pformatetc->cfFormat,
728 szFormatName,
729 sizeof(szFormatName) / sizeof(szFormatName[0])))
730 {
731 DPRINT1("CDevSettings::QueryGetData(\"%ws\")\n", szFormatName);
732 }
733 else
734 {
735 DPRINT1("CDevSettings::QueryGetData(Format %u)\n", (unsigned int)pformatetc->cfFormat);
736 }
737 }
738 #endif
739
740 return DV_E_FORMATETC;
741 }
742
743 static HRESULT STDMETHODCALLTYPE
744 CDevSettings_GetCanonicalFormatEtc(IDataObject* iface,
745 FORMATETC* pformatectIn,
746 FORMATETC* pformatetcOut)
747 {
748 HRESULT hr;
749
750 DPRINT1("CDevSettings::GetCanonicalFormatEtc\n");
751
752 hr = IDataObject_QueryGetData(iface,
753 pformatectIn);
754 if (SUCCEEDED(hr))
755 {
756 CopyMemory(pformatetcOut,
757 pformatectIn,
758 sizeof(FORMATETC));
759
760 /* Make sure the data is target device independent */
761 if (pformatectIn->ptd == NULL)
762 hr = DATA_S_SAMEFORMATETC;
763 else
764 {
765 pformatetcOut->ptd = NULL;
766 hr = S_OK;
767 }
768 }
769 else
770 {
771 ZeroMemory(pformatetcOut,
772 sizeof(FORMATETC));
773 }
774
775 return hr;
776 }
777
778 static HRESULT STDMETHODCALLTYPE
779 CDevSettings_SetData(IDataObject* iface,
780 FORMATETC* pformatetc,
781 STGMEDIUM* pmedium,
782 BOOL fRelease)
783 {
784 DPRINT1("CDevSettings::SetData UNIMPLEMENTED\n");
785 return E_NOTIMPL;
786 }
787
788 static __inline VOID
789 pCDevSettings_FillFormatEtc(FORMATETC *pFormatEtc,
790 CLIPFORMAT cf)
791 {
792 pFormatEtc->cfFormat = cf;
793 pFormatEtc->ptd = NULL;
794 pFormatEtc->dwAspect = DVASPECT_CONTENT;
795 pFormatEtc->lindex = -1;
796 pFormatEtc->tymed = TYMED_HGLOBAL;
797 }
798
799 static HRESULT STDMETHODCALLTYPE
800 CDevSettings_EnumFormatEtc(IDataObject* iface,
801 DWORD dwDirection,
802 IEnumFORMATETC** ppenumFormatEtc)
803 {
804 HRESULT hr;
805 FORMATETC fetc[9];
806 PCDevSettings This = impl_from_IDataObject(iface);
807
808 *ppenumFormatEtc = NULL;
809
810 if (dwDirection == DATADIR_GET)
811 {
812 pCDevSettings_FillFormatEtc(&fetc[0],
813 This->cfExtInterface);
814 pCDevSettings_FillFormatEtc(&fetc[1],
815 This->cfDisplayDevice);
816 pCDevSettings_FillFormatEtc(&fetc[2],
817 This->cfDisplayName);
818 pCDevSettings_FillFormatEtc(&fetc[3],
819 This->cfDisplayId);
820 pCDevSettings_FillFormatEtc(&fetc[4],
821 This->cfDisplayKey);
822 pCDevSettings_FillFormatEtc(&fetc[5],
823 This->cfDisplayStateFlags);
824 pCDevSettings_FillFormatEtc(&fetc[6],
825 This->cfMonitorName);
826 pCDevSettings_FillFormatEtc(&fetc[7],
827 This->cfMonitorDevice);
828 pCDevSettings_FillFormatEtc(&fetc[8],
829 This->cfPruningMode);
830
831 hr = SHCreateStdEnumFmtEtc(sizeof(fetc) / sizeof(fetc[0]),
832 fetc,
833 ppenumFormatEtc);
834 }
835 else
836 hr = E_NOTIMPL;
837
838 return hr;
839 }
840
841 static HRESULT STDMETHODCALLTYPE
842 CDevSettings_DAdvise(IDataObject* iface,
843 FORMATETC* pformatetc,
844 DWORD advf,
845 IAdviseSink* pAdvSink,
846 DWORD* pdwConnection)
847 {
848 *pdwConnection = 0;
849 return OLE_E_ADVISENOTSUPPORTED;
850 }
851
852 static HRESULT STDMETHODCALLTYPE
853 CDevSettings_DUnadvise(IDataObject* iface,
854 DWORD dwConnection)
855 {
856 return OLE_E_ADVISENOTSUPPORTED;
857 }
858
859 static HRESULT STDMETHODCALLTYPE
860 CDevSettings_EnumDAdvise(IDataObject* iface,
861 IEnumSTATDATA** ppenumAdvise)
862 {
863 *ppenumAdvise = NULL;
864 return OLE_E_ADVISENOTSUPPORTED;
865 }
866
867 static const struct IDataObjectVtbl vtblIDataObject = {
868 CDevSettings_QueryInterface,
869 CDevSettings_AddRef,
870 CDevSettings_Release,
871 CDevSettings_GetData,
872 CDevSettings_GetDataHere,
873 CDevSettings_QueryGetData,
874 CDevSettings_GetCanonicalFormatEtc,
875 CDevSettings_SetData,
876 CDevSettings_EnumFormatEtc,
877 CDevSettings_DAdvise,
878 CDevSettings_DUnadvise,
879 CDevSettings_EnumDAdvise,
880 };
881
882 IDataObject *
883 CreateDevSettings(PDISPLAY_DEVICE_ENTRY DisplayDeviceInfo)
884 {
885 PCDevSettings This;
886
887 This = HeapAlloc(GetProcessHeap(),
888 0,
889 sizeof(*This));
890 if (This != NULL)
891 {
892 This->lpIDataObjectVtbl = &vtblIDataObject;
893 This->ref = 1;
894
895 if (SUCCEEDED(pCDevSettings_Initialize(This,
896 DisplayDeviceInfo)))
897 {
898 return impl_to_interface(This, IDataObject);
899 }
900
901 CDevSettings_Release(impl_to_interface(This, IDataObject));
902 }
903
904 return NULL;
905 }
906
907 LONG WINAPI
908 DisplaySaveSettings(PVOID pContext,
909 HWND hwndPropSheet)
910 {
911 //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
912 DPRINT("DisplaySaveSettings() UNIMPLEMENTED!\n");
913 return DISP_CHANGE_BADPARAM;
914 }