1 /* 2 * PROJECT: ReactOS user32.dll 3 * FILE: win32ss/user/user32/misc/display.c 4 * PURPOSE: DDE 5 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 6 */ 7 8 #include <user32.h> 9 10 WINE_DEFAULT_DEBUG_CHANNEL(user32); 11 12 #define SIZEOF_DEVMODEA_300 124 13 #define SIZEOF_DEVMODEA_400 148 14 #define SIZEOF_DEVMODEA_500 156 15 #define SIZEOF_DEVMODEW_300 188 16 #define SIZEOF_DEVMODEW_400 212 17 #define SIZEOF_DEVMODEW_500 220 18 19 /* 20 * @implemented 21 */ 22 BOOL WINAPI 23 EnumDisplayDevicesA( 24 LPCSTR lpDevice, 25 DWORD iDevNum, 26 PDISPLAY_DEVICEA lpDisplayDevice, 27 DWORD dwFlags) 28 { 29 BOOL rc; 30 UNICODE_STRING Device; 31 DISPLAY_DEVICEW DisplayDeviceW; 32 33 if (!RtlCreateUnicodeStringFromAsciiz(&Device, (PCSZ)lpDevice)) 34 { 35 SetLastError(ERROR_OUTOFMEMORY); 36 return FALSE; 37 } 38 39 RtlZeroMemory(&DisplayDeviceW, sizeof(DISPLAY_DEVICEW)); 40 DisplayDeviceW.cb = sizeof(DISPLAY_DEVICEW); 41 rc = NtUserEnumDisplayDevices(&Device, 42 iDevNum, 43 &DisplayDeviceW, 44 dwFlags); 45 if (rc) 46 { 47 /* Copy result from DisplayDeviceW to lpDisplayDevice. Buffers have the same size so result is always NULL terminated. */ 48 lpDisplayDevice->StateFlags = DisplayDeviceW.StateFlags; 49 WideCharToMultiByte(CP_ACP, 0, DisplayDeviceW.DeviceName, -1, 50 lpDisplayDevice->DeviceName, 51 sizeof(lpDisplayDevice->DeviceName) / sizeof(lpDisplayDevice->DeviceName[0]), 52 NULL, NULL); 53 WideCharToMultiByte(CP_ACP, 0, DisplayDeviceW.DeviceString, -1, 54 lpDisplayDevice->DeviceString, 55 sizeof(lpDisplayDevice->DeviceString) / sizeof(lpDisplayDevice->DeviceString[0]), 56 NULL, NULL); 57 WideCharToMultiByte(CP_ACP, 0, DisplayDeviceW.DeviceID, -1, 58 lpDisplayDevice->DeviceID, 59 sizeof(lpDisplayDevice->DeviceID) / sizeof(lpDisplayDevice->DeviceID[0]), 60 NULL, NULL); 61 WideCharToMultiByte(CP_ACP, 0, DisplayDeviceW.DeviceKey, -1, 62 lpDisplayDevice->DeviceKey, 63 sizeof(lpDisplayDevice->DeviceKey) / sizeof(lpDisplayDevice->DeviceKey[0]), 64 NULL, NULL); 65 } 66 67 RtlFreeUnicodeString(&Device); 68 69 return rc; 70 } 71 72 73 /* 74 * @implemented 75 */ 76 BOOL 77 WINAPI 78 EnumDisplayDevicesW( 79 LPCWSTR lpDevice, 80 DWORD iDevNum, 81 PDISPLAY_DEVICEW lpDisplayDevice, 82 DWORD dwFlags) 83 { 84 UNICODE_STRING Device; 85 BOOL rc; 86 87 RtlInitUnicodeString(&Device, lpDevice); 88 89 rc = NtUserEnumDisplayDevices( 90 &Device, 91 iDevNum, 92 lpDisplayDevice, 93 dwFlags); 94 95 return rc; 96 } 97 98 99 /* 100 * @implemented 101 */ 102 BOOL 103 WINAPI 104 EnumDisplayMonitors( 105 HDC hdc, 106 LPCRECT lprcClip, 107 MONITORENUMPROC lpfnEnum, 108 LPARAM dwData) 109 { 110 INT iCount, i; 111 HMONITOR *hMonitorList; 112 LPRECT pRectList; 113 HANDLE hHeap; 114 BOOL ret = FALSE; 115 116 /* get list of monitors/rects */ 117 iCount = NtUserEnumDisplayMonitors(hdc, lprcClip, NULL, NULL, 0); 118 if (iCount < 0) 119 { 120 /* FIXME: SetLastError() */ 121 return FALSE; 122 } 123 if (iCount == 0) 124 { 125 return TRUE; 126 } 127 128 hHeap = GetProcessHeap(); 129 hMonitorList = HeapAlloc(hHeap, 0, sizeof (HMONITOR) * iCount); 130 if (hMonitorList == NULL) 131 { 132 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 133 return FALSE; 134 } 135 pRectList = HeapAlloc(hHeap, 0, sizeof (RECT) * iCount); 136 if (pRectList == NULL) 137 { 138 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 139 goto cleanup; 140 } 141 142 iCount = NtUserEnumDisplayMonitors(hdc, lprcClip, hMonitorList, pRectList, iCount); 143 if (iCount <= 0) 144 { 145 /* FIXME: SetLastError() */ 146 goto cleanup; 147 } 148 149 /* enumerate list */ 150 for (i = 0; i < iCount; i++) 151 { 152 HMONITOR hMonitor = hMonitorList[i]; 153 LPRECT pMonitorRect = pRectList + i; 154 HDC hMonitorDC = NULL; 155 156 if (hdc != NULL) 157 { 158 /* make monitor DC */ 159 hMonitorDC = hdc; 160 } 161 162 if (!lpfnEnum(hMonitor, hMonitorDC, pMonitorRect, dwData)) 163 goto cleanup; /* return FALSE */ 164 } 165 166 ret = TRUE; 167 168 cleanup: 169 if(hMonitorList) 170 HeapFree(hHeap, 0, hMonitorList); 171 if(pRectList) 172 HeapFree(hHeap, 0, pRectList); 173 return ret; 174 } 175 176 177 /* 178 * @implemented 179 */ 180 BOOL 181 WINAPI 182 EnumDisplaySettingsExA( 183 LPCSTR lpszDeviceName, 184 DWORD iModeNum, 185 LPDEVMODEA lpDevMode, 186 DWORD dwFlags) 187 { 188 NTSTATUS Status; 189 UNICODE_STRING usDeviceName; 190 PUNICODE_STRING pusDeviceName = NULL; 191 LPDEVMODEW lpExtendedDevMode; 192 BOOL Result = FALSE; 193 194 if (lpszDeviceName) 195 { 196 if (!RtlCreateUnicodeStringFromAsciiz(&usDeviceName, (PCSZ)lpszDeviceName)) 197 { 198 SetLastError(ERROR_OUTOFMEMORY); 199 return FALSE; 200 } 201 pusDeviceName = &usDeviceName; 202 } 203 204 /* Allocate memory for DEVMODEW and extra data */ 205 lpExtendedDevMode = RtlAllocateHeap(RtlGetProcessHeap(), 206 HEAP_ZERO_MEMORY, 207 sizeof(DEVMODEW) + lpDevMode->dmDriverExtra); 208 if (!lpExtendedDevMode) 209 { 210 if (pusDeviceName) 211 RtlFreeUnicodeString(&usDeviceName); 212 213 return FALSE; 214 } 215 216 /* Initialize structure fields */ 217 lpExtendedDevMode->dmSize = sizeof(DEVMODEW); 218 lpExtendedDevMode->dmDriverExtra = lpDevMode->dmDriverExtra; 219 220 Status = NtUserEnumDisplaySettings(pusDeviceName, iModeNum, lpExtendedDevMode, dwFlags); 221 222 if (pusDeviceName) 223 RtlFreeUnicodeString(&usDeviceName); 224 225 if (NT_SUCCESS(Status)) 226 { 227 /* Store old structure size */ 228 WORD OldSize = lpDevMode->dmSize; 229 230 #define COPYS(f,len) WideCharToMultiByte(CP_THREAD_ACP, 0, lpExtendedDevMode->f, len, (LPSTR)lpDevMode->f, len, NULL, NULL) 231 #define COPYN(f) lpDevMode->f = lpExtendedDevMode->f 232 233 COPYS(dmDeviceName, CCHDEVICENAME); 234 COPYN(dmSpecVersion); 235 COPYN(dmDriverVersion); 236 COPYN(dmFields); 237 COPYN(dmPosition.x); 238 COPYN(dmPosition.y); 239 COPYN(dmScale); 240 COPYN(dmCopies); 241 COPYN(dmDefaultSource); 242 COPYN(dmPrintQuality); 243 COPYN(dmColor); 244 COPYN(dmDuplex); 245 COPYN(dmYResolution); 246 COPYN(dmTTOption); 247 COPYN(dmCollate); 248 COPYS(dmFormName,CCHFORMNAME); 249 COPYN(dmLogPixels); 250 COPYN(dmBitsPerPel); 251 COPYN(dmPelsWidth); 252 COPYN(dmPelsHeight); 253 COPYN(dmDisplayFlags); // aka dmNup 254 COPYN(dmDisplayFrequency); 255 256 /* we're done with 0x300 fields */ 257 if (OldSize > SIZEOF_DEVMODEA_300) 258 { 259 COPYN(dmICMMethod); 260 COPYN(dmICMIntent); 261 COPYN(dmMediaType); 262 COPYN(dmDitherType); 263 COPYN(dmReserved1); 264 COPYN(dmReserved2); 265 266 /* we're done with 0x400 fields */ 267 if (OldSize > SIZEOF_DEVMODEA_400) 268 { 269 COPYN(dmPanningWidth); 270 COPYN(dmPanningHeight); 271 } 272 } 273 274 /* Restore old size */ 275 lpDevMode->dmSize = OldSize; 276 277 /* Extra data presented? */ 278 if (lpDevMode->dmDriverExtra && lpExtendedDevMode->dmDriverExtra) 279 { 280 /* We choose the smallest size */ 281 if (lpDevMode->dmDriverExtra > lpExtendedDevMode->dmDriverExtra) 282 lpDevMode->dmDriverExtra = lpExtendedDevMode->dmDriverExtra; 283 284 /* Copy extra data */ 285 RtlCopyMemory((PUCHAR)lpDevMode + OldSize, 286 lpExtendedDevMode + 1, 287 lpDevMode->dmDriverExtra); 288 } 289 290 /* If the size of source structure is less, than used, we clean unsupported flags */ 291 if (OldSize < FIELD_OFFSET(DEVMODEA, dmPanningHeight)) 292 lpDevMode->dmFields &= ~DM_PANNINGHEIGHT; 293 294 if (OldSize < FIELD_OFFSET(DEVMODEA, dmPanningWidth)) 295 lpDevMode->dmFields &= ~DM_PANNINGWIDTH; 296 297 Result = TRUE; 298 } 299 300 /* Free memory */ 301 RtlFreeHeap(RtlGetProcessHeap(), 0, lpExtendedDevMode); 302 303 return Result; 304 } 305 306 307 /* 308 * @implemented 309 */ 310 BOOL 311 WINAPI 312 EnumDisplaySettingsA( 313 LPCSTR lpszDeviceName, 314 DWORD iModeNum, 315 LPDEVMODEA lpDevMode) 316 { 317 /* Fixup sizes */ 318 lpDevMode->dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod); 319 lpDevMode->dmDriverExtra = 0; 320 321 return EnumDisplaySettingsExA(lpszDeviceName, iModeNum, lpDevMode, 0); 322 } 323 324 325 /* 326 * @implemented 327 */ 328 BOOL 329 WINAPI 330 EnumDisplaySettingsExW( 331 LPCWSTR lpszDeviceName, 332 DWORD iModeNum, 333 LPDEVMODEW lpDevMode, 334 DWORD dwFlags) 335 { 336 NTSTATUS Status; 337 UNICODE_STRING usDeviceName; 338 PUNICODE_STRING pusDeviceName = NULL; 339 LPDEVMODEW lpExtendedDevMode; 340 BOOL Result = FALSE; 341 342 if (lpszDeviceName) 343 { 344 RtlInitUnicodeString(&usDeviceName, lpszDeviceName); 345 pusDeviceName = &usDeviceName; 346 } 347 348 /* Allocate memory for DEVMODEW and extra data */ 349 lpExtendedDevMode = RtlAllocateHeap(RtlGetProcessHeap(), 350 HEAP_ZERO_MEMORY, 351 sizeof(DEVMODEW) + lpDevMode->dmDriverExtra); 352 if (!lpExtendedDevMode) 353 return FALSE; 354 355 /* Initialize structure fields */ 356 lpExtendedDevMode->dmSize = sizeof(DEVMODEW); 357 lpExtendedDevMode->dmDriverExtra = lpDevMode->dmDriverExtra; 358 359 Status = NtUserEnumDisplaySettings(pusDeviceName, iModeNum, lpExtendedDevMode, dwFlags); 360 if (NT_SUCCESS(Status)) 361 { 362 /* Store old structure sizes */ 363 WORD OldSize = lpDevMode->dmSize; 364 WORD OldDriverExtra = lpDevMode->dmDriverExtra; 365 366 /* Copy general data */ 367 RtlCopyMemory(lpDevMode, lpExtendedDevMode, OldSize); 368 369 /* Restore old sizes */ 370 lpDevMode->dmSize = OldSize; 371 lpDevMode->dmDriverExtra = OldDriverExtra; 372 373 /* Extra data presented? */ 374 if (lpDevMode->dmDriverExtra && lpExtendedDevMode->dmDriverExtra) 375 { 376 /* We choose the smallest size */ 377 if (lpDevMode->dmDriverExtra > lpExtendedDevMode->dmDriverExtra) 378 lpDevMode->dmDriverExtra = lpExtendedDevMode->dmDriverExtra; 379 380 /* Copy extra data */ 381 RtlCopyMemory((PUCHAR)lpDevMode + OldSize, 382 lpExtendedDevMode + 1, 383 lpDevMode->dmDriverExtra); 384 } 385 386 /* If the size of source structure is less, than used, we clean unsupported flags */ 387 if (OldSize < FIELD_OFFSET(DEVMODEW, dmPanningHeight)) 388 lpDevMode->dmFields &= ~DM_PANNINGHEIGHT; 389 390 if (OldSize < FIELD_OFFSET(DEVMODEW, dmPanningWidth)) 391 lpDevMode->dmFields &= ~DM_PANNINGWIDTH; 392 393 Result = TRUE; 394 } 395 396 /* Free memory */ 397 RtlFreeHeap(RtlGetProcessHeap(), 0, lpExtendedDevMode); 398 399 return Result; 400 } 401 402 403 /* 404 * @implemented 405 */ 406 BOOL 407 WINAPI 408 EnumDisplaySettingsW( 409 LPCWSTR lpszDeviceName, 410 DWORD iModeNum, 411 LPDEVMODEW lpDevMode) 412 { 413 /* Fixup sizes */ 414 lpDevMode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod); 415 lpDevMode->dmDriverExtra = 0; 416 417 return EnumDisplaySettingsExW(lpszDeviceName, iModeNum, lpDevMode, 0); 418 } 419 420 421 /* 422 * @implemented 423 */ 424 BOOL 425 WINAPI 426 GetMonitorInfoA( 427 HMONITOR hMonitor, 428 LPMONITORINFO lpmi) 429 { 430 if (lpmi->cbSize == sizeof (MONITORINFO)) 431 { 432 return NtUserGetMonitorInfo(hMonitor, lpmi); 433 } 434 else if (lpmi->cbSize != sizeof (MONITORINFOEXA)) 435 { 436 SetLastError(ERROR_INVALID_PARAMETER); 437 return FALSE; 438 } 439 else 440 { 441 MONITORINFOEXW miExW; 442 INT res; 443 444 miExW.cbSize = sizeof (MONITORINFOEXW); 445 if (!NtUserGetMonitorInfo(hMonitor, (LPMONITORINFO)&miExW)) 446 { 447 return FALSE; 448 } 449 memcpy(lpmi, &miExW, sizeof (MONITORINFO)); 450 res = WideCharToMultiByte(CP_THREAD_ACP, 0, miExW.szDevice, -1, 451 ((LPMONITORINFOEXA)lpmi)->szDevice, CCHDEVICENAME, 452 NULL, NULL); 453 if (res == 0) 454 { 455 WARN("WideCharToMultiByte() failed!\n"); 456 return FALSE; 457 } 458 } 459 460 return TRUE; 461 } 462 463 464 /* 465 * @implemented 466 */ 467 BOOL 468 WINAPI 469 GetMonitorInfoW( 470 HMONITOR hMonitor, 471 LPMONITORINFO lpmi) 472 { 473 return NtUserGetMonitorInfo(hMonitor, lpmi); 474 } 475 476 477 /* 478 * @implemented 479 */ 480 HMONITOR 481 WINAPI 482 MonitorFromPoint( 483 IN POINT ptPoint, 484 IN DWORD dwFlags ) 485 { 486 return NtUserMonitorFromPoint(ptPoint, dwFlags); 487 } 488 489 490 /* 491 * @implemented 492 */ 493 HMONITOR 494 WINAPI 495 MonitorFromRect( 496 IN LPCRECT lpcRect, 497 IN DWORD dwFlags ) 498 { 499 return NtUserMonitorFromRect(lpcRect, dwFlags); 500 } 501 502 503 /* 504 * @implemented 505 */ 506 HMONITOR 507 WINAPI 508 MonitorFromWindow( 509 IN HWND hWnd, 510 IN DWORD dwFlags ) 511 { 512 return NtUserMonitorFromWindow(hWnd, dwFlags); 513 } 514 515 516 /* 517 * @implemented 518 */ 519 LONG 520 WINAPI 521 ChangeDisplaySettingsExA( 522 LPCSTR lpszDeviceName, 523 LPDEVMODEA lpDevMode, 524 HWND hwnd, 525 DWORD dwflags, 526 LPVOID lParam) 527 { 528 LONG rc; 529 UNICODE_STRING DeviceName; 530 PUNICODE_STRING pDeviceName = &DeviceName; 531 532 if (lpszDeviceName != NULL) 533 { 534 if (!RtlCreateUnicodeStringFromAsciiz(pDeviceName, (PCSZ)lpszDeviceName)) 535 { 536 SetLastError(ERROR_OUTOFMEMORY); 537 return DISP_CHANGE_BADPARAM; /* FIXME what to return? */ 538 } 539 } 540 else 541 pDeviceName = NULL; 542 543 if (lpDevMode != NULL) 544 { 545 LPDEVMODEW pDevModeW; 546 pDevModeW = GdiConvertToDevmodeW(lpDevMode); 547 if(pDevModeW) 548 { 549 rc = NtUserChangeDisplaySettings(pDeviceName, pDevModeW, dwflags, lParam); 550 RtlFreeHeap(GetProcessHeap(), 0, pDevModeW); 551 } 552 else 553 rc = DISP_CHANGE_SUCCESSFUL; 554 } 555 else 556 rc = NtUserChangeDisplaySettings(pDeviceName, NULL, dwflags, lParam); 557 558 if (lpszDeviceName != NULL) 559 RtlFreeUnicodeString(&DeviceName); 560 561 return rc; 562 } 563 564 565 /* 566 * @implemented 567 */ 568 LONG 569 WINAPI 570 ChangeDisplaySettingsA( 571 LPDEVMODEA lpDevMode, 572 DWORD dwflags) 573 { 574 if(lpDevMode) 575 lpDevMode->dmDriverExtra = 0; 576 return ChangeDisplaySettingsExA ( NULL, lpDevMode, NULL, dwflags, 0 ); 577 } 578 579 580 /* 581 * @implemented 582 */ 583 LONG 584 WINAPI 585 ChangeDisplaySettingsExW( 586 LPCWSTR lpszDeviceName, 587 LPDEVMODEW lpDevMode, 588 HWND hwnd, 589 DWORD dwflags, 590 LPVOID lParam) 591 { 592 LONG rc; 593 UNICODE_STRING DeviceName; 594 PUNICODE_STRING pDeviceName = &DeviceName; 595 596 if (lpszDeviceName != NULL) 597 RtlInitUnicodeString(pDeviceName, lpszDeviceName); 598 else 599 pDeviceName = NULL; 600 601 rc = NtUserChangeDisplaySettings(pDeviceName, lpDevMode, dwflags, lParam); 602 603 return rc; 604 } 605 606 607 /* 608 * @implemented 609 */ 610 LONG 611 WINAPI 612 ChangeDisplaySettingsW( 613 LPDEVMODEW lpDevMode, 614 DWORD dwflags) 615 { 616 if(lpDevMode) 617 lpDevMode->dmDriverExtra = 0; 618 return ChangeDisplaySettingsExW(NULL, lpDevMode, NULL, dwflags, 0); 619 } 620