mirror of
https://github.com/reactos/reactos.git
synced 2024-09-11 05:12:43 +00:00
500 lines
11 KiB
C
500 lines
11 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS user32.dll
|
|
* FILE: win32ss/user/user32/misc/misc.c
|
|
* PURPOSE: Misc
|
|
* PROGRAMMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
|
|
*/
|
|
|
|
#include <user32.h>
|
|
|
|
VOID
|
|
WINAPI
|
|
UserSetLastError(IN DWORD dwErrCode)
|
|
{
|
|
/*
|
|
* Equivalent of SetLastError in kernel32, but without breaking
|
|
* into the debugger nor checking whether the last old error is
|
|
* the same as the one we are going to set.
|
|
*/
|
|
NtCurrentTeb()->LastErrorValue = dwErrCode;
|
|
}
|
|
|
|
VOID
|
|
WINAPI
|
|
UserSetLastNTError(IN NTSTATUS Status)
|
|
{
|
|
/*
|
|
* Equivalent of BaseSetLastNTError in kernel32, but using
|
|
* UserSetLastError: convert from NT to Win32, then set.
|
|
*/
|
|
UserSetLastError(RtlNtStatusToDosError(Status));
|
|
}
|
|
|
|
|
|
PTHREADINFO
|
|
GetW32ThreadInfo(VOID)
|
|
{
|
|
PTHREADINFO ti;
|
|
|
|
ti = (PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo;
|
|
if (ti == NULL)
|
|
{
|
|
/* create the THREADINFO structure */
|
|
NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
|
|
ti = (PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo;
|
|
}
|
|
|
|
return ti;
|
|
}
|
|
|
|
|
|
/*
|
|
* GetUserObjectSecurity
|
|
*
|
|
* Retrieves security information for user object specified
|
|
* with handle 'hObject'. Descriptor returned in self-relative
|
|
* format.
|
|
*
|
|
* Arguments:
|
|
* 1) hObject - handle to an object to retrieve information for
|
|
* 2) pSecurityInfo - type of information to retrieve
|
|
* 3) pSecurityDescriptor - buffer which receives descriptor
|
|
* 4) dwLength - size, in bytes, of buffer 'pSecurityDescriptor'
|
|
* 5) pdwLengthNeeded - reseives actual size of descriptor
|
|
*
|
|
* Return Vaules:
|
|
* TRUE on success
|
|
* FALSE on failure, call GetLastError() for more information
|
|
*/
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
GetUserObjectSecurity(
|
|
IN HANDLE hObject,
|
|
IN PSECURITY_INFORMATION pSecurityInfo,
|
|
OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
IN DWORD dwLength,
|
|
OUT PDWORD pdwLengthNeeded
|
|
)
|
|
{
|
|
DWORD dwWin32Error;
|
|
NTSTATUS Status;
|
|
|
|
|
|
Status = NtQuerySecurityObject(
|
|
hObject, // Object Handle
|
|
*pSecurityInfo, // Security Information
|
|
pSecurityDescriptor,// Security Descriptor
|
|
dwLength, // Buffer Length
|
|
pdwLengthNeeded // Actual Length
|
|
);
|
|
|
|
if ( ! NT_SUCCESS( Status ) ) {
|
|
dwWin32Error = RtlNtStatusToDosError( Status );
|
|
NtCurrentTeb()->LastErrorValue = dwWin32Error;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* SetUserObjectSecurity
|
|
*
|
|
* Sets new security descriptor to user object specified by
|
|
* handle 'hObject'. Descriptor must be in self-relative format.
|
|
*
|
|
* Arguments:
|
|
* 1) hObject - handle to an object to set information for
|
|
* 2) pSecurityInfo - type of information to apply
|
|
* 3) pSecurityDescriptor - buffer which descriptor to set
|
|
*
|
|
* Return Vaules:
|
|
* TRUE on success
|
|
* FALSE on failure, call GetLastError() for more information
|
|
*/
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
SetUserObjectSecurity(
|
|
IN HANDLE hObject,
|
|
IN PSECURITY_INFORMATION pSecurityInfo,
|
|
IN PSECURITY_DESCRIPTOR pSecurityDescriptor
|
|
)
|
|
{
|
|
DWORD dwWin32Error;
|
|
NTSTATUS Status;
|
|
|
|
|
|
Status = NtSetSecurityObject(
|
|
hObject, // Object Handle
|
|
*pSecurityInfo, // Security Information
|
|
pSecurityDescriptor // Security Descriptor
|
|
);
|
|
|
|
if ( ! NT_SUCCESS( Status ) ) {
|
|
dwWin32Error = RtlNtStatusToDosError( Status );
|
|
NtCurrentTeb()->LastErrorValue = dwWin32Error;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
IsGUIThread(
|
|
BOOL bConvert)
|
|
{
|
|
PTHREADINFO ti = (PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo;
|
|
if (ti == NULL)
|
|
{
|
|
if(bConvert)
|
|
{
|
|
NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
|
|
if ((PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo) return TRUE;
|
|
else
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
return FALSE;
|
|
}
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
FASTCALL
|
|
TestWindowProcess(PWND Wnd)
|
|
{
|
|
if (Wnd->head.pti == (PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo)
|
|
return TRUE;
|
|
else
|
|
return (NtUserQueryWindow(Wnd->head.h, QUERY_WINDOW_UNIQUE_PROCESS_ID) ==
|
|
(DWORD_PTR)NtCurrentTeb()->ClientId.UniqueProcess );
|
|
}
|
|
|
|
BOOL
|
|
FASTCALL
|
|
TestState(PWND pWnd, UINT Flag)
|
|
{
|
|
UINT bit;
|
|
bit = 1 << LOWORD(Flag);
|
|
switch(HIWORD(Flag))
|
|
{
|
|
case 0:
|
|
return (pWnd->state & bit);
|
|
case 1:
|
|
return (pWnd->state2 & bit);
|
|
case 2:
|
|
return (pWnd->ExStyle2 & bit);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
PUSER_HANDLE_ENTRY
|
|
FASTCALL
|
|
GetUser32Handle(HANDLE handle)
|
|
{
|
|
INT Index;
|
|
USHORT generation;
|
|
|
|
if (!handle) return NULL;
|
|
|
|
Index = (((UINT_PTR)handle & 0xffff) - FIRST_USER_HANDLE) >> 1;
|
|
|
|
if (Index < 0 || Index >= gHandleTable->nb_handles)
|
|
return NULL;
|
|
|
|
if (!gHandleEntries[Index].type || !gHandleEntries[Index].ptr)
|
|
return NULL;
|
|
|
|
generation = (UINT_PTR)handle >> 16;
|
|
|
|
if (generation == gHandleEntries[Index].generation || !generation || generation == 0xffff)
|
|
return &gHandleEntries[Index];
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Decide whether an object is located on the desktop or shared heap
|
|
*/
|
|
static const BOOL g_ObjectHeapTypeShared[TYPE_CTYPES] =
|
|
{
|
|
FALSE, /* TYPE_FREE (not used) */
|
|
FALSE, /* TYPE_WINDOW */
|
|
FALSE, /* TYPE_MENU */
|
|
TRUE, /* TYPE_CURSOR */
|
|
TRUE, /* TYPE_SETWINDOWPOS */
|
|
FALSE, /* TYPE_HOOK */
|
|
TRUE, /* TYPE_CLIPDATA */
|
|
FALSE, /* TYPE_CALLPROC */
|
|
TRUE, /* TYPE_ACCELTABLE */
|
|
FALSE, /* TYPE_DDEACCESS */
|
|
FALSE, /* TYPE_DDECONV */
|
|
FALSE, /* TYPE_DDEXACT */
|
|
TRUE, /* TYPE_MONITOR */
|
|
TRUE, /* TYPE_KBDLAYOUT */
|
|
TRUE, /* TYPE_KBDFILE */
|
|
TRUE, /* TYPE_WINEVENTHOOK */
|
|
TRUE, /* TYPE_TIMER */
|
|
FALSE, /* TYPE_INPUTCONTEXT */
|
|
FALSE, /* TYPE_HIDDATA */
|
|
FALSE, /* TYPE_DEVICEINFO */
|
|
FALSE, /* TYPE_TOUCHINPUTINFO */
|
|
FALSE, /* TYPE_GESTUREINFOOBJ */
|
|
};
|
|
|
|
//
|
|
// Validate Handle and return the pointer to the object.
|
|
//
|
|
PVOID
|
|
FASTCALL
|
|
ValidateHandle(HANDLE handle, UINT uType)
|
|
{
|
|
PVOID ret;
|
|
PUSER_HANDLE_ENTRY pEntry;
|
|
|
|
ASSERT(uType < TYPE_CTYPES);
|
|
|
|
pEntry = GetUser32Handle(handle);
|
|
|
|
if (pEntry && uType == 0)
|
|
uType = pEntry->type;
|
|
|
|
// Must have an entry and must be the same type!
|
|
if ( (!pEntry) ||
|
|
(pEntry->type != uType) ||
|
|
!pEntry->ptr ||
|
|
(pEntry->flags & HANDLEENTRY_DESTROY) || (pEntry->flags & HANDLEENTRY_INDESTROY) )
|
|
{
|
|
switch ( uType )
|
|
{ // Test (with wine too) confirms these results!
|
|
case TYPE_WINDOW:
|
|
SetLastError(ERROR_INVALID_WINDOW_HANDLE);
|
|
break;
|
|
case TYPE_MENU:
|
|
SetLastError(ERROR_INVALID_MENU_HANDLE);
|
|
break;
|
|
case TYPE_CURSOR:
|
|
SetLastError(ERROR_INVALID_CURSOR_HANDLE);
|
|
break;
|
|
case TYPE_SETWINDOWPOS:
|
|
SetLastError(ERROR_INVALID_DWP_HANDLE);
|
|
break;
|
|
case TYPE_HOOK:
|
|
SetLastError(ERROR_INVALID_HOOK_HANDLE);
|
|
break;
|
|
case TYPE_ACCELTABLE:
|
|
SetLastError(ERROR_INVALID_ACCEL_HANDLE);
|
|
break;
|
|
default:
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
break;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
if (g_ObjectHeapTypeShared[uType])
|
|
ret = SharedPtrToUser(pEntry->ptr);
|
|
else
|
|
ret = DesktopPtrToUser(pEntry->ptr);
|
|
|
|
return ret;
|
|
}
|
|
|
|
//
|
|
// Validate Handle and return the pointer to the object.
|
|
//
|
|
PVOID
|
|
FASTCALL
|
|
ValidateHandleNoErr(HANDLE handle, UINT uType)
|
|
{
|
|
PVOID ret;
|
|
PUSER_HANDLE_ENTRY pEntry;
|
|
|
|
ASSERT(uType < TYPE_CTYPES);
|
|
|
|
pEntry = GetUser32Handle(handle);
|
|
|
|
if (pEntry && uType == 0)
|
|
uType = pEntry->type;
|
|
|
|
// Must have an entry and must be the same type!
|
|
if ( (!pEntry) || (pEntry->type != uType) || !pEntry->ptr )
|
|
return NULL;
|
|
|
|
if (g_ObjectHeapTypeShared[uType])
|
|
ret = SharedPtrToUser(pEntry->ptr);
|
|
else
|
|
ret = DesktopPtrToUser(pEntry->ptr);
|
|
|
|
return ret;
|
|
}
|
|
|
|
//
|
|
// Validate a callproc handle and return the pointer to the object.
|
|
//
|
|
PCALLPROCDATA
|
|
FASTCALL
|
|
ValidateCallProc(HANDLE hCallProc)
|
|
{
|
|
PUSER_HANDLE_ENTRY pEntry;
|
|
|
|
PCALLPROCDATA CallProc = ValidateHandle(hCallProc, TYPE_CALLPROC);
|
|
|
|
pEntry = GetUser32Handle(hCallProc);
|
|
|
|
if (CallProc != NULL && pEntry->ppi == g_ppi)
|
|
return CallProc;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// Validate a window handle and return the pointer to the object.
|
|
//
|
|
PWND
|
|
FASTCALL
|
|
ValidateHwnd(HWND hwnd)
|
|
{
|
|
PCLIENTINFO ClientInfo = GetWin32ClientInfo();
|
|
ASSERT(ClientInfo != NULL);
|
|
|
|
/* See if the window is cached */
|
|
if (hwnd && hwnd == ClientInfo->CallbackWnd.hWnd)
|
|
return ClientInfo->CallbackWnd.pWnd;
|
|
|
|
return ValidateHandle((HANDLE)hwnd, TYPE_WINDOW);
|
|
}
|
|
|
|
//
|
|
// Validate a window handle and return the pointer to the object.
|
|
//
|
|
PWND
|
|
FASTCALL
|
|
ValidateHwndNoErr(HWND hwnd)
|
|
{
|
|
PWND Wnd;
|
|
PCLIENTINFO ClientInfo = GetWin32ClientInfo();
|
|
ASSERT(ClientInfo != NULL);
|
|
|
|
/* See if the window is cached */
|
|
if (hwnd == ClientInfo->CallbackWnd.hWnd)
|
|
return ClientInfo->CallbackWnd.pWnd;
|
|
|
|
Wnd = ValidateHandleNoErr((HANDLE)hwnd, TYPE_WINDOW);
|
|
if (Wnd != NULL)
|
|
{
|
|
return Wnd;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
PWND
|
|
FASTCALL
|
|
GetThreadDesktopWnd(VOID)
|
|
{
|
|
PWND Wnd = GetThreadDesktopInfo()->spwnd;
|
|
if (Wnd != NULL)
|
|
Wnd = DesktopPtrToUser(Wnd);
|
|
return Wnd;
|
|
}
|
|
|
|
//
|
|
// Validate a window handle and return the pointer to the object.
|
|
//
|
|
PWND
|
|
FASTCALL
|
|
ValidateHwndOrDesk(HWND hwnd)
|
|
{
|
|
if (hwnd == HWND_DESKTOP)
|
|
return GetThreadDesktopWnd();
|
|
|
|
return ValidateHwnd(hwnd);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
DWORD WINAPI WCSToMBEx(WORD CodePage,LPWSTR UnicodeString,LONG UnicodeSize,LPSTR *MBString,LONG MBSize,BOOL Allocate)
|
|
{
|
|
DWORD Size;
|
|
if (UnicodeSize == -1)
|
|
{
|
|
UnicodeSize = wcslen(UnicodeString)+1;
|
|
}
|
|
if (MBSize == -1)
|
|
{
|
|
if (!Allocate)
|
|
{
|
|
return 0;
|
|
}
|
|
MBSize = UnicodeSize * 2;
|
|
}
|
|
if (Allocate)
|
|
{
|
|
LPSTR SafeString = RtlAllocateHeap(GetProcessHeap(), 0, MBSize);
|
|
if (SafeString == NULL)
|
|
return 0;
|
|
*MBString = SafeString;
|
|
}
|
|
if (CodePage == 0)
|
|
{
|
|
RtlUnicodeToMultiByteN(*MBString,MBSize,&Size,UnicodeString,UnicodeSize);
|
|
}
|
|
else
|
|
{
|
|
WideCharToMultiByte(CodePage,0,UnicodeString,UnicodeSize,*MBString,MBSize,0,0);
|
|
}
|
|
return UnicodeSize;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
DWORD WINAPI MBToWCSEx(WORD CodePage,LPSTR MBString,LONG MBSize,LPWSTR *UnicodeString,LONG UnicodeSize,BOOL Allocate)
|
|
{
|
|
DWORD Size;
|
|
if (MBSize == -1)
|
|
{
|
|
MBSize = strlen(MBString)+1;
|
|
}
|
|
if (UnicodeSize == -1)
|
|
{
|
|
if (!Allocate)
|
|
{
|
|
return 0;
|
|
}
|
|
UnicodeSize = MBSize;
|
|
}
|
|
if (Allocate)
|
|
{
|
|
LPWSTR SafeString = RtlAllocateHeap(GetProcessHeap(), 0, UnicodeSize);
|
|
if (SafeString == NULL)
|
|
return 0;
|
|
*UnicodeString = SafeString;
|
|
}
|
|
UnicodeSize *= sizeof(WCHAR);
|
|
if (CodePage == 0)
|
|
{
|
|
RtlMultiByteToUnicodeN(*UnicodeString,UnicodeSize,&Size,MBString,MBSize);
|
|
}
|
|
else
|
|
{
|
|
Size = MultiByteToWideChar(CodePage,0,MBString,MBSize,*UnicodeString,UnicodeSize);
|
|
}
|
|
return Size;
|
|
}
|