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 #include <wine/debug.h> 14 WINE_DEFAULT_DEBUG_CHANNEL(user32); 15 16 /********************************************************************* 17 * desktop class descriptor 18 */ 19 #if 0 // Kept for referencing. 20 const struct builtin_class_descr DESKTOP_builtin_class = 21 { 22 WC_DESKTOP, /* name */ 23 CS_DBLCLKS, /* style */ 24 NULL, /* procA (winproc is Unicode only) */ 25 DesktopWndProc, /* procW */ 26 0, /* extra */ 27 IDC_ARROW, /* cursor */ 28 (HBRUSH)(COLOR_BACKGROUND+1) /* brush */ 29 }; 30 #endif 31 32 LRESULT 33 WINAPI 34 DesktopWndProcW(HWND Wnd, 35 UINT Msg, 36 WPARAM wParam, 37 LPARAM lParam) 38 { 39 TRACE("Desktop W Class Atom! hWnd 0x%x, Msg %d\n", Wnd, Msg); 40 41 switch(Msg) 42 { 43 case WM_ERASEBKGND: 44 case WM_NCCREATE: 45 case WM_CREATE: 46 case WM_CLOSE: 47 case WM_DISPLAYCHANGE: 48 case WM_PAINT: 49 case WM_SYSCOLORCHANGE: 50 { 51 LRESULT lResult; 52 NtUserMessageCall( Wnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DESKTOP, FALSE); 53 TRACE("Desktop lResult %d\n", lResult); 54 return lResult; 55 } 56 57 case WM_PALETTECHANGED: 58 if (Wnd == (HWND)wParam) break; 59 case WM_QUERYNEWPALETTE: 60 { 61 HDC hdc = GetWindowDC( Wnd ); 62 PaintDesktop(hdc); 63 ReleaseDC( Wnd, hdc ); 64 break; 65 } 66 67 case WM_SETCURSOR: 68 return (LRESULT)SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW)); 69 70 default: 71 return DefWindowProcW(Wnd, Msg, wParam, lParam); 72 } 73 return 0; 74 } 75 76 VOID 77 WINAPI 78 LogFontA2W(LPLOGFONTW pW, CONST LOGFONTA *pA) 79 { 80 #define COPYS(f,len) MultiByteToWideChar ( CP_THREAD_ACP, 0, pA->f, len, pW->f, len ) 81 #define COPYN(f) pW->f = pA->f 82 83 COPYN(lfHeight); 84 COPYN(lfWidth); 85 COPYN(lfEscapement); 86 COPYN(lfOrientation); 87 COPYN(lfWeight); 88 COPYN(lfItalic); 89 COPYN(lfUnderline); 90 COPYN(lfStrikeOut); 91 COPYN(lfCharSet); 92 COPYN(lfOutPrecision); 93 COPYN(lfClipPrecision); 94 COPYN(lfQuality); 95 COPYN(lfPitchAndFamily); 96 COPYS(lfFaceName,LF_FACESIZE); 97 98 #undef COPYN 99 #undef COPYS 100 } 101 102 VOID 103 WINAPI 104 LogFontW2A(LPLOGFONTA pA, CONST LOGFONTW *pW) 105 { 106 #define COPYS(f,len) WideCharToMultiByte ( CP_THREAD_ACP, 0, pW->f, len, pA->f, len, NULL, NULL ) 107 #define COPYN(f) pA->f = pW->f 108 109 COPYN(lfHeight); 110 COPYN(lfWidth); 111 COPYN(lfEscapement); 112 COPYN(lfOrientation); 113 COPYN(lfWeight); 114 COPYN(lfItalic); 115 COPYN(lfUnderline); 116 COPYN(lfStrikeOut); 117 COPYN(lfCharSet); 118 COPYN(lfOutPrecision); 119 COPYN(lfClipPrecision); 120 COPYN(lfQuality); 121 COPYN(lfPitchAndFamily); 122 COPYS(lfFaceName,LF_FACESIZE); 123 124 #undef COPYN 125 #undef COPYS 126 } 127 128 int WINAPI 129 RealGetSystemMetrics(int nIndex) 130 { 131 //FIXME("Global Server Data -> %x\n",gpsi); 132 if (nIndex < 0 || nIndex >= SM_CMETRICS) return 0; 133 return gpsi->aiSysMet[nIndex]; 134 } 135 136 /* 137 * @implemented 138 */ 139 int WINAPI 140 GetSystemMetrics(int nIndex) 141 { 142 BOOL Hook; 143 int Ret = 0; 144 145 if (!gpsi) // Fixme! Hax! Need Timos delay load support? 146 { 147 return RealGetSystemMetrics(nIndex); 148 } 149 150 LoadUserApiHook(); 151 152 Hook = BeginIfHookedUserApiHook(); 153 154 /* Bypass SEH and go direct. */ 155 if (!Hook) return RealGetSystemMetrics(nIndex); 156 157 _SEH2_TRY 158 { 159 Ret = guah.GetSystemMetrics(nIndex); 160 } 161 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 162 { 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 } 386 _SEH2_END; 387 388 EndUserApiHook(); 389 390 return Ret; 391 } 392 393 /* 394 * @implemented 395 */ 396 BOOL WINAPI 397 SystemParametersInfoW(UINT uiAction, 398 UINT uiParam, 399 PVOID pvParam, 400 UINT fWinIni) 401 { 402 BOOL Hook, Ret = FALSE; 403 404 LoadUserApiHook(); 405 406 Hook = BeginIfHookedUserApiHook(); 407 408 /* Bypass SEH and go direct. */ 409 if (!Hook) return RealSystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni); 410 411 _SEH2_TRY 412 { 413 Ret = guah.SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni); 414 } 415 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 416 { 417 } 418 _SEH2_END; 419 420 EndUserApiHook(); 421 422 return Ret; 423 } 424 425 /* 426 * @implemented 427 */ 428 HDESK WINAPI 429 CreateDesktopA(LPCSTR lpszDesktop, 430 LPCSTR lpszDevice, 431 LPDEVMODEA pDevmode, 432 DWORD dwFlags, 433 ACCESS_MASK dwDesiredAccess, 434 LPSECURITY_ATTRIBUTES lpsa) 435 { 436 UNICODE_STRING DesktopNameU; 437 HDESK hDesktop; 438 LPDEVMODEW DevmodeW = NULL; 439 440 if (lpszDesktop) 441 { 442 /* After conversion, the buffer is zero-terminated */ 443 RtlCreateUnicodeStringFromAsciiz(&DesktopNameU, lpszDesktop); 444 } 445 else 446 { 447 RtlInitUnicodeString(&DesktopNameU, NULL); 448 } 449 450 if (pDevmode) 451 DevmodeW = GdiConvertToDevmodeW(pDevmode); 452 453 hDesktop = CreateDesktopW(DesktopNameU.Buffer, 454 NULL, 455 DevmodeW, 456 dwFlags, 457 dwDesiredAccess, 458 lpsa); 459 460 /* Free the string, if it was allocated */ 461 if (lpszDesktop) RtlFreeUnicodeString(&DesktopNameU); 462 463 return hDesktop; 464 } 465 466 467 /* 468 * @implemented 469 */ 470 HDESK WINAPI 471 CreateDesktopW(LPCWSTR lpszDesktop, 472 LPCWSTR lpszDevice, 473 LPDEVMODEW pDevmode, 474 DWORD dwFlags, 475 ACCESS_MASK dwDesiredAccess, 476 LPSECURITY_ATTRIBUTES lpsa) 477 { 478 OBJECT_ATTRIBUTES oas; 479 UNICODE_STRING DesktopName, DesktopDevice; 480 HWINSTA hWinSta; 481 HDESK hDesktop; 482 ULONG Attributes = (OBJ_OPENIF|OBJ_CASE_INSENSITIVE); 483 484 /* Retrive WinStation handle. */ 485 hWinSta = NtUserGetProcessWindowStation(); 486 487 /* Initialize the strings. */ 488 RtlInitUnicodeString(&DesktopName, lpszDesktop); 489 RtlInitUnicodeString(&DesktopDevice, lpszDevice); 490 491 /* Check for process is inherited, set flag if set. */ 492 if (lpsa && lpsa->bInheritHandle) Attributes |= OBJ_INHERIT; 493 494 /* Initialize the attributes for the desktop. */ 495 InitializeObjectAttributes( &oas, 496 &DesktopName, 497 Attributes, 498 hWinSta, 499 lpsa ? lpsa->lpSecurityDescriptor : NULL); 500 501 /* Send the request and call to win32k. */ 502 hDesktop = NtUserCreateDesktop( &oas, 503 &DesktopDevice, 504 pDevmode, 505 dwFlags, 506 dwDesiredAccess); 507 508 return(hDesktop); 509 } 510 511 512 /* 513 * @implemented 514 */ 515 BOOL 516 WINAPI 517 EnumDesktopsA( 518 HWINSTA WindowStation, 519 DESKTOPENUMPROCA EnumFunc, 520 LPARAM Context) 521 { 522 return EnumNamesA(WindowStation, EnumFunc, Context, TRUE); 523 } 524 525 526 /* 527 * @implemented 528 */ 529 BOOL 530 WINAPI 531 EnumDesktopsW( 532 HWINSTA WindowStation, 533 DESKTOPENUMPROCW EnumFunc, 534 LPARAM Context) 535 { 536 return EnumNamesW(WindowStation, EnumFunc, Context, TRUE); 537 } 538 539 540 /* 541 * @implemented 542 */ 543 HDESK 544 WINAPI 545 GetThreadDesktop( 546 DWORD dwThreadId) 547 { 548 USER_API_MESSAGE ApiMessage; 549 PUSER_GET_THREAD_CONSOLE_DESKTOP GetThreadConsoleDesktopRequest = &ApiMessage.Data.GetThreadConsoleDesktopRequest; 550 551 GetThreadConsoleDesktopRequest->ThreadId = dwThreadId; 552 553 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, 554 NULL, 555 CSR_CREATE_API_NUMBER(USERSRV_SERVERDLL_INDEX, UserpGetThreadConsoleDesktop), 556 sizeof(*GetThreadConsoleDesktopRequest)); 557 if (!NT_SUCCESS(ApiMessage.Status)) 558 { 559 UserSetLastNTError(ApiMessage.Status); 560 return NULL; 561 } 562 563 return NtUserGetThreadDesktop(dwThreadId, 564 (DWORD)GetThreadConsoleDesktopRequest->ConsoleDesktop); 565 } 566 567 568 /* 569 * @implemented 570 */ 571 HDESK 572 WINAPI 573 OpenDesktopA( 574 LPCSTR lpszDesktop, 575 DWORD dwFlags, 576 BOOL fInherit, 577 ACCESS_MASK dwDesiredAccess) 578 { 579 UNICODE_STRING DesktopNameU; 580 HDESK hDesktop; 581 582 if (lpszDesktop) 583 { 584 /* After conversion, the buffer is zero-terminated */ 585 RtlCreateUnicodeStringFromAsciiz(&DesktopNameU, lpszDesktop); 586 } 587 else 588 { 589 RtlInitUnicodeString(&DesktopNameU, NULL); 590 } 591 592 hDesktop = OpenDesktopW(DesktopNameU.Buffer, 593 dwFlags, 594 fInherit, 595 dwDesiredAccess); 596 597 /* Free the string, if it was allocated */ 598 if (lpszDesktop) RtlFreeUnicodeString(&DesktopNameU); 599 600 return hDesktop; 601 } 602 603 604 /* 605 * @implemented 606 */ 607 HDESK 608 WINAPI 609 OpenDesktopW( 610 LPCWSTR lpszDesktop, 611 DWORD dwFlags, 612 BOOL fInherit, 613 ACCESS_MASK dwDesiredAccess) 614 { 615 UNICODE_STRING DesktopName; 616 OBJECT_ATTRIBUTES ObjectAttributes; 617 618 RtlInitUnicodeString(&DesktopName, lpszDesktop); 619 620 InitializeObjectAttributes(&ObjectAttributes, 621 &DesktopName, 622 OBJ_CASE_INSENSITIVE, 623 GetProcessWindowStation(), 624 0); 625 626 if( fInherit ) 627 { 628 ObjectAttributes.Attributes |= OBJ_INHERIT; 629 } 630 631 return NtUserOpenDesktop(&ObjectAttributes, dwFlags, dwDesiredAccess); 632 } 633 634 635 /* 636 * @implemented 637 */ 638 BOOL WINAPI 639 SetShellWindow(HWND hwndShell) 640 { 641 return SetShellWindowEx(hwndShell, hwndShell); 642 } 643 644 645 /* 646 * @implemented 647 */ 648 HWND WINAPI 649 GetShellWindow(VOID) 650 { 651 PDESKTOPINFO pdi; 652 pdi = GetThreadDesktopInfo(); 653 if (pdi) return pdi->hShellWindow; 654 return NULL; 655 } 656 657 658 /* EOF */ 659