reactos/win32ss/user/user32/misc/desktop.c
Andrew Boyarshin 458a26ab76
[WIN32SS:NTUSER] Use the 2nd parameter of NtUserGetThreadDesktop() as fallback. (#1065)
- The 2nd parameter is already passed in user-mode by GetThreadDesktop().
  It is then used by NtUserGetThreadDesktop() as a fallback for console
  threads.

- Lookup and validate the thread by using the IntTID2PTI() helper.
- Don't reference the desktop with too many access rights.
- Get rid of the old-school DECLARE_RETURN() & co. macros.

Co-authored-by: Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
2019-04-28 19:27:45 +02:00

661 lines
16 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS user32.dll
* FILE: win32ss/user/user32/misc/desktop.c
* PURPOSE: Desktops
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* 06-06-2001 CSH Created
*/
#include <user32.h>
WINE_DEFAULT_DEBUG_CHANNEL(user32);
/*********************************************************************
* desktop class descriptor
*/
#if 0 // Kept for referencing.
const struct builtin_class_descr DESKTOP_builtin_class =
{
WC_DESKTOP, /* name */
CS_DBLCLKS, /* style */
NULL, /* procA (winproc is Unicode only) */
DesktopWndProc, /* procW */
0, /* extra */
IDC_ARROW, /* cursor */
(HBRUSH)(COLOR_BACKGROUND+1) /* brush */
};
#endif
LRESULT
WINAPI
DesktopWndProcW(HWND Wnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
TRACE("Desktop W Class Atom! hWnd 0x%x, Msg %d\n", Wnd, Msg);
switch(Msg)
{
case WM_ERASEBKGND:
case WM_NCCREATE:
case WM_CREATE:
case WM_CLOSE:
case WM_DISPLAYCHANGE:
case WM_PAINT:
case WM_SYSCOLORCHANGE:
{
LRESULT lResult;
NtUserMessageCall( Wnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DESKTOP, FALSE);
TRACE("Desktop lResult %d\n", lResult);
return lResult;
}
case WM_PALETTECHANGED:
if (Wnd == (HWND)wParam) break;
case WM_QUERYNEWPALETTE:
{
HDC hdc = GetWindowDC( Wnd );
PaintDesktop(hdc);
ReleaseDC( Wnd, hdc );
break;
}
case WM_SETCURSOR:
return (LRESULT)SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW));
default:
return DefWindowProcW(Wnd, Msg, wParam, lParam);
}
return 0;
}
VOID
WINAPI
LogFontA2W(LPLOGFONTW pW, CONST LOGFONTA *pA)
{
#define COPYS(f,len) MultiByteToWideChar ( CP_THREAD_ACP, 0, pA->f, len, pW->f, len )
#define COPYN(f) pW->f = pA->f
COPYN(lfHeight);
COPYN(lfWidth);
COPYN(lfEscapement);
COPYN(lfOrientation);
COPYN(lfWeight);
COPYN(lfItalic);
COPYN(lfUnderline);
COPYN(lfStrikeOut);
COPYN(lfCharSet);
COPYN(lfOutPrecision);
COPYN(lfClipPrecision);
COPYN(lfQuality);
COPYN(lfPitchAndFamily);
COPYS(lfFaceName,LF_FACESIZE);
#undef COPYN
#undef COPYS
}
VOID
WINAPI
LogFontW2A(LPLOGFONTA pA, CONST LOGFONTW *pW)
{
#define COPYS(f,len) WideCharToMultiByte ( CP_THREAD_ACP, 0, pW->f, len, pA->f, len, NULL, NULL )
#define COPYN(f) pA->f = pW->f
COPYN(lfHeight);
COPYN(lfWidth);
COPYN(lfEscapement);
COPYN(lfOrientation);
COPYN(lfWeight);
COPYN(lfItalic);
COPYN(lfUnderline);
COPYN(lfStrikeOut);
COPYN(lfCharSet);
COPYN(lfOutPrecision);
COPYN(lfClipPrecision);
COPYN(lfQuality);
COPYN(lfPitchAndFamily);
COPYS(lfFaceName,LF_FACESIZE);
#undef COPYN
#undef COPYS
}
int WINAPI
RealGetSystemMetrics(int nIndex)
{
//FIXME("Global Server Data -> %x\n",gpsi);
if (nIndex < 0 || nIndex >= SM_CMETRICS) return 0;
return gpsi->aiSysMet[nIndex];
}
/*
* @implemented
*/
int WINAPI
GetSystemMetrics(int nIndex)
{
BOOL Hook;
int Ret = 0;
if (!gpsi) // Fixme! Hax! Need Timos delay load support?
{
return RealGetSystemMetrics(nIndex);
}
LoadUserApiHook();
Hook = BeginIfHookedUserApiHook();
/* Bypass SEH and go direct. */
if (!Hook) return RealGetSystemMetrics(nIndex);
_SEH2_TRY
{
Ret = guah.GetSystemMetrics(nIndex);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ERR("Got exception in hooked GetSystemMetrics!\n");
}
_SEH2_END;
EndUserApiHook();
return Ret;
}
/*
* @unimplemented
*/
BOOL WINAPI SetDeskWallpaper(LPCSTR filename)
{
return SystemParametersInfoA(SPI_SETDESKWALLPAPER,0,(PVOID)filename,TRUE);
}
BOOL WINAPI
RealSystemParametersInfoA(UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni)
{
switch (uiAction)
{
case SPI_GETNONCLIENTMETRICS:
{
LPNONCLIENTMETRICSA pnclma = (LPNONCLIENTMETRICSA)pvParam;
NONCLIENTMETRICSW nclmw;
if(pnclma->cbSize != sizeof(NONCLIENTMETRICSA))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
nclmw.cbSize = sizeof(NONCLIENTMETRICSW);
if (!SystemParametersInfoW(uiAction, sizeof(NONCLIENTMETRICSW),
&nclmw, fWinIni))
return FALSE;
pnclma->iBorderWidth = nclmw.iBorderWidth;
pnclma->iScrollWidth = nclmw.iScrollWidth;
pnclma->iScrollHeight = nclmw.iScrollHeight;
pnclma->iCaptionWidth = nclmw.iCaptionWidth;
pnclma->iCaptionHeight = nclmw.iCaptionHeight;
pnclma->iSmCaptionWidth = nclmw.iSmCaptionWidth;
pnclma->iSmCaptionHeight = nclmw.iSmCaptionHeight;
pnclma->iMenuWidth = nclmw.iMenuWidth;
pnclma->iMenuHeight = nclmw.iMenuHeight;
LogFontW2A(&(pnclma->lfCaptionFont), &(nclmw.lfCaptionFont));
LogFontW2A(&(pnclma->lfSmCaptionFont), &(nclmw.lfSmCaptionFont));
LogFontW2A(&(pnclma->lfMenuFont), &(nclmw.lfMenuFont));
LogFontW2A(&(pnclma->lfStatusFont), &(nclmw.lfStatusFont));
LogFontW2A(&(pnclma->lfMessageFont), &(nclmw.lfMessageFont));
return TRUE;
}
case SPI_SETNONCLIENTMETRICS:
{
LPNONCLIENTMETRICSA pnclma = (LPNONCLIENTMETRICSA)pvParam;
NONCLIENTMETRICSW nclmw;
if(pnclma->cbSize != sizeof(NONCLIENTMETRICSA))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
nclmw.cbSize = sizeof(NONCLIENTMETRICSW);
nclmw.iBorderWidth = pnclma->iBorderWidth;
nclmw.iScrollWidth = pnclma->iScrollWidth;
nclmw.iScrollHeight = pnclma->iScrollHeight;
nclmw.iCaptionWidth = pnclma->iCaptionWidth;
nclmw.iCaptionHeight = pnclma->iCaptionHeight;
nclmw.iSmCaptionWidth = pnclma->iSmCaptionWidth;
nclmw.iSmCaptionHeight = pnclma->iSmCaptionHeight;
nclmw.iMenuWidth = pnclma->iMenuWidth;
nclmw.iMenuHeight = pnclma->iMenuHeight;
LogFontA2W(&(nclmw.lfCaptionFont), &(pnclma->lfCaptionFont));
LogFontA2W(&(nclmw.lfSmCaptionFont), &(pnclma->lfSmCaptionFont));
LogFontA2W(&(nclmw.lfMenuFont), &(pnclma->lfMenuFont));
LogFontA2W(&(nclmw.lfStatusFont), &(pnclma->lfStatusFont));
LogFontA2W(&(nclmw.lfMessageFont), &(pnclma->lfMessageFont));
return SystemParametersInfoW(uiAction, sizeof(NONCLIENTMETRICSW),
&nclmw, fWinIni);
}
case SPI_GETICONMETRICS:
{
LPICONMETRICSA picma = (LPICONMETRICSA)pvParam;
ICONMETRICSW icmw;
if(picma->cbSize != sizeof(ICONMETRICSA))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
icmw.cbSize = sizeof(ICONMETRICSW);
if (!SystemParametersInfoW(uiAction, sizeof(ICONMETRICSW),
&icmw, fWinIni))
return FALSE;
picma->iHorzSpacing = icmw.iHorzSpacing;
picma->iVertSpacing = icmw.iVertSpacing;
picma->iTitleWrap = icmw.iTitleWrap;
LogFontW2A(&(picma->lfFont), &(icmw.lfFont));
return TRUE;
}
case SPI_SETICONMETRICS:
{
LPICONMETRICSA picma = (LPICONMETRICSA)pvParam;
ICONMETRICSW icmw;
if(picma->cbSize != sizeof(ICONMETRICSA))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
icmw.cbSize = sizeof(ICONMETRICSW);
icmw.iHorzSpacing = picma->iHorzSpacing;
icmw.iVertSpacing = picma->iVertSpacing;
icmw.iTitleWrap = picma->iTitleWrap;
LogFontA2W(&(icmw.lfFont), &(picma->lfFont));
return SystemParametersInfoW(uiAction, sizeof(ICONMETRICSW),
&icmw, fWinIni);
}
case SPI_GETICONTITLELOGFONT:
{
LOGFONTW lfw;
if (!SystemParametersInfoW(uiAction, 0, &lfw, fWinIni))
return FALSE;
LogFontW2A(pvParam, &lfw);
return TRUE;
}
case SPI_SETICONTITLELOGFONT:
{
LPLOGFONTA plfa = (LPLOGFONTA)pvParam;
LOGFONTW lfw;
LogFontA2W(&lfw,plfa);
return SystemParametersInfoW(uiAction, 0, &lfw, fWinIni);
}
case SPI_GETDESKWALLPAPER:
{
BOOL Ret;
WCHAR awc[MAX_PATH];
UNICODE_STRING ustrWallpaper;
ANSI_STRING astrWallpaper;
Ret = NtUserSystemParametersInfo(SPI_GETDESKWALLPAPER, MAX_PATH, awc, fWinIni);
RtlInitUnicodeString(&ustrWallpaper, awc);
RtlInitEmptyAnsiString(&astrWallpaper, pvParam, uiParam);
RtlUnicodeStringToAnsiString(&astrWallpaper, &ustrWallpaper, FALSE);
return Ret;
}
case SPI_SETDESKWALLPAPER:
{
UNICODE_STRING ustrWallpaper;
BOOL Ret;
if (pvParam)
{
if (!RtlCreateUnicodeStringFromAsciiz(&ustrWallpaper, pvParam))
{
ERR("RtlCreateUnicodeStringFromAsciiz failed\n");
return FALSE;
}
pvParam = &ustrWallpaper;
}
Ret = NtUserSystemParametersInfo(SPI_SETDESKWALLPAPER, uiParam, pvParam, fWinIni);
if (pvParam)
RtlFreeUnicodeString(&ustrWallpaper);
return Ret;
}
}
return NtUserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
}
BOOL WINAPI
RealSystemParametersInfoW(UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni)
{
switch(uiAction)
{
case SPI_SETDESKWALLPAPER:
{
UNICODE_STRING ustrWallpaper;
RtlInitUnicodeString(&ustrWallpaper, pvParam);
return NtUserSystemParametersInfo(SPI_SETDESKWALLPAPER, uiParam, &ustrWallpaper, fWinIni);
}
}
return NtUserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
}
/*
* @implemented
*/
BOOL WINAPI
SystemParametersInfoA(UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni)
{
BOOL Hook, Ret = FALSE;
LoadUserApiHook();
Hook = BeginIfHookedUserApiHook();
/* Bypass SEH and go direct. */
if (!Hook) return RealSystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
_SEH2_TRY
{
Ret = guah.SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ERR("Got exception in hooked SystemParametersInfoA!\n");
}
_SEH2_END;
EndUserApiHook();
return Ret;
}
/*
* @implemented
*/
BOOL WINAPI
SystemParametersInfoW(UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni)
{
BOOL Hook, Ret = FALSE;
LoadUserApiHook();
Hook = BeginIfHookedUserApiHook();
/* Bypass SEH and go direct. */
if (!Hook) return RealSystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni);
_SEH2_TRY
{
Ret = guah.SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ERR("Got exception in hooked SystemParametersInfoW!\n");
}
_SEH2_END;
EndUserApiHook();
return Ret;
}
/*
* @implemented
*/
HDESK WINAPI
CreateDesktopA(LPCSTR lpszDesktop,
LPCSTR lpszDevice,
LPDEVMODEA pDevmode,
DWORD dwFlags,
ACCESS_MASK dwDesiredAccess,
LPSECURITY_ATTRIBUTES lpsa)
{
UNICODE_STRING DesktopNameU;
HDESK hDesktop;
LPDEVMODEW DevmodeW = NULL;
if (lpszDesktop)
{
/* After conversion, the buffer is zero-terminated */
RtlCreateUnicodeStringFromAsciiz(&DesktopNameU, lpszDesktop);
}
else
{
RtlInitUnicodeString(&DesktopNameU, NULL);
}
if (pDevmode)
DevmodeW = GdiConvertToDevmodeW(pDevmode);
hDesktop = CreateDesktopW(DesktopNameU.Buffer,
NULL,
DevmodeW,
dwFlags,
dwDesiredAccess,
lpsa);
/* Free the string, if it was allocated */
if (lpszDesktop) RtlFreeUnicodeString(&DesktopNameU);
return hDesktop;
}
/*
* @implemented
*/
HDESK WINAPI
CreateDesktopW(LPCWSTR lpszDesktop,
LPCWSTR lpszDevice,
LPDEVMODEW pDevmode,
DWORD dwFlags,
ACCESS_MASK dwDesiredAccess,
LPSECURITY_ATTRIBUTES lpsa)
{
OBJECT_ATTRIBUTES oas;
UNICODE_STRING DesktopName, DesktopDevice;
HWINSTA hWinSta;
HDESK hDesktop;
ULONG Attributes = (OBJ_OPENIF|OBJ_CASE_INSENSITIVE);
/* Retrive WinStation handle. */
hWinSta = NtUserGetProcessWindowStation();
/* Initialize the strings. */
RtlInitUnicodeString(&DesktopName, lpszDesktop);
RtlInitUnicodeString(&DesktopDevice, lpszDevice);
/* Check for process is inherited, set flag if set. */
if (lpsa && lpsa->bInheritHandle) Attributes |= OBJ_INHERIT;
/* Initialize the attributes for the desktop. */
InitializeObjectAttributes( &oas,
&DesktopName,
Attributes,
hWinSta,
lpsa ? lpsa->lpSecurityDescriptor : NULL);
/* Send the request and call to win32k. */
hDesktop = NtUserCreateDesktop( &oas,
&DesktopDevice,
pDevmode,
dwFlags,
dwDesiredAccess);
return(hDesktop);
}
/*
* @implemented
*/
BOOL
WINAPI
EnumDesktopsA(
HWINSTA WindowStation,
DESKTOPENUMPROCA EnumFunc,
LPARAM Context)
{
return EnumNamesA(WindowStation, EnumFunc, Context, TRUE);
}
/*
* @implemented
*/
BOOL
WINAPI
EnumDesktopsW(
HWINSTA WindowStation,
DESKTOPENUMPROCW EnumFunc,
LPARAM Context)
{
return EnumNamesW(WindowStation, EnumFunc, Context, TRUE);
}
/*
* @implemented
*/
HDESK
WINAPI
GetThreadDesktop(
DWORD dwThreadId)
{
USER_API_MESSAGE ApiMessage;
PUSER_GET_THREAD_CONSOLE_DESKTOP GetThreadConsoleDesktopRequest = &ApiMessage.Data.GetThreadConsoleDesktopRequest;
GetThreadConsoleDesktopRequest->ThreadId = dwThreadId;
CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
NULL,
CSR_CREATE_API_NUMBER(USERSRV_SERVERDLL_INDEX, UserpGetThreadConsoleDesktop),
sizeof(*GetThreadConsoleDesktopRequest));
if (!NT_SUCCESS(ApiMessage.Status))
{
UserSetLastNTError(ApiMessage.Status);
return NULL;
}
return NtUserGetThreadDesktop(dwThreadId,
GetThreadConsoleDesktopRequest->ConsoleDesktop);
}
/*
* @implemented
*/
HDESK
WINAPI
OpenDesktopA(
LPCSTR lpszDesktop,
DWORD dwFlags,
BOOL fInherit,
ACCESS_MASK dwDesiredAccess)
{
UNICODE_STRING DesktopNameU;
HDESK hDesktop;
if (lpszDesktop)
{
/* After conversion, the buffer is zero-terminated */
RtlCreateUnicodeStringFromAsciiz(&DesktopNameU, lpszDesktop);
}
else
{
RtlInitUnicodeString(&DesktopNameU, NULL);
}
hDesktop = OpenDesktopW(DesktopNameU.Buffer,
dwFlags,
fInherit,
dwDesiredAccess);
/* Free the string, if it was allocated */
if (lpszDesktop) RtlFreeUnicodeString(&DesktopNameU);
return hDesktop;
}
/*
* @implemented
*/
HDESK
WINAPI
OpenDesktopW(
LPCWSTR lpszDesktop,
DWORD dwFlags,
BOOL fInherit,
ACCESS_MASK dwDesiredAccess)
{
UNICODE_STRING DesktopName;
OBJECT_ATTRIBUTES ObjectAttributes;
RtlInitUnicodeString(&DesktopName, lpszDesktop);
InitializeObjectAttributes(&ObjectAttributes,
&DesktopName,
OBJ_CASE_INSENSITIVE,
GetProcessWindowStation(),
0);
if( fInherit )
{
ObjectAttributes.Attributes |= OBJ_INHERIT;
}
return NtUserOpenDesktop(&ObjectAttributes, dwFlags, dwDesiredAccess);
}
/*
* @implemented
*/
BOOL WINAPI
SetShellWindow(HWND hwndShell)
{
return SetShellWindowEx(hwndShell, hwndShell);
}
/*
* @implemented
*/
HWND WINAPI
GetShellWindow(VOID)
{
PDESKTOPINFO pdi;
pdi = GetThreadDesktopInfo();
if (pdi) return pdi->hShellWindow;
return NULL;
}
/* EOF */