Merge the following revisions from kernel-fun branch:
[reactos.git] / reactos / win32ss / user / user32 / misc / desktop.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS user32.dll
4 * FILE: lib/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 RtlUnicodeStringToAnsiString(&astrWallpaper, &ustrWallpaper, TRUE);
310
311 RtlCopyMemory(pvParam, astrWallpaper.Buffer, uiParam);
312 RtlFreeAnsiString(&astrWallpaper);
313 return Ret;
314 }
315
316 case SPI_SETDESKWALLPAPER:
317 {
318 UNICODE_STRING ustrWallpaper;
319 BOOL Ret;
320
321 if (pvParam)
322 {
323 if (!RtlCreateUnicodeStringFromAsciiz(&ustrWallpaper, pvParam))
324 {
325 ERR("RtlCreateUnicodeStringFromAsciiz failed\n");
326 return FALSE;
327 }
328 pvParam = &ustrWallpaper;
329 }
330
331 Ret = NtUserSystemParametersInfo(SPI_SETDESKWALLPAPER, uiParam, pvParam, fWinIni);
332
333 if (pvParam)
334 RtlFreeUnicodeString(&ustrWallpaper);
335
336 return Ret;
337 }
338 }
339 return NtUserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
340 }
341
342 BOOL WINAPI
343 RealSystemParametersInfoW(UINT uiAction,
344 UINT uiParam,
345 PVOID pvParam,
346 UINT fWinIni)
347 {
348 switch(uiAction)
349 {
350
351 case SPI_SETDESKWALLPAPER:
352 {
353 UNICODE_STRING ustrWallpaper;
354
355 RtlInitUnicodeString(&ustrWallpaper, pvParam);
356 return NtUserSystemParametersInfo(SPI_SETDESKWALLPAPER, uiParam, &ustrWallpaper, fWinIni);
357 }
358 }
359 return NtUserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
360 }
361
362
363 /*
364 * @implemented
365 */
366 BOOL WINAPI
367 SystemParametersInfoA(UINT uiAction,
368 UINT uiParam,
369 PVOID pvParam,
370 UINT fWinIni)
371 {
372 BOOL Hook, Ret = FALSE;
373
374 LoadUserApiHook();
375
376 Hook = BeginIfHookedUserApiHook();
377
378 /* Bypass SEH and go direct. */
379 if (!Hook) return RealSystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
380
381 _SEH2_TRY
382 {
383 Ret = guah.SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
384 }
385 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
386 {
387 }
388 _SEH2_END;
389
390 EndUserApiHook();
391
392 return Ret;
393 }
394
395 /*
396 * @implemented
397 */
398 BOOL WINAPI
399 SystemParametersInfoW(UINT uiAction,
400 UINT uiParam,
401 PVOID pvParam,
402 UINT fWinIni)
403 {
404 BOOL Hook, Ret = FALSE;
405
406 LoadUserApiHook();
407
408 Hook = BeginIfHookedUserApiHook();
409
410 /* Bypass SEH and go direct. */
411 if (!Hook) return RealSystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni);
412
413 _SEH2_TRY
414 {
415 Ret = guah.SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni);
416 }
417 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
418 {
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)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 */