xref: /reactos/win32ss/user/user32/misc/desktop.c (revision cc439606)
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