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