1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS user32.dll 4 * FILE: win32ss/user/user32/misc/desktop.c 5 * PURPOSE: Desktops 6 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * UPDATE HISTORY: 8 * 06-06-2001 CSH Created 9 */ 10 11 #include <user32.h> 12 13 WINE_DEFAULT_DEBUG_CHANNEL(user32); 14 15 /********************************************************************* 16 * desktop class descriptor 17 */ 18 #if 0 // Kept for referencing. 19 const struct builtin_class_descr DESKTOP_builtin_class = 20 { 21 WC_DESKTOP, /* name */ 22 CS_DBLCLKS, /* style */ 23 NULL, /* procA (winproc is Unicode only) */ 24 DesktopWndProc, /* procW */ 25 0, /* extra */ 26 IDC_ARROW, /* cursor */ 27 (HBRUSH)(COLOR_BACKGROUND+1) /* brush */ 28 }; 29 #endif 30 31 LRESULT 32 WINAPI 33 DesktopWndProcW(HWND Wnd, 34 UINT Msg, 35 WPARAM wParam, 36 LPARAM lParam) 37 { 38 TRACE("Desktop W Class Atom! hWnd 0x%x, Msg %d\n", Wnd, Msg); 39 40 switch(Msg) 41 { 42 case WM_ERASEBKGND: 43 case WM_NCCREATE: 44 case WM_CREATE: 45 case WM_CLOSE: 46 case WM_DISPLAYCHANGE: 47 case WM_PAINT: 48 case WM_SYSCOLORCHANGE: 49 { 50 LRESULT lResult; 51 NtUserMessageCall( Wnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DESKTOP, FALSE); 52 TRACE("Desktop lResult %d\n", lResult); 53 return lResult; 54 } 55 56 case WM_PALETTECHANGED: 57 if (Wnd == (HWND)wParam) break; 58 case WM_QUERYNEWPALETTE: 59 { 60 HDC hdc = GetWindowDC( Wnd ); 61 PaintDesktop(hdc); 62 ReleaseDC( Wnd, hdc ); 63 break; 64 } 65 66 case WM_SETCURSOR: 67 return (LRESULT)SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW)); 68 69 default: 70 return DefWindowProcW(Wnd, Msg, wParam, lParam); 71 } 72 return 0; 73 } 74 75 VOID 76 WINAPI 77 LogFontA2W(LPLOGFONTW pW, CONST LOGFONTA *pA) 78 { 79 #define COPYS(f,len) MultiByteToWideChar ( CP_THREAD_ACP, 0, pA->f, len, pW->f, len ) 80 #define COPYN(f) pW->f = pA->f 81 82 COPYN(lfHeight); 83 COPYN(lfWidth); 84 COPYN(lfEscapement); 85 COPYN(lfOrientation); 86 COPYN(lfWeight); 87 COPYN(lfItalic); 88 COPYN(lfUnderline); 89 COPYN(lfStrikeOut); 90 COPYN(lfCharSet); 91 COPYN(lfOutPrecision); 92 COPYN(lfClipPrecision); 93 COPYN(lfQuality); 94 COPYN(lfPitchAndFamily); 95 COPYS(lfFaceName,LF_FACESIZE); 96 97 #undef COPYN 98 #undef COPYS 99 } 100 101 VOID 102 WINAPI 103 LogFontW2A(LPLOGFONTA pA, CONST LOGFONTW *pW) 104 { 105 #define COPYS(f,len) WideCharToMultiByte ( CP_THREAD_ACP, 0, pW->f, len, pA->f, len, NULL, NULL ) 106 #define COPYN(f) pA->f = pW->f 107 108 COPYN(lfHeight); 109 COPYN(lfWidth); 110 COPYN(lfEscapement); 111 COPYN(lfOrientation); 112 COPYN(lfWeight); 113 COPYN(lfItalic); 114 COPYN(lfUnderline); 115 COPYN(lfStrikeOut); 116 COPYN(lfCharSet); 117 COPYN(lfOutPrecision); 118 COPYN(lfClipPrecision); 119 COPYN(lfQuality); 120 COPYN(lfPitchAndFamily); 121 COPYS(lfFaceName,LF_FACESIZE); 122 123 #undef COPYN 124 #undef COPYS 125 } 126 127 int WINAPI 128 RealGetSystemMetrics(int nIndex) 129 { 130 //FIXME("Global Server Data -> %x\n",gpsi); 131 if (nIndex < 0 || nIndex >= SM_CMETRICS) return 0; 132 return gpsi->aiSysMet[nIndex]; 133 } 134 135 /* 136 * @implemented 137 */ 138 int WINAPI 139 GetSystemMetrics(int nIndex) 140 { 141 BOOL Hook; 142 int Ret = 0; 143 144 if (!gpsi) // Fixme! Hax! Need Timos delay load support? 145 { 146 return RealGetSystemMetrics(nIndex); 147 } 148 149 LoadUserApiHook(); 150 151 Hook = BeginIfHookedUserApiHook(); 152 153 /* Bypass SEH and go direct. */ 154 if (!Hook) return RealGetSystemMetrics(nIndex); 155 156 _SEH2_TRY 157 { 158 Ret = guah.GetSystemMetrics(nIndex); 159 } 160 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 161 { 162 ERR("Got exception in hooked GetSystemMetrics!\n"); 163 } 164 _SEH2_END; 165 166 EndUserApiHook(); 167 168 return Ret; 169 } 170 171 /* 172 * @unimplemented 173 */ 174 BOOL WINAPI SetDeskWallpaper(LPCSTR filename) 175 { 176 return SystemParametersInfoA(SPI_SETDESKWALLPAPER,0,(PVOID)filename,TRUE); 177 } 178 179 BOOL WINAPI 180 RealSystemParametersInfoA(UINT uiAction, 181 UINT uiParam, 182 PVOID pvParam, 183 UINT fWinIni) 184 { 185 switch (uiAction) 186 { 187 188 case SPI_GETNONCLIENTMETRICS: 189 { 190 LPNONCLIENTMETRICSA pnclma = (LPNONCLIENTMETRICSA)pvParam; 191 NONCLIENTMETRICSW nclmw; 192 if(pnclma->cbSize != sizeof(NONCLIENTMETRICSA)) 193 { 194 SetLastError(ERROR_INVALID_PARAMETER); 195 return FALSE; 196 } 197 nclmw.cbSize = sizeof(NONCLIENTMETRICSW); 198 199 if (!SystemParametersInfoW(uiAction, sizeof(NONCLIENTMETRICSW), 200 &nclmw, fWinIni)) 201 return FALSE; 202 203 pnclma->iBorderWidth = nclmw.iBorderWidth; 204 pnclma->iScrollWidth = nclmw.iScrollWidth; 205 pnclma->iScrollHeight = nclmw.iScrollHeight; 206 pnclma->iCaptionWidth = nclmw.iCaptionWidth; 207 pnclma->iCaptionHeight = nclmw.iCaptionHeight; 208 pnclma->iSmCaptionWidth = nclmw.iSmCaptionWidth; 209 pnclma->iSmCaptionHeight = nclmw.iSmCaptionHeight; 210 pnclma->iMenuWidth = nclmw.iMenuWidth; 211 pnclma->iMenuHeight = nclmw.iMenuHeight; 212 LogFontW2A(&(pnclma->lfCaptionFont), &(nclmw.lfCaptionFont)); 213 LogFontW2A(&(pnclma->lfSmCaptionFont), &(nclmw.lfSmCaptionFont)); 214 LogFontW2A(&(pnclma->lfMenuFont), &(nclmw.lfMenuFont)); 215 LogFontW2A(&(pnclma->lfStatusFont), &(nclmw.lfStatusFont)); 216 LogFontW2A(&(pnclma->lfMessageFont), &(nclmw.lfMessageFont)); 217 return TRUE; 218 } 219 case SPI_SETNONCLIENTMETRICS: 220 { 221 LPNONCLIENTMETRICSA pnclma = (LPNONCLIENTMETRICSA)pvParam; 222 NONCLIENTMETRICSW nclmw; 223 if(pnclma->cbSize != sizeof(NONCLIENTMETRICSA)) 224 { 225 SetLastError(ERROR_INVALID_PARAMETER); 226 return FALSE; 227 } 228 nclmw.cbSize = sizeof(NONCLIENTMETRICSW); 229 nclmw.iBorderWidth = pnclma->iBorderWidth; 230 nclmw.iScrollWidth = pnclma->iScrollWidth; 231 nclmw.iScrollHeight = pnclma->iScrollHeight; 232 nclmw.iCaptionWidth = pnclma->iCaptionWidth; 233 nclmw.iCaptionHeight = pnclma->iCaptionHeight; 234 nclmw.iSmCaptionWidth = pnclma->iSmCaptionWidth; 235 nclmw.iSmCaptionHeight = pnclma->iSmCaptionHeight; 236 nclmw.iMenuWidth = pnclma->iMenuWidth; 237 nclmw.iMenuHeight = pnclma->iMenuHeight; 238 LogFontA2W(&(nclmw.lfCaptionFont), &(pnclma->lfCaptionFont)); 239 LogFontA2W(&(nclmw.lfSmCaptionFont), &(pnclma->lfSmCaptionFont)); 240 LogFontA2W(&(nclmw.lfMenuFont), &(pnclma->lfMenuFont)); 241 LogFontA2W(&(nclmw.lfStatusFont), &(pnclma->lfStatusFont)); 242 LogFontA2W(&(nclmw.lfMessageFont), &(pnclma->lfMessageFont)); 243 244 return SystemParametersInfoW(uiAction, sizeof(NONCLIENTMETRICSW), 245 &nclmw, fWinIni); 246 } 247 case SPI_GETICONMETRICS: 248 { 249 LPICONMETRICSA picma = (LPICONMETRICSA)pvParam; 250 ICONMETRICSW icmw; 251 if(picma->cbSize != sizeof(ICONMETRICSA)) 252 { 253 SetLastError(ERROR_INVALID_PARAMETER); 254 return FALSE; 255 } 256 icmw.cbSize = sizeof(ICONMETRICSW); 257 if (!SystemParametersInfoW(uiAction, sizeof(ICONMETRICSW), 258 &icmw, fWinIni)) 259 return FALSE; 260 261 picma->iHorzSpacing = icmw.iHorzSpacing; 262 picma->iVertSpacing = icmw.iVertSpacing; 263 picma->iTitleWrap = icmw.iTitleWrap; 264 LogFontW2A(&(picma->lfFont), &(icmw.lfFont)); 265 return TRUE; 266 } 267 case SPI_SETICONMETRICS: 268 { 269 LPICONMETRICSA picma = (LPICONMETRICSA)pvParam; 270 ICONMETRICSW icmw; 271 if(picma->cbSize != sizeof(ICONMETRICSA)) 272 { 273 SetLastError(ERROR_INVALID_PARAMETER); 274 return FALSE; 275 } 276 icmw.cbSize = sizeof(ICONMETRICSW); 277 icmw.iHorzSpacing = picma->iHorzSpacing; 278 icmw.iVertSpacing = picma->iVertSpacing; 279 icmw.iTitleWrap = picma->iTitleWrap; 280 LogFontA2W(&(icmw.lfFont), &(picma->lfFont)); 281 282 return SystemParametersInfoW(uiAction, sizeof(ICONMETRICSW), 283 &icmw, fWinIni); 284 } 285 case SPI_GETICONTITLELOGFONT: 286 { 287 LOGFONTW lfw; 288 if (!SystemParametersInfoW(uiAction, 0, &lfw, fWinIni)) 289 return FALSE; 290 LogFontW2A(pvParam, &lfw); 291 return TRUE; 292 } 293 case SPI_SETICONTITLELOGFONT: 294 { 295 LPLOGFONTA plfa = (LPLOGFONTA)pvParam; 296 LOGFONTW lfw; 297 LogFontA2W(&lfw,plfa); 298 return SystemParametersInfoW(uiAction, 0, &lfw, fWinIni); 299 } 300 case SPI_GETDESKWALLPAPER: 301 { 302 BOOL Ret; 303 WCHAR awc[MAX_PATH]; 304 UNICODE_STRING ustrWallpaper; 305 ANSI_STRING astrWallpaper; 306 307 Ret = NtUserSystemParametersInfo(SPI_GETDESKWALLPAPER, MAX_PATH, awc, fWinIni); 308 RtlInitUnicodeString(&ustrWallpaper, awc); 309 RtlInitEmptyAnsiString(&astrWallpaper, pvParam, uiParam); 310 RtlUnicodeStringToAnsiString(&astrWallpaper, &ustrWallpaper, FALSE); 311 return Ret; 312 } 313 314 case SPI_SETDESKWALLPAPER: 315 { 316 UNICODE_STRING ustrWallpaper; 317 BOOL Ret; 318 319 if (pvParam) 320 { 321 if (!RtlCreateUnicodeStringFromAsciiz(&ustrWallpaper, pvParam)) 322 { 323 ERR("RtlCreateUnicodeStringFromAsciiz failed\n"); 324 return FALSE; 325 } 326 pvParam = &ustrWallpaper; 327 } 328 329 Ret = NtUserSystemParametersInfo(SPI_SETDESKWALLPAPER, uiParam, pvParam, fWinIni); 330 331 if (pvParam) 332 RtlFreeUnicodeString(&ustrWallpaper); 333 334 return Ret; 335 } 336 } 337 return NtUserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); 338 } 339 340 BOOL WINAPI 341 RealSystemParametersInfoW(UINT uiAction, 342 UINT uiParam, 343 PVOID pvParam, 344 UINT fWinIni) 345 { 346 switch(uiAction) 347 { 348 349 case SPI_SETDESKWALLPAPER: 350 { 351 UNICODE_STRING ustrWallpaper; 352 353 RtlInitUnicodeString(&ustrWallpaper, pvParam); 354 return NtUserSystemParametersInfo(SPI_SETDESKWALLPAPER, uiParam, &ustrWallpaper, fWinIni); 355 } 356 } 357 return NtUserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); 358 } 359 360 361 /* 362 * @implemented 363 */ 364 BOOL WINAPI 365 SystemParametersInfoA(UINT uiAction, 366 UINT uiParam, 367 PVOID pvParam, 368 UINT fWinIni) 369 { 370 BOOL Hook, Ret = FALSE; 371 372 LoadUserApiHook(); 373 374 Hook = BeginIfHookedUserApiHook(); 375 376 /* Bypass SEH and go direct. */ 377 if (!Hook) return RealSystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni); 378 379 _SEH2_TRY 380 { 381 Ret = guah.SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni); 382 } 383 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 384 { 385 ERR("Got exception in hooked SystemParametersInfoA!\n"); 386 } 387 _SEH2_END; 388 389 EndUserApiHook(); 390 391 return Ret; 392 } 393 394 /* 395 * @implemented 396 */ 397 BOOL WINAPI 398 SystemParametersInfoW(UINT uiAction, 399 UINT uiParam, 400 PVOID pvParam, 401 UINT fWinIni) 402 { 403 BOOL Hook, Ret = FALSE; 404 405 LoadUserApiHook(); 406 407 Hook = BeginIfHookedUserApiHook(); 408 409 /* Bypass SEH and go direct. */ 410 if (!Hook) return RealSystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni); 411 412 _SEH2_TRY 413 { 414 Ret = guah.SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni); 415 } 416 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 417 { 418 ERR("Got exception in hooked SystemParametersInfoW!\n"); 419 } 420 _SEH2_END; 421 422 EndUserApiHook(); 423 424 return Ret; 425 } 426 427 /* 428 * @implemented 429 */ 430 HDESK WINAPI 431 CreateDesktopA(LPCSTR lpszDesktop, 432 LPCSTR lpszDevice, 433 LPDEVMODEA pDevmode, 434 DWORD dwFlags, 435 ACCESS_MASK dwDesiredAccess, 436 LPSECURITY_ATTRIBUTES lpsa) 437 { 438 UNICODE_STRING DesktopNameU; 439 HDESK hDesktop; 440 LPDEVMODEW DevmodeW = NULL; 441 442 if (lpszDesktop) 443 { 444 /* After conversion, the buffer is zero-terminated */ 445 RtlCreateUnicodeStringFromAsciiz(&DesktopNameU, lpszDesktop); 446 } 447 else 448 { 449 RtlInitUnicodeString(&DesktopNameU, NULL); 450 } 451 452 if (pDevmode) 453 DevmodeW = GdiConvertToDevmodeW(pDevmode); 454 455 hDesktop = CreateDesktopW(DesktopNameU.Buffer, 456 NULL, 457 DevmodeW, 458 dwFlags, 459 dwDesiredAccess, 460 lpsa); 461 462 /* Free the string, if it was allocated */ 463 if (lpszDesktop) RtlFreeUnicodeString(&DesktopNameU); 464 465 return hDesktop; 466 } 467 468 469 /* 470 * @implemented 471 */ 472 HDESK WINAPI 473 CreateDesktopW(LPCWSTR lpszDesktop, 474 LPCWSTR lpszDevice, 475 LPDEVMODEW pDevmode, 476 DWORD dwFlags, 477 ACCESS_MASK dwDesiredAccess, 478 LPSECURITY_ATTRIBUTES lpsa) 479 { 480 OBJECT_ATTRIBUTES oas; 481 UNICODE_STRING DesktopName, DesktopDevice; 482 HWINSTA hWinSta; 483 HDESK hDesktop; 484 ULONG Attributes = (OBJ_OPENIF|OBJ_CASE_INSENSITIVE); 485 486 /* Retrive WinStation handle. */ 487 hWinSta = NtUserGetProcessWindowStation(); 488 489 /* Initialize the strings. */ 490 RtlInitUnicodeString(&DesktopName, lpszDesktop); 491 RtlInitUnicodeString(&DesktopDevice, lpszDevice); 492 493 /* Check for process is inherited, set flag if set. */ 494 if (lpsa && lpsa->bInheritHandle) Attributes |= OBJ_INHERIT; 495 496 /* Initialize the attributes for the desktop. */ 497 InitializeObjectAttributes( &oas, 498 &DesktopName, 499 Attributes, 500 hWinSta, 501 lpsa ? lpsa->lpSecurityDescriptor : NULL); 502 503 /* Send the request and call to win32k. */ 504 hDesktop = NtUserCreateDesktop( &oas, 505 &DesktopDevice, 506 pDevmode, 507 dwFlags, 508 dwDesiredAccess); 509 510 return(hDesktop); 511 } 512 513 514 /* 515 * @implemented 516 */ 517 BOOL 518 WINAPI 519 EnumDesktopsA( 520 HWINSTA WindowStation, 521 DESKTOPENUMPROCA EnumFunc, 522 LPARAM Context) 523 { 524 return EnumNamesA(WindowStation, EnumFunc, Context, TRUE); 525 } 526 527 528 /* 529 * @implemented 530 */ 531 BOOL 532 WINAPI 533 EnumDesktopsW( 534 HWINSTA WindowStation, 535 DESKTOPENUMPROCW EnumFunc, 536 LPARAM Context) 537 { 538 return EnumNamesW(WindowStation, EnumFunc, Context, TRUE); 539 } 540 541 542 /* 543 * @implemented 544 */ 545 HDESK 546 WINAPI 547 GetThreadDesktop( 548 DWORD dwThreadId) 549 { 550 USER_API_MESSAGE ApiMessage; 551 PUSER_GET_THREAD_CONSOLE_DESKTOP GetThreadConsoleDesktopRequest = &ApiMessage.Data.GetThreadConsoleDesktopRequest; 552 553 GetThreadConsoleDesktopRequest->ThreadId = dwThreadId; 554 555 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, 556 NULL, 557 CSR_CREATE_API_NUMBER(USERSRV_SERVERDLL_INDEX, UserpGetThreadConsoleDesktop), 558 sizeof(*GetThreadConsoleDesktopRequest)); 559 if (!NT_SUCCESS(ApiMessage.Status)) 560 { 561 UserSetLastNTError(ApiMessage.Status); 562 return NULL; 563 } 564 565 return NtUserGetThreadDesktop(dwThreadId, 566 (DWORD_PTR)GetThreadConsoleDesktopRequest->ConsoleDesktop); 567 } 568 569 570 /* 571 * @implemented 572 */ 573 HDESK 574 WINAPI 575 OpenDesktopA( 576 LPCSTR lpszDesktop, 577 DWORD dwFlags, 578 BOOL fInherit, 579 ACCESS_MASK dwDesiredAccess) 580 { 581 UNICODE_STRING DesktopNameU; 582 HDESK hDesktop; 583 584 if (lpszDesktop) 585 { 586 /* After conversion, the buffer is zero-terminated */ 587 RtlCreateUnicodeStringFromAsciiz(&DesktopNameU, lpszDesktop); 588 } 589 else 590 { 591 RtlInitUnicodeString(&DesktopNameU, NULL); 592 } 593 594 hDesktop = OpenDesktopW(DesktopNameU.Buffer, 595 dwFlags, 596 fInherit, 597 dwDesiredAccess); 598 599 /* Free the string, if it was allocated */ 600 if (lpszDesktop) RtlFreeUnicodeString(&DesktopNameU); 601 602 return hDesktop; 603 } 604 605 606 /* 607 * @implemented 608 */ 609 HDESK 610 WINAPI 611 OpenDesktopW( 612 LPCWSTR lpszDesktop, 613 DWORD dwFlags, 614 BOOL fInherit, 615 ACCESS_MASK dwDesiredAccess) 616 { 617 UNICODE_STRING DesktopName; 618 OBJECT_ATTRIBUTES ObjectAttributes; 619 620 RtlInitUnicodeString(&DesktopName, lpszDesktop); 621 622 InitializeObjectAttributes(&ObjectAttributes, 623 &DesktopName, 624 OBJ_CASE_INSENSITIVE, 625 GetProcessWindowStation(), 626 0); 627 628 if( fInherit ) 629 { 630 ObjectAttributes.Attributes |= OBJ_INHERIT; 631 } 632 633 return NtUserOpenDesktop(&ObjectAttributes, dwFlags, dwDesiredAccess); 634 } 635 636 637 /* 638 * @implemented 639 */ 640 BOOL WINAPI 641 SetShellWindow(HWND hwndShell) 642 { 643 return SetShellWindowEx(hwndShell, hwndShell); 644 } 645 646 647 /* 648 * @implemented 649 */ 650 HWND WINAPI 651 GetShellWindow(VOID) 652 { 653 PDESKTOPINFO pdi; 654 pdi = GetThreadDesktopInfo(); 655 if (pdi) return pdi->hShellWindow; 656 return NULL; 657 } 658 659 660 /* EOF */ 661