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 SIZE_T 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 requested 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 = StringCbCopyW(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 } 919