mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 14:30:57 +00:00
458a26ab76
- 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>
660 lines
16 KiB
C
660 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 */
|