Author: peterw Date: Wed Apr 5 12:05:55 2006 New Revision: 21460
URL: http://svn.reactos.ru/svn/reactos?rev=21460&view=rev Log: Applied patch by: Thomas Weidenmueller - win32k window class rewrite. - http://www.reactos.org/bugzilla/show_bug.cgi?id=1366
Added: trunk/reactos/subsystems/win32/win32k/misc/usrheap.c Modified: trunk/reactos/dll/win32/user32/controls/regcontrol.c trunk/reactos/dll/win32/user32/misc/misc.c trunk/reactos/dll/win32/user32/windows/class.c trunk/reactos/dll/win32/user32/windows/message.c trunk/reactos/dll/win32/user32/windows/window.c trunk/reactos/include/ndk/pstypes.h trunk/reactos/include/reactos/probe.h trunk/reactos/include/reactos/win32k/ntuser.h trunk/reactos/lib/rtl/heap.c trunk/reactos/subsystems/win32/win32k/include/class.h trunk/reactos/subsystems/win32/win32k/include/desktop.h trunk/reactos/subsystems/win32/win32k/include/object.h trunk/reactos/subsystems/win32/win32k/include/userfuncs.h trunk/reactos/subsystems/win32/win32k/include/win32.h trunk/reactos/subsystems/win32/win32k/include/window.h trunk/reactos/subsystems/win32/win32k/main/dllmain.c trunk/reactos/subsystems/win32/win32k/misc/err.c trunk/reactos/subsystems/win32/win32k/ntuser/accelerator.c trunk/reactos/subsystems/win32/win32k/ntuser/class.c trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c trunk/reactos/subsystems/win32/win32k/ntuser/hook.c trunk/reactos/subsystems/win32/win32k/ntuser/menu.c trunk/reactos/subsystems/win32/win32k/ntuser/message.c trunk/reactos/subsystems/win32/win32k/ntuser/misc.c trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c trunk/reactos/subsystems/win32/win32k/ntuser/object.c trunk/reactos/subsystems/win32/win32k/ntuser/windc.c trunk/reactos/subsystems/win32/win32k/ntuser/window.c trunk/reactos/subsystems/win32/win32k/w32k.h trunk/reactos/subsystems/win32/win32k/win32k.rbuild trunk/reactos/tools/nci/w32ksvc.db
Modified: trunk/reactos/dll/win32/user32/controls/regcontrol.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/user32/controls/re... ============================================================================== --- trunk/reactos/dll/win32/user32/controls/regcontrol.c (original) +++ trunk/reactos/dll/win32/user32/controls/regcontrol.c Wed Apr 5 12:05:55 2006 @@ -44,15 +44,13 @@ RtlInitUnicodeString(&ClassName, Descr->name); }
- NtUserRegisterClassExWOW( + NtUserRegisterClassEx( &wc, - &ClassName, &ClassName, &MenuName, Descr->procA, REGISTERCLASS_SYSTEM, - 0, - 0); + NULL); }
/***********************************************************************
Modified: trunk/reactos/dll/win32/user32/misc/misc.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/user32/misc/misc.c... ============================================================================== --- trunk/reactos/dll/win32/user32/misc/misc.c (original) +++ trunk/reactos/dll/win32/user32/misc/misc.c Wed Apr 5 12:05:55 2006 @@ -113,3 +113,34 @@ { return NtUserUpdatePerUserSystemParameters(dwReserved, bEnable); } + +PW32THREADINFO +GetW32ThreadInfo(VOID) +{ + PW32THREADINFO ti; + + ti = (PW32THREADINFO)NtCurrentTeb()->Win32ThreadInfo; + if (ti == NULL) + { + /* create the W32THREADINFO structure */ + NtUserGetThreadState(THREADSTATE_GETTHREADINFO); + ti = (PW32THREADINFO)NtCurrentTeb()->Win32ThreadInfo; + } + + return ti; +} + +PW32PROCESSINFO +GetW32ProcessInfo(VOID) +{ + PW32THREADINFO ti; + PW32PROCESSINFO pi = NULL; + + ti = GetW32ThreadInfo(); + if (ti != NULL) + { + pi = ti->pi; + } + + return pi; +}
Modified: trunk/reactos/dll/win32/user32/windows/class.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/user32/windows/cla... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/class.c (original) +++ trunk/reactos/dll/win32/user32/windows/class.c Wed Apr 5 12:05:55 2006 @@ -11,117 +11,6 @@
#include <user32.h>
-static BOOL GetClassInfoExCommon( - HINSTANCE hInst, - LPCWSTR lpszClass, - LPWNDCLASSEXW lpwcx, - BOOL unicode) -{ - LPWSTR str; - UNICODE_STRING str2, str3; - WNDCLASSEXW w; - BOOL retval; - NTSTATUS Status; - - if ( !lpszClass || !lpwcx ) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if(IS_ATOM(lpszClass)) - str = (LPWSTR)lpszClass; - else - { - extern BOOL ControlsInitialized; - - if (unicode) - { - str = HEAP_strdupW ( lpszClass, wcslen(lpszClass) ); - - if ( !str ) - { - SetLastError (ERROR_OUTOFMEMORY); - return FALSE; - } - } - - else - { - Status = HEAP_strdupAtoW(&str, (LPCSTR)lpszClass, NULL); - - if (! NT_SUCCESS(Status)) - { - SetLastError(RtlNtStatusToDosError(Status)); - return FALSE; - } - } - - /* Register built-in controls if not already done */ - if ( !ControlsInitialized ) - { - ControlsInitialized = ControlsInit(str); - } - } - - str2.Length = str3.Length = 0; - str2.MaximumLength = str3.MaximumLength = 255; - str2.Buffer = (PWSTR)HEAP_alloc ( str2.MaximumLength * sizeof(WCHAR) ); - if ( !str2.Buffer ) - { - SetLastError (ERROR_OUTOFMEMORY); - if ( !IS_ATOM(str) ) - HEAP_free ( str ); - return FALSE; - } - - str3.Buffer = (PWSTR)HEAP_alloc ( str3.MaximumLength * sizeof(WCHAR) ); - if ( !str3.Buffer ) - { - SetLastError (ERROR_OUTOFMEMORY); - HEAP_free ( str2.Buffer ); - if ( !IS_ATOM(str) ) - HEAP_free ( str ); - return FALSE; - } - - w.lpszMenuName = (LPCWSTR)&str2; - w.lpszClassName = (LPCWSTR)&str3; - - /* get info about system classes? */ - if (!hInst) hInst = User32Instance; - - retval = (BOOL)NtUserGetClassInfo(hInst, str, &w, TRUE, 0); - - w.hInstance = (hInst == User32Instance) ? 0 : hInst; - - if ( !IS_ATOM(str) ) - HEAP_free(str); - - RtlCopyMemory ( lpwcx, &w, sizeof(WNDCLASSEXW) ); - - if ( !IS_INTRESOURCE(w.lpszMenuName) && w.lpszMenuName ) - { - if (unicode) - lpwcx->lpszMenuName = heap_string_poolW ( str2.Buffer, str2.Length ); - else - ((LPWNDCLASSEXA) lpwcx)->lpszMenuName = heap_string_poolA ( str2.Buffer, str2.Length ); - } - - if ( !IS_ATOM(w.lpszClassName) && w.lpszClassName ) - { - if (unicode) - lpwcx->lpszClassName = heap_string_poolW ( str3.Buffer, str3.Length ); - else - ((LPWNDCLASSEXA) lpwcx)->lpszClassName = heap_string_poolA ( str3.Buffer, str3.Length ); - } - - HEAP_free ( str2.Buffer ); - HEAP_free ( str3.Buffer ); - - return retval; -} -
/* * @implemented @@ -133,7 +22,40 @@ LPCSTR lpszClass, LPWNDCLASSEXA lpwcx) { - return GetClassInfoExCommon(hinst, (LPWSTR)lpszClass, (LPWNDCLASSEXW)lpwcx, FALSE); + UNICODE_STRING ClassName = {0}; + BOOL Ret; + + if (lpszClass == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (IS_ATOM(lpszClass)) + { + ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass); + } + else + { + if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, + lpszClass)) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + } + + Ret = NtUserGetClassInfo(hinst, + &ClassName, + (LPWNDCLASSEXW)lpwcx, + TRUE); + + if (!IS_ATOM(lpszClass)) + { + RtlFreeUnicodeString(&ClassName); + } + + return Ret; }
@@ -147,7 +69,28 @@ LPCWSTR lpszClass, LPWNDCLASSEXW lpwcx) { - return GetClassInfoExCommon(hinst, lpszClass, lpwcx, TRUE); + UNICODE_STRING ClassName = {0}; + + if (lpszClass == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (IS_ATOM(lpszClass)) + { + ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass); + } + else + { + RtlInitUnicodeString(&ClassName, + lpszClass); + } + + return NtUserGetClassInfo(hinst, + &ClassName, + lpwcx, + FALSE); }
@@ -170,6 +113,7 @@ return FALSE; }
+ w.cbSize = sizeof(w); retval = GetClassInfoExA(hInstance,lpClassName,&w); if (retval) { @@ -197,8 +141,12 @@ return FALSE; }
+ w.cbSize = sizeof(w); retval = GetClassInfoExW(hInstance,lpClassName,&w); - RtlCopyMemory (lpWndClass,&w.style,sizeof(WNDCLASSW)); + if (retval) + { + RtlCopyMemory (lpWndClass,&w.style,sizeof(WNDCLASSW)); + } return retval; }
@@ -275,25 +223,14 @@ LPSTR lpClassName, int nMaxCount) { - int result; - LPWSTR ClassNameW; - NTSTATUS Status; - - if(!lpClassName) - return 0; - - ClassNameW = HEAP_alloc ( (nMaxCount+1)*sizeof(WCHAR) ); - - result = NtUserGetClassName ( hWnd, ClassNameW, nMaxCount ); - - Status = HEAP_strcpyWtoA ( lpClassName, ClassNameW, result ); - - HEAP_free ( ClassNameW ); - - if ( !NT_SUCCESS(Status) ) - return 0; - - return result; + ANSI_STRING ClassName; + + ClassName.MaximumLength = nMaxCount; + ClassName.Buffer = lpClassName; + + return NtUserGetClassName(hWnd, + (PUNICODE_STRING)&ClassName, + TRUE); }
@@ -307,7 +244,14 @@ LPWSTR lpClassName, int nMaxCount) { - return NtUserGetClassName(hWnd, lpClassName, nMaxCount); + UNICODE_STRING ClassName; + + ClassName.MaximumLength = nMaxCount; + ClassName.Buffer = lpClassName; + + return NtUserGetClassName(hWnd, + &ClassName, + FALSE); }
@@ -573,8 +517,8 @@ RTL_ATOM Atom; WNDCLASSEXA WndClass; UNICODE_STRING ClassName; - UNICODE_STRING MenuName; - HMENU hMenu; + UNICODE_STRING MenuName = {0}; + HMENU hMenu = NULL;
if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXA) || lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 || @@ -609,16 +553,17 @@ WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon); }
- if HIWORD(lpwcx->lpszMenuName) - { - hMenu = 0; - RtlCreateUnicodeStringFromAsciiz(&MenuName, WndClass.lpszMenuName); - } - else - { - MenuName.Length = - MenuName.MaximumLength = 0; - MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName; + if (lpwcx->lpszMenuName != NULL) + { + if (HIWORD(lpwcx->lpszMenuName)) + { + RtlCreateUnicodeStringFromAsciiz(&MenuName, WndClass.lpszMenuName); + } + else + { + MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName; + } + hMenu = LoadMenuA(WndClass.hInstance, lpwcx->lpszMenuName); }
@@ -627,20 +572,18 @@ ClassName.Length = ClassName.MaximumLength = 0; ClassName.Buffer = (LPWSTR)WndClass.lpszClassName; - } else + } + else { RtlCreateUnicodeStringFromAsciiz(&ClassName, WndClass.lpszClassName); }
- Atom = NtUserRegisterClassExWOW( - (WNDCLASSEXW*)&WndClass, - &ClassName, - &ClassName, - &MenuName, - NULL, - REGISTERCLASS_ANSI, - 0, - hMenu); + Atom = NtUserRegisterClassEx((WNDCLASSEXW*)&WndClass, + &ClassName, + &MenuName, + NULL, + REGISTERCLASS_ANSI, + hMenu);
if (!IS_ATOM(WndClass.lpszMenuName)) RtlFreeUnicodeString(&MenuName); @@ -658,8 +601,8 @@ { WNDCLASSEXW WndClass; UNICODE_STRING ClassName; - UNICODE_STRING MenuName; - HMENU hMenu; + UNICODE_STRING MenuName = {0}; + HMENU hMenu = NULL;
if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) || lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 || @@ -694,16 +637,16 @@ WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon); }
- if HIWORD(lpwcx->lpszMenuName) - { - hMenu = 0; - RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName); - } - else - { - MenuName.Length = - MenuName.MaximumLength = 0; - MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName; + if (lpwcx->lpszMenuName != NULL) + { + if (HIWORD(lpwcx->lpszMenuName)) + { + RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName); + } + else + { + MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName; + } hMenu = LoadMenuW(WndClass.hInstance, lpwcx->lpszMenuName); }
@@ -712,20 +655,18 @@ ClassName.Length = ClassName.MaximumLength = 0; ClassName.Buffer = (LPWSTR)WndClass.lpszClassName; - } else + } + else { RtlInitUnicodeString(&ClassName, WndClass.lpszClassName); }
- return (ATOM)NtUserRegisterClassExWOW( - &WndClass, - &ClassName, - &ClassName, - &MenuName, - NULL, - 0, - 0, - hMenu); + return (ATOM)NtUserRegisterClassEx(&WndClass, + &ClassName, + &MenuName, + NULL, + 0, + hMenu); }
/* @@ -769,42 +710,65 @@ */ DWORD STDCALL -SetClassLongA ( - HWND hWnd, - int nIndex, - LONG dwNewLong) -{ - UNICODE_STRING str2buf; - PUNICODE_STRING str; - PUNICODE_STRING str2 = &str2buf; - - if ( nIndex != GCL_MENUNAME ) - { - return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, TRUE ); - } - if ( IS_INTRESOURCE(dwNewLong) ) - { - str2 = (PUNICODE_STRING)dwNewLong; - } - else - { - RtlCreateUnicodeStringFromAsciiz ( &str2buf,(LPSTR)dwNewLong ); - } - - str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE); - - if ( !IS_INTRESOURCE(dwNewLong) ) - { - RtlFreeUnicodeString ( str2 ); - } - if ( IS_INTRESOURCE(str) ) - { - return (DWORD)str; - } - else - { - return (DWORD)heap_string_poolA ( str->Buffer, str->Length ); - } +SetClassLongA (HWND hWnd, + int nIndex, + LONG dwNewLong) +{ + PSTR lpStr = (PSTR)dwNewLong; + UNICODE_STRING Value = {0}; + BOOL Allocated = FALSE; + DWORD Ret; + + /* FIXME - portability!!!! */ + + if (nIndex == GCL_MENUNAME && lpStr != NULL) + { + if (!IS_INTRESOURCE(lpStr)) + { + if (!RtlCreateUnicodeStringFromAsciiz(&Value, + lpStr)) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + Allocated = TRUE; + } + else + Value.Buffer = (PWSTR)lpStr; + + dwNewLong = (LONG)&Value; + } + else if (nIndex == GCW_ATOM && lpStr != NULL) + { + if (!IS_ATOM(lpStr)) + { + if (!RtlCreateUnicodeStringFromAsciiz(&Value, + lpStr)) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + Allocated = TRUE; + } + else + Value.Buffer = (PWSTR)lpStr; + + dwNewLong = (LONG)&Value; + } + + Ret = (DWORD)NtUserSetClassLong(hWnd, + nIndex, + dwNewLong, + TRUE); + + if (Allocated) + { + RtlFreeUnicodeString(&Value); + } + + return Ret; }
@@ -813,42 +777,44 @@ */ DWORD STDCALL -SetClassLongW( - HWND hWnd, - int nIndex, - LONG dwNewLong) -{ - UNICODE_STRING str2buf; - PUNICODE_STRING str; - PUNICODE_STRING str2 = &str2buf; - - if (nIndex != GCL_MENUNAME ) - { - return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, FALSE ); - } - if ( IS_INTRESOURCE(dwNewLong) ) - { - str2 = (PUNICODE_STRING)dwNewLong; - } - else - { - RtlCreateUnicodeString ( &str2buf, (LPWSTR)dwNewLong ); - } - - str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE); - - if ( !IS_INTRESOURCE(dwNewLong) ) - { - RtlFreeUnicodeString(str2); - } - if ( IS_INTRESOURCE(str) ) - { - return (DWORD)str; - } - else - { - return (DWORD)heap_string_poolW ( str->Buffer, str->Length ); - } +SetClassLongW(HWND hWnd, + int nIndex, + LONG dwNewLong) +{ + PWSTR lpStr = (PWSTR)dwNewLong; + UNICODE_STRING Value = {0}; + + /* FIXME - portability!!!! */ + + if (nIndex == GCL_MENUNAME && lpStr != NULL) + { + if (!IS_INTRESOURCE(lpStr)) + { + RtlInitUnicodeString(&Value, + lpStr); + } + else + Value.Buffer = lpStr; + + dwNewLong = (LONG)&Value; + } + else if (nIndex == GCW_ATOM && lpStr != NULL) + { + if (!IS_ATOM(lpStr)) + { + RtlInitUnicodeString(&Value, + lpStr); + } + else + Value.Buffer = lpStr; + + dwNewLong = (LONG)&Value; + } + + return (DWORD)NtUserSetClassLong(hWnd, + nIndex, + dwNewLong, + FALSE); }
@@ -868,7 +834,7 @@ if ((nIndex < 0) && (nIndex != GCW_ATOM)) return 0;
- return (WORD) NtUserSetClassLong ( hWnd, nIndex, wNewWord, TRUE ); + return (WORD) SetClassLongW ( hWnd, nIndex, wNewWord ); }
@@ -909,28 +875,32 @@ LPCSTR lpClassName, HINSTANCE hInstance) { - LPWSTR ClassName; - NTSTATUS Status; - BOOL Result; - - if(!IS_ATOM(lpClassName)) - { - Status = HEAP_strdupAtoW(&ClassName, lpClassName, NULL); - if(!NT_SUCCESS(Status)) - { - SetLastError(RtlNtStatusToDosError(Status)); - return FALSE; - } - } - else - ClassName = (LPWSTR)lpClassName; - - Result = (BOOL)NtUserUnregisterClass((LPCWSTR)ClassName, hInstance, 0); - - if(ClassName && !IS_ATOM(lpClassName)) - HEAP_free(ClassName); - - return Result; + UNICODE_STRING ClassName = {0}; + NTSTATUS Status; + BOOL Ret; + + if (!IS_ATOM(lpClassName)) + { + Status = HEAP_strdupAtoW(&ClassName.Buffer, lpClassName, NULL); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + + RtlInitUnicodeString(&ClassName, + ClassName.Buffer); + } + else + ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName); + + Ret = NtUserUnregisterClass(&ClassName, + hInstance); + + if(!IS_ATOM(lpClassName) && ClassName.Buffer != NULL) + HEAP_free(ClassName.Buffer); + + return Ret; }
@@ -943,7 +913,18 @@ LPCWSTR lpClassName, HINSTANCE hInstance) { - return (BOOL)NtUserUnregisterClass(lpClassName, hInstance, 0); + UNICODE_STRING ClassName = {0}; + + if (!IS_ATOM(lpClassName)) + { + RtlInitUnicodeString(&ClassName, + lpClassName); + } + else + ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName); + + return NtUserUnregisterClass(&ClassName, + hInstance); }
/* EOF */
Modified: trunk/reactos/dll/win32/user32/windows/message.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/user32/windows/mes... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/message.c (original) +++ trunk/reactos/dll/win32/user32/windows/message.c Wed Apr 5 12:05:55 2006 @@ -951,6 +951,7 @@ return FALSE; } Result = WndProc(AnsiMsg.hwnd, AnsiMsg.message, AnsiMsg.wParam, AnsiMsg.lParam); + if (! MsgiUnicodeToAnsiReply(&AnsiMsg, &UnicodeMsg, &Result)) { return FALSE; @@ -991,6 +992,7 @@ } Result = WndProc(UnicodeMsg.hwnd, UnicodeMsg.message, UnicodeMsg.wParam, UnicodeMsg.lParam); + if (! MsgiAnsiToUnicodeReply(&UnicodeMsg, &AnsiMsg, &Result)) { return FALSE; @@ -1010,20 +1012,19 @@ WPARAM wParam, LPARAM lParam) { - BOOL IsHandle; - WndProcHandle wphData; + WNDPROC_INFO wpInfo;
if (lpPrevWndFunc == NULL) - lpPrevWndFunc = (WNDPROC)NtUserGetWindowLong(hWnd, GWL_WNDPROC, FALSE); - - IsHandle = NtUserDereferenceWndProcHandle(lpPrevWndFunc,&wphData); - if (! IsHandle) + lpPrevWndFunc = (WNDPROC)NtUserGetWindowLong(hWnd, GWLP_WNDPROC, FALSE); + + if (!NtUserDereferenceWndProcHandle((HANDLE)lpPrevWndFunc, + &wpInfo)) { return IntCallWindowProcA(TRUE, lpPrevWndFunc, hWnd, Msg, wParam, lParam); } else { - return IntCallWindowProcA(! wphData.IsUnicode, wphData.WindowProc, + return IntCallWindowProcA(!wpInfo.IsUnicode, wpInfo.WindowProc, hWnd, Msg, wParam, lParam); } } @@ -1039,17 +1040,16 @@ WPARAM wParam, LPARAM lParam) { - BOOL IsHandle; - WndProcHandle wphData; - - IsHandle = NtUserDereferenceWndProcHandle(lpPrevWndFunc,&wphData); - if (! IsHandle) + WNDPROC_INFO wpInfo; + + if (!NtUserDereferenceWndProcHandle((HANDLE)lpPrevWndFunc, + &wpInfo)) { return IntCallWindowProcW(FALSE, lpPrevWndFunc, hWnd, Msg, wParam, lParam); } else { - return IntCallWindowProcW(! wphData.IsUnicode, wphData.WindowProc, + return IntCallWindowProcW(!wpInfo.IsUnicode, wpInfo.WindowProc, hWnd, Msg, wParam, lParam); } }
Modified: trunk/reactos/dll/win32/user32/windows/window.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/user32/windows/win... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/window.c (original) +++ trunk/reactos/dll/win32/user32/windows/window.c Wed Apr 5 12:05:55 2006 @@ -289,8 +289,8 @@ { wce.cbSize = sizeof(WNDCLASSEXW); if(GetClassInfoExW(hInstance, lpClassName, &wce) && wce.lpszMenuName) - { - hMenu = LoadMenuW(hInstance, wce.lpszMenuName); + {DbgPrint("LoadingMenu 0x%p %d\n", wce.lpszMenuName, IS_INTRESOURCE(wce.lpszMenuName)); + hMenu = LoadMenuW(hInstance, wce.lpszMenuName);DbgPrint("Loaded menu: 0x%p\n", hMenu); } }
@@ -1449,7 +1449,7 @@ STDCALL GetFocus(VOID) { - return (HWND)NtUserGetThreadState(0); + return (HWND)NtUserGetThreadState(THREADSTATE_FOCUSWINDOW); }
/*
Modified: trunk/reactos/include/ndk/pstypes.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/include/ndk/pstypes.h?rev=21... ============================================================================== --- trunk/reactos/include/ndk/pstypes.h (original) +++ trunk/reactos/include/ndk/pstypes.h Wed Apr 5 12:05:55 2006 @@ -424,7 +424,7 @@ ULONG LastErrorValue; /* 34h */ ULONG CountOfOwnedCriticalSections; /* 38h */ PVOID CsrClientThread; /* 3Ch */ - struct _W32THREAD* Win32ThreadInfo; /* 40h */ + PVOID Win32ThreadInfo; /* 40h */ ULONG User32Reserved[0x1A]; /* 44h */ ULONG UserReserved[5]; /* ACh */ PVOID WOW32Reserved; /* C0h */
Modified: trunk/reactos/include/reactos/probe.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/include/reactos/probe.h?rev=... ============================================================================== --- trunk/reactos/include/reactos/probe.h (original) +++ trunk/reactos/include/reactos/probe.h Wed Apr 5 12:05:55 2006 @@ -8,6 +8,14 @@ static const UNICODE_STRING __emptyUnicodeString = {0}; static const LARGE_INTEGER __emptyLargeInteger = {{0, 0}}; static const ULARGE_INTEGER __emptyULargeInteger = {{0, 0}}; + +#if defined(_WIN32K_) +/* + * NOTE: NTOSKRNL unfortunately doesn't export RtlRaiseStatus! + */ +VOID NTAPI W32kRaiseStatus(NTSTATUS Status); +#define RtlRaiseStatus W32kRaiseStatus +#endif
/* * NOTE: Alignment of the pointers is not verified!
Modified: trunk/reactos/include/reactos/win32k/ntuser.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/include/reactos/win32k/ntuse... ============================================================================== --- trunk/reactos/include/reactos/win32k/ntuser.h (original) +++ trunk/reactos/include/reactos/win32k/ntuser.h Wed Apr 5 12:05:55 2006 @@ -1,6 +1,75 @@ #ifndef __WIN32K_NTUSER_H #define __WIN32K_NTUSER_H
+struct _W32PROCESSINFO; +struct _W32THREADINFO; + +typedef struct _DESKTOP +{ + HANDLE hKernelHeap; + WCHAR szDesktopName[1]; +} DESKTOP, *PDESKTOP; + +typedef struct _CALLPROC +{ + struct _W32PROCESSINFO *pi; + WNDPROC WndProc; + BOOL Unicode : 1; +} CALLPROC, *PCALLPROC; + +typedef struct _WINDOWCLASS +{ + struct _WINDOWCLASS *Next; + struct _WINDOWCLASS *Clone; + struct _WINDOWCLASS *Base; + PDESKTOP Desktop; + RTL_ATOM Atom; + ULONG Windows; + + UINT Style; + WNDPROC WndProc; + union + { + WNDPROC WndProcExtra; + PCALLPROC CallProc; + }; + INT ClsExtra; + INT WndExtra; + HINSTANCE hInstance; + HANDLE hIcon; /* FIXME - Use pointer! */ + HANDLE hIconSm; /* FIXME - Use pointer! */ + HANDLE hCursor; /* FIXME - Use pointer! */ + HBRUSH hbrBackground; + HANDLE hMenu; /* FIXME - Use pointer! */ + PWSTR MenuName; + PSTR AnsiMenuName; + + ULONG_PTR ClassExtraDataOffset; + + BOOL Destroying : 1; + BOOL Unicode : 1; + BOOL System : 1; + BOOL Global : 1; +} WINDOWCLASS, *PWINDOWCLASS; + +typedef struct _W32PROCESSINFO +{ + PVOID UserHandleTable; + PWINDOWCLASS LocalClassList; + PWINDOWCLASS GlobalClassList; + PWINDOWCLASS SystemClassList; +} W32PROCESSINFO, *PW32PROCESSINFO; + +typedef struct _W32THREADINFO +{ + PW32PROCESSINFO pi; /* [USER] */ + PW32PROCESSINFO kpi; /* [KERNEL] */ + PDESKTOP Desktop; + ULONG_PTR DesktopHeapDelta; +} W32THREADINFO, *PW32THREADINFO; + +PW32THREADINFO GetW32ThreadInfo(VOID); +PW32PROCESSINFO GetW32ProcessInfo(VOID);
DWORD NTAPI @@ -196,8 +265,8 @@ ULONG NTAPI NtUserGetSystemMetrics(ULONG Index);
-DWORD NTAPI -NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi); +ULONG_PTR NTAPI +NtUserGetClassLong(HWND hWnd, INT Offset, BOOL Ansi);
LONG NTAPI NtUserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi); @@ -785,18 +854,17 @@ NtUserGetCaretPos( LPPOINT lpPoint);
-DWORD NTAPI -NtUserGetClassInfo(HINSTANCE hInst, - LPCWSTR str, +BOOL NTAPI +NtUserGetClassInfo(HINSTANCE hInstance, + PUNICODE_STRING ClassName, LPWNDCLASSEXW wcex, - BOOL Ansi, - DWORD unknown3); - -DWORD + BOOL Ansi); + +INT NTAPI NtUserGetClassName(HWND hWnd, - LPWSTR lpClassName, - ULONG nMaxCount); + PUNICODE_STRING ClassName, + BOOL Ansi);
HANDLE NTAPI @@ -1041,6 +1109,7 @@ DWORD dwThreadId, DWORD Unknown1);
+#define THREADSTATE_GETTHREADINFO (0) #define THREADSTATE_FOCUSWINDOW (1) #define THREADSTATE_INSENDMESSAGE (2) DWORD @@ -1355,14 +1424,12 @@ #define REGISTERCLASS_ALL (REGISTERCLASS_ANSI | REGISTERCLASS_SYSTEM)
RTL_ATOM NTAPI -NtUserRegisterClassExWOW( +NtUserRegisterClassEx( CONST WNDCLASSEXW* lpwcx, PUNICODE_STRING ClassName, - PUNICODE_STRING ClassNameCopy, PUNICODE_STRING MenuName, WNDPROC wpExtra, DWORD Flags, - DWORD Unknown7, HMENU hMenu);
BOOL @@ -1470,11 +1537,11 @@ HWND NTAPI NtUserGetCapture(VOID);
-DWORD NTAPI +ULONG_PTR NTAPI NtUserSetClassLong( HWND hWnd, - DWORD Offset, - LONG dwNewLong, + INT Offset, + ULONG_PTR dwNewLong, BOOL Ansi );
@@ -1840,9 +1907,8 @@ BOOL NTAPI NtUserUnregisterClass( - LPCWSTR ClassNameOrAtom, - HINSTANCE hInstance, - DWORD Unknown); + PUNICODE_STRING ClassNameOrAtom, + HINSTANCE hInstance);
BOOL NTAPI @@ -1951,15 +2017,15 @@
HWND NTAPI NtUserGetLastActivePopup(HWND hWnd); -typedef struct _WndProcHandle + +typedef struct _WNDPROC_INFO { - WNDPROC WindowProc; - BOOL IsUnicode; - HANDLE ProcessID; -} WndProcHandle; + WNDPROC WindowProc; + BOOL IsUnicode; +} WNDPROC_INFO, *PWNDPROC_INFO;
-DWORD NTAPI -NtUserDereferenceWndProcHandle(WNDPROC wpHandle, WndProcHandle *Data); +BOOL NTAPI +NtUserDereferenceWndProcHandle(IN HANDLE wpHandle, OUT PWNDPROC_INFO wpInfo);
VOID NTAPI NtUserManualGuiCheck(LONG Check);
Modified: trunk/reactos/lib/rtl/heap.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/lib/rtl/heap.c?rev=21460&... ============================================================================== --- trunk/reactos/lib/rtl/heap.c (original) +++ trunk/reactos/lib/rtl/heap.c Wed Apr 5 12:05:55 2006 @@ -311,7 +311,7 @@ } else { - Status = NtAllocateVirtualMemory(NtCurrentProcess(), + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &address, 0, &commitsize, @@ -570,13 +570,24 @@
/* Initialize critical section */
- RtlInitializeHeapLock( &heap->critSection ); + if (RtlpGetMode() == UserMode) + { + RtlInitializeHeapLock( &heap->critSection ); + } }
/* Commit memory */ if (heap->commitRoutine) { - Status = heap->commitRoutine(heap, &address, &commitSize); + if (subheap != (SUBHEAP *)heap) + { + Status = heap->commitRoutine(heap, &address, &commitSize); + } + else + { + /* the caller is responsible for committing the first page! */ + Status = STATUS_SUCCESS; + } } else {
Modified: trunk/reactos/subsystems/win32/win32k/include/class.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/incl... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/class.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/class.h Wed Apr 5 12:05:55 2006 @@ -4,28 +4,19 @@ #define IS_ATOM(x) \ (((ULONG_PTR)(x) > 0x0) && ((ULONG_PTR)(x) < 0x10000))
-typedef struct _WNDCLASS_OBJECT -{ - UINT cbSize; - LONG refs; /* windows using this class (is 0 after class creation) */ - UINT style; - WNDPROC lpfnWndProcA; - WNDPROC lpfnWndProcW; - int cbClsExtra; - int cbWndExtra; - HANDLE hInstance; - HICON hIcon; - HCURSOR hCursor; - HBRUSH hbrBackground; - HMENU hMenu; - UNICODE_STRING lpszMenuName; - RTL_ATOM Atom; - HICON hIconSm; - BOOL Unicode; - BOOL Global; - LIST_ENTRY ListEntry; /* linked into owning process */ - PCHAR ExtraData; -} WNDCLASS_OBJECT, *PWNDCLASS_OBJECT; +VOID +DestroyCallProc(IN PDESKTOP Desktop, + IN OUT PCALLPROC CallProc); + +PCALLPROC +CloneCallProc(IN PDESKTOP Desktop, + IN PCALLPROC CallProc); + +PCALLPROC +CreateCallProc(IN PDESKTOP Desktop, + IN WNDPROC WndProc, + IN BOOL Unicode, + IN PW32PROCESSINFO pi);
NTSTATUS FASTCALL InitClassImpl(VOID); @@ -33,32 +24,45 @@ NTSTATUS FASTCALL CleanupClassImpl(VOID);
-void FASTCALL DestroyProcessClasses(PW32PROCESS Process ); +BOOL +UserGetCallProcInfo(IN HANDLE hCallProc, + OUT PWNDPROC_INFO wpInfo);
-__inline VOID FASTCALL -ClassDerefObject(PWNDCLASS_OBJECT Class); +void FASTCALL +DestroyProcessClasses(PW32PROCESS Process );
-__inline VOID FASTCALL -ClassRefObject(PWNDCLASS_OBJECT Class); +PWINDOWCLASS +IntReferenceClass(IN PWINDOWCLASS BaseClass, + IN PDESKTOP Desktop);
-PWNDCLASS_OBJECT FASTCALL -ClassGetClassByAtom( - RTL_ATOM Atom, - HINSTANCE hInstance); +VOID +IntDereferenceClass(IN OUT PWINDOWCLASS Class, + IN PDESKTOP Desktop, + IN PW32PROCESSINFO pi);
-PWNDCLASS_OBJECT FASTCALL -ClassGetClassByName( - LPCWSTR ClassName, - HINSTANCE hInstance); +RTL_ATOM +UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx, + IN PUNICODE_STRING ClassName, + IN PUNICODE_STRING MenuName, + IN HANDLE hMenu, + IN WNDPROC wpExtra, + IN DWORD dwFlags);
-PWNDCLASS_OBJECT FASTCALL -ClassGetClassByNameOrAtom( - LPCWSTR ClassNameOrAtom, - HINSTANCE hInstance); +BOOL +UserUnregisterClass(IN PUNICODE_STRING ClassName, + IN HINSTANCE hInstance);
-struct _WINDOW_OBJECT; -ULONG FASTCALL -IntGetClassLong(struct _WINDOW_OBJECT *WindowObject, ULONG Offset, BOOL Ansi); +ULONG_PTR +UserGetClassLongPtr(IN PWINDOWCLASS Class, + IN INT Index, + IN BOOL Ansi); + +RTL_ATOM +IntGetClassAtom(IN PUNICODE_STRING ClassName, + IN HINSTANCE hInstance OPTIONAL, + IN PW32PROCESSINFO pi OPTIONAL, + OUT PWINDOWCLASS *BaseClass OPTIONAL, + OUT PWINDOWCLASS **Link OPTIONAL);
#endif /* _WIN32K_CLASS_H */
Modified: trunk/reactos/subsystems/win32/win32k/include/desktop.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/incl... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/desktop.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/desktop.h Wed Apr 5 12:05:55 2006 @@ -6,8 +6,6 @@
typedef struct _DESKTOP_OBJECT { - PVOID DesktopHeap; /* points to kmode memory! */ - CSHORT Type; CSHORT Size; LIST_ENTRY ListEntry; @@ -26,11 +24,15 @@ PVOID BlockInputThread;
LIST_ENTRY ShellHookWindows; + + HANDLE hDesktopHeap; + PSECTION_OBJECT DesktopHeapSection; + PDESKTOP DesktopInfo; } DESKTOP_OBJECT, *PDESKTOP_OBJECT;
extern PDESKTOP_OBJECT InputDesktop; extern HDESK InputDesktopHandle; -extern PWNDCLASS_OBJECT DesktopWindowClass; +extern PWINDOWCLASS DesktopWindowClass; extern HDC ScreenDeviceContext; extern BOOL g_PaintDesktopVersion;
@@ -91,6 +93,8 @@ HDESK FASTCALL IntGetDesktopObjectHandle(PDESKTOP_OBJECT DesktopObject);
+BOOL IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject); + NTSTATUS FASTCALL IntValidateDesktopHandle( HDESK Desktop, @@ -115,6 +119,113 @@ #define IntIsActiveDesktop(Desktop) \ ((Desktop)->WindowStation->ActiveDesktop == (Desktop))
+static __inline PVOID +DesktopHeapAlloc(IN PDESKTOP Desktop, + IN SIZE_T Bytes) +{ + return RtlAllocateHeap(Desktop->hKernelHeap, + HEAP_NO_SERIALIZE, + Bytes); +} + +static __inline BOOL +DesktopHeapFree(IN PDESKTOP Desktop, + IN PVOID lpMem) +{ + return RtlFreeHeap(Desktop->hKernelHeap, + HEAP_NO_SERIALIZE, + lpMem); +} + +static __inline PVOID +DesktopHeapReAlloc(IN PDESKTOP Desktop, + IN PVOID lpMem, + IN SIZE_T Bytes) +{ +#if 0 + /* NOTE: ntoskrnl doesn't export RtlReAllocateHeap... */ + return RtlReAllocateHeap(Desktop->hKernelHeap, + HEAP_NO_SERIALIZE, + lpMem, + Bytes); +#else + SIZE_T PrevSize; + PVOID pNew; + + PrevSize = RtlSizeHeap(Desktop->hKernelHeap, + HEAP_NO_SERIALIZE, + lpMem); + + if (PrevSize == Bytes) + return lpMem; + + pNew = RtlAllocateHeap(Desktop->hKernelHeap, + HEAP_NO_SERIALIZE, + Bytes); + if (pNew != NULL) + { + if (PrevSize < Bytes) + Bytes = PrevSize; + + RtlCopyMemory(pNew, + lpMem, + Bytes); + + RtlFreeHeap(Desktop->hKernelHeap, + HEAP_NO_SERIALIZE, + lpMem); + } + + return pNew; +#endif +} + +static __inline ULONG_PTR +DesktopHeapGetUserDelta(VOID) +{ + PW32HEAP_USER_MAPPING Mapping; + HANDLE hDesktopHeap; + ULONG_PTR Delta = 0; + + ASSERT(PsGetWin32Thread()->Desktop != NULL); + hDesktopHeap = PsGetWin32Thread()->Desktop->hDesktopHeap; + + Mapping = PsGetWin32Process()->HeapMappings.Next; + while (Mapping != NULL) + { + if (Mapping->UserMapping == (PVOID)hDesktopHeap) + { + Delta = (ULONG_PTR)Mapping->KernelMapping - (ULONG_PTR)Mapping->UserMapping; + break; + } + + Mapping = Mapping->Next; + } + + return Delta; +} + +static __inline PVOID +DesktopHeapAddressToUser(IN PDESKTOP Desktop, + PVOID lpMem) +{ + PW32HEAP_USER_MAPPING Mapping; + + Mapping = PsGetWin32Process()->HeapMappings.Next; + while (Mapping != NULL) + { + if (Mapping->KernelMapping == (PVOID)Desktop->hKernelHeap) + { + return (PVOID)(((ULONG_PTR)lpMem - (ULONG_PTR)Desktop->hKernelHeap) + + (ULONG_PTR)Mapping->UserMapping); + } + + Mapping = Mapping->Next; + } + + return NULL; +} + #endif /* _WIN32K_DESKTOP_H */
/* EOF */
Modified: trunk/reactos/subsystems/win32/win32k/include/object.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/incl... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/object.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/object.h Wed Apr 5 12:05:55 2006 @@ -45,7 +45,7 @@ otCursorIcon, otHook, otMonitor, - otClass //fixme: remove + otCallProc
} USER_OBJECT_TYPE;
@@ -125,6 +125,8 @@ \ }
+HANDLE FASTCALL ObmObjectToHandle(PVOID obj); + VOID FASTCALL CreateStockObjects (VOID); VOID FASTCALL CreateSysColorObjects (VOID);
Modified: trunk/reactos/subsystems/win32/win32k/include/userfuncs.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/incl... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/userfuncs.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/userfuncs.h Wed Apr 5 12:05:55 2006 @@ -75,7 +75,7 @@
/******************** HANDLE.C ***************/
-extern USER_HANDLE_TABLE gHandleTable; +extern PUSER_HANDLE_TABLE gHandleTable;
PUSER_HANDLE_ENTRY handle_to_entry(PUSER_HANDLE_TABLE ht, HANDLE handle ); VOID UserInitHandleTable(PUSER_HANDLE_TABLE ht, PVOID mem, ULONG bytes);
Modified: trunk/reactos/subsystems/win32/win32k/include/win32.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/incl... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/win32.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/win32.h Wed Apr 5 12:05:55 2006 @@ -15,10 +15,18 @@ BOOLEAN IsExiting; SINGLE_LIST_ENTRY ReferencesList;
+ PW32THREADINFO ThreadInfo; } W32THREAD, *PW32THREAD;
#include <poppack.h>
+typedef struct _W32HEAP_USER_MAPPING +{ + struct _W32HEAP_USER_MAPPING *Next; + PVOID KernelMapping; + PVOID UserMapping; + ULONG Count; +} W32HEAP_USER_MAPPING, *PW32HEAP_USER_MAPPING;
typedef struct _W32PROCESS { @@ -32,6 +40,9 @@ ULONG Flags; LONG GDIObjects; LONG UserObjects; + + W32HEAP_USER_MAPPING HeapMappings; + PW32PROCESSINFO ProcessInfo; } W32PROCESS, *PW32PROCESS;
Modified: trunk/reactos/subsystems/win32/win32k/include/window.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/incl... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/window.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/window.h Wed Apr 5 12:05:55 2006 @@ -26,8 +26,21 @@
typedef struct _WINDOW_OBJECT { + /* Pointer to the thread information */ + PW32THREADINFO ti; + /* Pointer to the desktop */ + PDESKTOP Desktop; + union + { + /* Pointer to a call procedure handle */ + PCALLPROC CallProc; + /* Extra Wnd proc (windows of system classes) */ + WNDPROC WndProcExtra; + }; + /* Indicates whether the window is derived from a system class */ + BOOL IsSystem; /* Pointer to the window class. */ - PWNDCLASS_OBJECT Class; + PWINDOWCLASS Class; /* Extended style. */ DWORD ExStyle; /* Window name. */ @@ -81,8 +94,7 @@ PWINDOW_SCROLLINFO Scroll; LONG UserData; BOOL Unicode; - WNDPROC WndProcA; - WNDPROC WndProcW; + WNDPROC WndProc; PETHREAD OwnerThread; HWND hWndLastPopup; /* handle to last active popup window (wine doesn't use pointer, for unk. reason)*/ PINTERNALPOS InternalPos; @@ -190,10 +202,6 @@ BOOL FASTCALL IntIsWindowInDestroy(PWINDOW_OBJECT Window);
-DWORD IntRemoveWndProcHandle(WNDPROC Handle); -DWORD IntRemoveProcessWndProcHandles(HANDLE ProcessID); -DWORD IntAddWndProcHandle(WNDPROC WindowProc, BOOL IsUnicode); - BOOL FASTCALL IntShowOwnedPopups( PWINDOW_OBJECT owner, BOOL fShow );
Modified: trunk/reactos/subsystems/win32/win32k/main/dllmain.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/main... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/main/dllmain.c (original) +++ trunk/reactos/subsystems/win32/win32k/main/dllmain.c Wed Apr 5 12:05:55 2006 @@ -33,6 +33,9 @@ PGDI_HANDLE_TABLE GdiHandleTable = NULL; PSECTION_OBJECT GdiTableSection = NULL;
+HANDLE GlobalUserHeap = NULL; +PSECTION_OBJECT GlobalUserHeapSection = NULL; + extern ULONG_PTR Win32kSSDT[]; extern UCHAR Win32kSSPT[]; extern ULONG Win32kNumberOfSysCalls; @@ -69,7 +72,34 @@
if (Create) { + ULONG ViewSize = 0; + LARGE_INTEGER Offset; + PVOID UserBase = NULL; + NTSTATUS Status; + extern PSECTION_OBJECT GlobalUserHeapSection; DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql()); + + /* map the global heap into the process */ + Offset.QuadPart = 0; + Status = MmMapViewOfSection(GlobalUserHeapSection, + PsGetCurrentProcess(), + &UserBase, + 0, + 0, + &Offset, + &ViewSize, + ViewUnmap, + SEC_NO_CHANGE, + PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */ + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to map the global heap! 0x%x\n", Status); + RETURN(Status); + } + Win32Process->HeapMappings.Next = NULL; + Win32Process->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap; + Win32Process->HeapMappings.UserMapping = UserBase; + Win32Process->HeapMappings.Count = 1;
InitializeListHead(&Win32Process->ClassList);
@@ -95,7 +125,6 @@ else { DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql()); - IntRemoveProcessWndProcHandles((HANDLE)Process->UniqueProcessId); IntCleanupMenus(Process, Win32Process); IntCleanupCurIcons(Process, Win32Process); IntEngCleanupDriverObjs(Process, Win32Process); @@ -114,6 +143,12 @@ if(LogonProcess == Win32Process) { LogonProcess = NULL; + } + + if (Win32Process->ProcessInfo != NULL) + { + UserHeapFree(Win32Process->ProcessInfo); + Win32Process->ProcessInfo = NULL; } }
@@ -198,17 +233,25 @@
if (hDesk != NULL) { + PDESKTOP_OBJECT DesktopObject; + Win32Thread->Desktop = NULL; Status = ObReferenceObjectByHandle(hDesk, 0, ExDesktopObjectType, KernelMode, - (PVOID*)&Win32Thread->Desktop, + (PVOID*)&DesktopObject, NULL); NtClose(hDesk); - if(!NT_SUCCESS(Status)) + if(NT_SUCCESS(Status)) + { + if (!IntSetThreadDesktop(DesktopObject)) + { + DPRINT1("Unable to set thread desktop\n"); + } + } + else { DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk); - Win32Thread->Desktop = NULL; } } } @@ -234,11 +277,15 @@ IntBlockInput(Win32Thread, FALSE); MsqDestroyMessageQueue(Win32Thread->MessageQueue); IntCleanupThreadCallbacks(Win32Thread); - if(Win32Thread->Desktop != NULL) - { - ObDereferenceObject(Win32Thread->Desktop); - } - + + IntSetThreadDesktop(NULL); + + if (Win32Thread->ThreadInfo != NULL) + { + UserHeapFree(Win32Thread->ThreadInfo); + Win32Thread->ThreadInfo = NULL; + } + /* cleanup user object references stack */ e = PopEntryList(&Win32Thread->ReferencesList); while (e) @@ -309,6 +356,7 @@ NTSTATUS Status; BOOLEAN Result; W32_CALLOUT_DATA CalloutData; + PVOID GlobalUserHeapBase = NULL;
/* * Register user mode call interface @@ -342,6 +390,16 @@ */ PsEstablishWin32Callouts(&CalloutData);
+ GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection, + &GlobalUserHeapBase, + 1 * 1024 * 1024); /* FIXME - 1 MB for now... */ + if (GlobalUserHeap == NULL) + { + DPRINT1("Failed to initialize the global heap!\n"); + return STATUS_UNSUCCESSFUL; + } + + Status = InitUserImpl(); if (!NT_SUCCESS(Status)) {
Modified: trunk/reactos/subsystems/win32/win32k/misc/err.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/misc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/misc/err.c (original) +++ trunk/reactos/subsystems/win32/win32k/misc/err.c Wed Apr 5 12:05:55 2006 @@ -61,4 +61,22 @@ return 0; }
+VOID +NTAPI +W32kRaiseStatus(NTSTATUS Status) +{ + EXCEPTION_RECORD ExceptionRecord; + + /* Create an exception record */ + ExceptionRecord.ExceptionCode = Status; + ExceptionRecord.ExceptionRecord = NULL; + ExceptionRecord.NumberParameters = 0; + ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + + RtlRaiseException(&ExceptionRecord); + + /* If we returned, raise a status */ + W32kRaiseStatus(Status); +} + /* EOF */
Added: trunk/reactos/subsystems/win32/win32k/misc/usrheap.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/misc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/misc/usrheap.c (added) +++ trunk/reactos/subsystems/win32/win32k/misc/usrheap.c Wed Apr 5 12:05:55 2006 @@ -1,0 +1,216 @@ +/* + * ReactOS W32 Subsystem + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <w32k.h> + +#define NDEBUG +#include <debug.h> + + +static NTSTATUS NTAPI +IntUserHeapCommitRoutine(IN PVOID Base, + IN OUT PVOID *CommitAddress, + IN OUT PSIZE_T CommitSize) +{ + PW32PROCESS W32Process; + PW32HEAP_USER_MAPPING Mapping; + PVOID UserBase = NULL; + NTSTATUS Status; + SIZE_T Delta = (SIZE_T)((ULONG_PTR)(*CommitAddress) - (ULONG_PTR)Base); + + W32Process = PsGetWin32Process(); + + if (W32Process != NULL) + { + /* search for the mapping */ + Mapping = &W32Process->HeapMappings; + while (Mapping != NULL) + { + if (Mapping->KernelMapping == Base) + { + UserBase = Mapping->UserMapping; + break; + } + + Mapping = Mapping->Next; + } + + ASSERT(UserBase != NULL); + } + else + { + ULONG ViewSize = 0; + LARGE_INTEGER Offset; + extern PSECTION_OBJECT GlobalUserHeapSection; + + /* HACK: This needs to be handled during startup only... */ + ASSERT(Base == (PVOID)GlobalUserHeap); + + /* temporarily map it into user space */ + Offset.QuadPart = 0; + Status = MmMapViewOfSection(GlobalUserHeapSection, + PsGetCurrentProcess(), + &UserBase, + 0, + 0, + &Offset, + &ViewSize, + ViewUnmap, + SEC_NO_CHANGE, + PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */ + + if (!NT_SUCCESS(Status)) + return Status; + } + + /* commit! */ + UserBase = (PVOID)((ULONG_PTR)UserBase + Delta); + + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), + &UserBase, + 0, + CommitSize, + MEM_COMMIT, + PAGE_EXECUTE_READ); + if (NT_SUCCESS(Status)) + { + *CommitAddress = (PVOID)((ULONG_PTR)UserBase + Delta); + } + + if (W32Process == NULL) + { + MmUnmapViewOfSection(PsGetCurrentProcess(), + UserBase); + } + + return Status; +} + +static HANDLE +IntUserHeapCreate(IN PSECTION_OBJECT SectionObject, + IN PVOID *SystemMappedBase, + IN ULONG HeapSize) +{ + PVOID MappedView = NULL; + LARGE_INTEGER Offset; + ULONG ViewSize = PAGE_SIZE; + RTL_HEAP_PARAMETERS Parameters = {0}; + HANDLE hHeap; + NTSTATUS Status; + + Offset.QuadPart = 0; + + /* Commit the first page before creating the heap! */ + Status = MmMapViewOfSection(SectionObject, + PsGetCurrentProcess(), + &MappedView, + 0, + 0, + &Offset, + &ViewSize, + ViewUnmap, + SEC_NO_CHANGE, + PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */ + if (!NT_SUCCESS(Status)) + return NULL; + + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), + &MappedView, + 0, + &ViewSize, + MEM_COMMIT, + PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */ + + MmUnmapViewOfSection(PsGetCurrentProcess(), + MappedView); + + if (!NT_SUCCESS(Status)) + return NULL; + + /* Create the heap, don't serialize in kmode! The caller is responsible + to synchronize the heap! */ + Parameters.Length = sizeof(Parameters); + Parameters.InitialCommit = PAGE_SIZE; + Parameters.InitialReserve = (SIZE_T)HeapSize; + Parameters.CommitRoutine = IntUserHeapCommitRoutine; + + hHeap = RtlCreateHeap(HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE, + *SystemMappedBase, + (SIZE_T)HeapSize, + PAGE_SIZE, + NULL, + &Parameters); + + return hHeap; +} + +HANDLE +UserCreateHeap(OUT PSECTION_OBJECT *SectionObject, + IN OUT PVOID *SystemBase, + IN ULONG HeapSize) +{ + LARGE_INTEGER SizeHeap; + HANDLE hHeap = NULL; + NTSTATUS Status; + + SizeHeap.QuadPart = HeapSize; + + /* create the section and map it into session space */ + Status = MmCreateSection((PVOID*)SectionObject, + SECTION_ALL_ACCESS, + NULL, + &SizeHeap, + PAGE_EXECUTE_READWRITE, /* would prefer PAGE_READWRITE, but thanks to RTL heaps... */ + SEC_RESERVE, + NULL, + NULL); + + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return FALSE; + } + + Status = MmMapViewInSystemSpace(*SectionObject, + SystemBase, + &HeapSize); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(*SectionObject); + *SectionObject = NULL; + + SetLastNtError(Status); + return FALSE; + } + + /* create the heap */ + hHeap = IntUserHeapCreate(*SectionObject, + SystemBase, + HeapSize); + + if (hHeap == NULL) + { + ObDereferenceObject(*SectionObject); + *SectionObject = NULL; + + SetLastNtError(STATUS_UNSUCCESSFUL); + } + + return hHeap; +}
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/accelerator.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/accelerator.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/accelerator.c Wed Apr 5 12:05:55 2006 @@ -80,7 +80,7 @@ return NULL; }
- Accel= UserGetObject(&gHandleTable, hAccel, otAccel); + Accel= UserGetObject(gHandleTable, hAccel, otAccel); if (!Accel) { SetLastWin32Error(ERROR_INVALID_ACCEL_HANDLE); @@ -344,7 +344,7 @@ Entries, EntriesCount); UserEnterExclusive();
- Accel = ObmCreateObject(&gHandleTable, (PHANDLE)&hAccel, otAccel, sizeof(ACCELERATOR_TABLE)); + Accel = ObmCreateObject(gHandleTable, (PHANDLE)&hAccel, otAccel, sizeof(ACCELERATOR_TABLE));
if (Accel == NULL) {
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/class.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/class.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/class.c Wed Apr 5 12:05:55 2006 @@ -1,6 +1,6 @@ /* * ReactOS W32 Subsystem - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team + * Copyright (C) 1998 - 2006 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,9 +22,12 @@ * PROJECT: ReactOS kernel * PURPOSE: Window classes * FILE: subsys/win32k/ntuser/class.c - * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * PROGRAMER: Thomas Weidenmueller w3seek@reactos.com * REVISION HISTORY: * 06-06-2001 CSH Created + * + * NOTE: Should classes created on a desktop heap be moved to the shared + * heap when the desktop is destroyed, or should they be unregistered? */ /* INCLUDES ******************************************************************/
@@ -33,7 +36,96 @@ #define NDEBUG #include <debug.h>
-/* FUNCTIONS *****************************************************************/ +/* CALLPROC ******************************************************************/ + +VOID +DestroyCallProc(IN PDESKTOP Desktop, + IN OUT PCALLPROC CallProc) +{ + /* FIXME - use new object manager! */ + HANDLE Handle = ObmObjectToHandle(CallProc); + + ObmDeleteObject(Handle, + otCallProc); +} + +PCALLPROC +CloneCallProc(IN PDESKTOP Desktop, + IN PCALLPROC CallProc) +{ + PCALLPROC NewCallProc; + HANDLE Handle; + + /* FIXME - use new object manager! */ + NewCallProc = (PCALLPROC)ObmCreateObject(gHandleTable, + &Handle, + otCallProc, + sizeof(CALLPROC)); + if (NewCallProc != NULL) + { + NewCallProc->pi = CallProc->pi; + NewCallProc->WndProc = CallProc->WndProc; + NewCallProc->Unicode = CallProc->Unicode; + } + + return NewCallProc; +} + +PCALLPROC +CreateCallProc(IN PDESKTOP Desktop, + IN WNDPROC WndProc, + IN BOOL Unicode, + IN PW32PROCESSINFO pi) +{ + PCALLPROC NewCallProc; + HANDLE Handle; + + /* FIXME - use new object manager! */ + NewCallProc = (PCALLPROC)ObmCreateObject(gHandleTable, + &Handle, + otCallProc, + sizeof(CALLPROC)); + if (NewCallProc != NULL) + { + NewCallProc->pi = pi; + NewCallProc->WndProc = WndProc; + NewCallProc->Unicode = Unicode; + } + + return NewCallProc; +} + +BOOL +UserGetCallProcInfo(IN HANDLE hCallProc, + OUT PWNDPROC_INFO wpInfo) +{ + PCALLPROC CallProc; + + /* NOTE: Accessing the WNDPROC_INFO structure may raise an exception! */ + + /* FIXME - use new object manager! */ + CallProc = UserGetObject(gHandleTable, + hCallProc, + otCallProc); + if (CallProc == NULL) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (CallProc->pi != GetW32ProcessInfo()) + { + SetLastWin32Error(ERROR_ACCESS_DENIED); + return FALSE; + } + + wpInfo->WindowProc = CallProc->WndProc; + wpInfo->IsUnicode = CallProc->Unicode; + + return TRUE; +} + +/* WINDOWCLASS ***************************************************************/
NTSTATUS FASTCALL InitClassImpl(VOID) @@ -47,398 +139,1673 @@ return(STATUS_SUCCESS); }
- -__inline VOID FASTCALL -ClassDerefObject(PWNDCLASS_OBJECT Class) -{ - ASSERT(Class->refs >= 1); - Class->refs--; -} - - -__inline VOID FASTCALL -ClassRefObject(PWNDCLASS_OBJECT Class) -{ - ASSERT(Class->refs >= 0); - Class->refs++; -} - - -VOID FASTCALL DestroyClass(PWNDCLASS_OBJECT Class) -{ -#if defined(DBG) || defined(KDBG) - if ( Class->refs != 0 ) - { - WCHAR AtomName[256]; - ULONG AtomNameLen = sizeof(AtomName); - RtlQueryAtomInAtomTable ( gAtomTable, Class->Atom, - NULL, NULL, AtomName, &AtomNameLen ); - DPRINT1("DestroyClass(): can't delete class = '%ws', b/c refs = %lu\n", AtomName, Class->refs ); - } -#endif - ASSERT(Class->refs == 0); - - RemoveEntryList(&Class->ListEntry); - if (Class->hMenu) - UserDestroyMenu(Class->hMenu); - RtlDeleteAtomFromAtomTable(gAtomTable, Class->Atom); - ExFreePool(Class); +static VOID +IntFreeClassMenuName(IN OUT PWINDOWCLASS Class) +{ + /* free the menu name, if it was changed and allocated */ + if (Class->MenuName != NULL && !IS_INTRESOURCE(Class->MenuName) && + Class->MenuName != (PWSTR)(Class + 1)) + { + UserHeapFree(Class->MenuName); + Class->MenuName = NULL; + Class->AnsiMenuName = NULL; + } +} + +static VOID +IntDestroyClass(IN OUT PWINDOWCLASS Class) +{ + /* there shouldn't be any clones anymore */ + + ASSERT(Class->Windows == 0); + + if (Class->Desktop != NULL) + { + ASSERT(Class->Clone == NULL); + } + else if (Class->Clone != NULL) + { + /* there must not be more than one clone! This can be the case + when the base class is on the shared heap */ + ASSERT(Class->Clone->Next == NULL); + + /* free the clone */ + IntDestroyClass(Class->Clone); + Class->Clone = NULL; + } + + if (Class->Base == Class) + { + /* destruct resources shared with clones */ + if (!Class->System && Class->CallProc != NULL) + { + DestroyCallProc(Class->Desktop, + Class->CallProc); + } + + IntFreeClassMenuName(Class); + } + + /* free the structure */ + if (Class->Desktop != NULL) + { + DesktopHeapFree(Class->Desktop, + Class); + } + else + { + UserHeapFree(Class); + } }
/* clean all process classes. all process windows must cleaned first!! */ void FASTCALL DestroyProcessClasses(PW32PROCESS Process ) { - PWNDCLASS_OBJECT Class; - - while (!IsListEmpty(&Process->ClassList)) - { - Class = CONTAINING_RECORD(RemoveHeadList(&Process->ClassList), WNDCLASS_OBJECT, ListEntry); - DestroyClass(Class); - } -} - - - - -PWNDCLASS_OBJECT FASTCALL -ClassGetClassByAtom(RTL_ATOM Atom, HINSTANCE hInstance) -{ - PWNDCLASS_OBJECT Class; - PW32PROCESS Process = PsGetWin32Process(); - - LIST_FOR_EACH(Class, &Process->ClassList, WNDCLASS_OBJECT, ListEntry) - { - if (Class->Atom != Atom) continue; - - if (!hInstance || Class->Global || Class->hInstance == hInstance) return Class; - } - - return NULL; -} - - -PWNDCLASS_OBJECT FASTCALL -ClassGetClassByName(LPCWSTR ClassName, HINSTANCE hInstance) -{ - NTSTATUS Status; - RTL_ATOM Atom; - - if (!ClassName || !PsGetWin32Thread()->Desktop) - return FALSE; - - Status = RtlLookupAtomInAtomTable( - gAtomTable, - (LPWSTR)ClassName, - &Atom); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to lookup class atom (ClassName '%S')!\n", ClassName); - return FALSE; - } - - return ClassGetClassByAtom(Atom, hInstance); -} - - -PWNDCLASS_OBJECT FASTCALL -ClassGetClassByNameOrAtom(LPCWSTR ClassNameOrAtom, HINSTANCE hInstance) -{ - if (!ClassNameOrAtom) return NULL; - - if (IS_ATOM(ClassNameOrAtom)) - return ClassGetClassByAtom((RTL_ATOM)((ULONG_PTR)ClassNameOrAtom), hInstance); - else - return ClassGetClassByName(ClassNameOrAtom, hInstance); -} - - -static -BOOL FASTCALL -IntRegisterClass( - CONST WNDCLASSEXW *lpwcx, - DWORD Flags, - WNDPROC wpExtra, - PUNICODE_STRING MenuName, - RTL_ATOM Atom, - HMENU hMenu) -{ - PWNDCLASS_OBJECT Class; - ULONG objectSize; - BOOL Global; - - ASSERT(lpwcx); - ASSERT(Atom); - ASSERT(lpwcx->hInstance); - - Global = (Flags & REGISTERCLASS_SYSTEM) || (lpwcx->style & CS_GLOBALCLASS); - - /* Check for double registration of the class. */ - Class = ClassGetClassByAtom(Atom, lpwcx->hInstance); - if (Class && Global == Class->Global) - { - /* can max have one class of each type (global/local) */ - SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS); - return(FALSE); - } - - objectSize = sizeof(WNDCLASS_OBJECT) + lpwcx->cbClsExtra; - - //FIXME: allocate in session heap (or possibly desktop heap) - Class = ExAllocatePool(PagedPool, objectSize); - if (!Class) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return(FALSE); - } - RtlZeroMemory(Class, objectSize); - - Class->cbSize = lpwcx->cbSize; - Class->style = lpwcx->style; - Class->cbClsExtra = lpwcx->cbClsExtra; - Class->cbWndExtra = lpwcx->cbWndExtra; - Class->hInstance = lpwcx->hInstance; - Class->hIcon = lpwcx->hIcon; - Class->hCursor = lpwcx->hCursor; - Class->hMenu = hMenu; - Class->hbrBackground = lpwcx->hbrBackground; - Class->Unicode = !(Flags & REGISTERCLASS_ANSI); - Class->Global = Global; - Class->hIconSm = lpwcx->hIconSm; - Class->Atom = Atom; - - if (MenuName->Length == 0) - { - Class->lpszMenuName.Length = - Class->lpszMenuName.MaximumLength = 0; - Class->lpszMenuName.Buffer = MenuName->Buffer; - } - else - { - Class->lpszMenuName.Length = - Class->lpszMenuName.MaximumLength = MenuName->MaximumLength; - Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Class->lpszMenuName.MaximumLength, TAG_STRING); - - if (Class->lpszMenuName.Buffer == NULL) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return(FALSE); - } - - RtlCopyUnicodeString(&Class->lpszMenuName, MenuName); - } - - if (wpExtra == NULL) - { - if (Flags & REGISTERCLASS_ANSI) - { - Class->lpfnWndProcA = lpwcx->lpfnWndProc; - Class->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE); - } - else - { - Class->lpfnWndProcW = lpwcx->lpfnWndProc; - Class->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE); - } - } - else - { - if (Flags & REGISTERCLASS_ANSI) - { - Class->lpfnWndProcA = lpwcx->lpfnWndProc; - Class->lpfnWndProcW = wpExtra; - } - else - { - Class->lpfnWndProcW = lpwcx->lpfnWndProc; - Class->lpfnWndProcA = wpExtra; - } - } - - - - /* Extra class data */ - if (Class->cbClsExtra) - Class->ExtraData = (PCHAR)(Class + 1); - - if (Global) - { - /* global classes go last (incl. system classes) */ - InsertTailList(&PsGetWin32Process()->ClassList, &Class->ListEntry); - } - else - { - /* local classes have priority so we put them first */ - InsertHeadList(&PsGetWin32Process()->ClassList, &Class->ListEntry); - } - - return TRUE; -} - - -ULONG FASTCALL -IntGetClassLong(PWINDOW_OBJECT Window, ULONG Offset, BOOL Ansi) -{ - LONG Ret; - - if ((int)Offset >= 0) - { - DPRINT("GetClassLong(%x, %d)\n", Window->hSelf, Offset); - if ((Offset + sizeof(LONG)) > Window->Class->cbClsExtra) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return 0; - } - Ret = *((LONG *)(Window->Class->ExtraData + Offset)); - DPRINT("Result: %x\n", Ret); - return Ret; - } - - switch (Offset) - { - case GCL_CBWNDEXTRA: - Ret = Window->Class->cbWndExtra; - break; - case GCL_CBCLSEXTRA: - Ret = Window->Class->cbClsExtra; - break; - case GCL_HBRBACKGROUND: - Ret = (ULONG)Window->Class->hbrBackground; - break; - case GCL_HCURSOR: - Ret = (ULONG)Window->Class->hCursor; - break; - case GCL_HICON: - Ret = (ULONG)Window->Class->hIcon; - break; - case GCL_HICONSM: - Ret = (ULONG)Window->Class->hIconSm; - break; - case GCL_HMODULE: - Ret = (ULONG)Window->Class->hInstance; - break; - case GCL_MENUNAME: - Ret = (ULONG)Window->Class->lpszMenuName.Buffer; - break; - case GCL_STYLE: - Ret = Window->Class->style; - break; - case GCL_WNDPROC: - if (Ansi) - { - Ret = (ULONG)Window->Class->lpfnWndProcA; - } - else - { - Ret = (ULONG)Window->Class->lpfnWndProcW; - } - break; - case GCW_ATOM: - Ret = Window->Class->Atom; - break; - default: - Ret = 0; - break; - } - return(Ret); -} - -static -void FASTCALL -co_IntSetClassLong(PWINDOW_OBJECT Window, ULONG Offset, LONG dwNewLong, BOOL Ansi) -{ - ASSERT_REFS_CO(Window); - - if ((int)Offset >= 0) - { - DPRINT("SetClassLong(%x, %d, %x)\n", Window->hSelf, Offset, dwNewLong); - if ((Offset + sizeof(LONG)) > Window->Class->cbClsExtra) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return; - } - *((LONG *)(Window->Class->ExtraData + Offset)) = dwNewLong; - return; - } - - switch (Offset) - { - case GCL_CBWNDEXTRA: - Window->Class->cbWndExtra = dwNewLong; - break; - case GCL_CBCLSEXTRA: - Window->Class->cbClsExtra = dwNewLong; - break; - case GCL_HBRBACKGROUND: - Window->Class->hbrBackground = (HBRUSH)dwNewLong; - break; - case GCL_HCURSOR: - Window->Class->hCursor = (HCURSOR)dwNewLong; - break; - case GCL_HICON: - Window->Class->hIcon = (HICON)dwNewLong; - - if (!IntGetOwner(Window) && !IntGetParent(Window)) - { - co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) Window->hSelf); - } - break; - case GCL_HICONSM: - Window->Class->hIconSm = (HICON)dwNewLong; - break; - case GCL_HMODULE: - Window->Class->hInstance = (HINSTANCE)dwNewLong; - break; - case GCL_MENUNAME: - if (Window->Class->lpszMenuName.MaximumLength) - RtlFreeUnicodeString(&Window->Class->lpszMenuName); - if (!IS_INTRESOURCE(dwNewLong)) - { - Window->Class->lpszMenuName.Length = - Window->Class->lpszMenuName.MaximumLength = ((PUNICODE_STRING)dwNewLong)->MaximumLength; - Window->Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Window->Class->lpszMenuName.MaximumLength, TAG_STRING); - RtlCopyUnicodeString(&Window->Class->lpszMenuName, (PUNICODE_STRING)dwNewLong); - } - else - { - Window->Class->lpszMenuName.Length = - Window->Class->lpszMenuName.MaximumLength = 0; - Window->Class->lpszMenuName.Buffer = (LPWSTR)dwNewLong; - } - break; - case GCL_STYLE: - Window->Class->style = dwNewLong; - break; - case GCL_WNDPROC: - if (Ansi) - { - Window->Class->lpfnWndProcA = (WNDPROC)dwNewLong; - Window->Class->lpfnWndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,FALSE); - Window->Class->Unicode = FALSE; - } - else - { - Window->Class->lpfnWndProcW = (WNDPROC)dwNewLong; - Window->Class->lpfnWndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,TRUE); - Window->Class->Unicode = TRUE; - } - break; - } -} + PWINDOWCLASS Class; + PW32PROCESSINFO pi = Process->ProcessInfo; + + if (pi != NULL) + { + /* free all local classes */ + Class = pi->LocalClassList; + while (Class != NULL) + { + pi->LocalClassList = Class->Next; + + ASSERT(Class->Base == Class); + IntDestroyClass(Class); + + Class = pi->LocalClassList; + } + + /* free all global classes */ + Class = pi->GlobalClassList; + while (Class != NULL) + { + pi->GlobalClassList = Class->Next; + + ASSERT(Class->Base == Class); + IntDestroyClass(Class); + + Class = pi->GlobalClassList; + } + + /* free all system classes */ + Class = pi->SystemClassList; + while (Class != NULL) + { + pi->SystemClassList = Class->Next; + + ASSERT(Class->Base == Class); + IntDestroyClass(Class); + + Class = pi->SystemClassList; + } + } +} + +static BOOL +IntRegisterClassAtom(IN PUNICODE_STRING ClassName, + OUT RTL_ATOM *pAtom) +{ + WCHAR szBuf[65]; + PWSTR AtomName; + NTSTATUS Status; + + if (ClassName->Length != 0) + { + /* FIXME - Don't limit to 64 characters! use SEH when allocating memory! */ + if (ClassName->Length / sizeof(WCHAR) >= sizeof(szBuf) / sizeof(szBuf[0])) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return (RTL_ATOM)0; + } + + RtlCopyMemory(szBuf, + ClassName->Buffer, + ClassName->Length); + szBuf[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL; + AtomName = szBuf; + } + else + AtomName = ClassName->Buffer; + + Status = RtlAddAtomToAtomTable(gAtomTable, + AtomName, + pAtom); + + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return FALSE; + } + + return TRUE; +} + +static VOID +IntDeregisterClassAtom(IN RTL_ATOM Atom) +{ + RtlDeleteAtomFromAtomTable(gAtomTable, + Atom); +} + +static BOOL +IntSetClassAtom(IN OUT PWINDOWCLASS Class, + IN PUNICODE_STRING ClassName) +{ + RTL_ATOM Atom = (RTL_ATOM)0; + + /* update the base class first */ + Class = Class->Base; + + if (!IntRegisterClassAtom(ClassName, + &Atom)) + { + return FALSE; + } + + IntDeregisterClassAtom(Class->Atom); + + Class->Atom = Atom; + + /* update the clones */ + Class = Class->Clone; + while (Class != NULL) + { + Class->Atom = Atom; + + Class = Class->Next; + } + + return TRUE; +} + +static WNDPROC +IntSetClassWndProc(IN OUT PWINDOWCLASS Class, + IN WNDPROC WndProc, + IN BOOL Ansi) +{ + WNDPROC Ret = Class->WndProc; + + if (Class->System) + { + DPRINT1("Attempted to change window procedure of system window class 0x%p!\n", Class->Atom); + SetLastWin32Error(ERROR_ACCESS_DENIED); + return NULL; + } + + /* update the base class first */ + Class = Class->Base; + + Class->Unicode = !Ansi; + Class->WndProc = WndProc; + if (Class->CallProc != NULL) + { + Class->CallProc->WndProc = WndProc; + Class->CallProc->Unicode = !Ansi; + } + + /* update the clones */ + Class = Class->Clone; + while (Class != NULL) + { + Class->Unicode = !Ansi; + Class->WndProc = WndProc; + + Class = Class->Next; + } + + return Ret; +} + +static PWINDOWCLASS +IntGetClassForDesktop(IN PWINDOWCLASS BaseClass, + IN PDESKTOP Desktop) +{ + SIZE_T ClassSize; + PWINDOWCLASS Class; + + ASSERT(Desktop != NULL); + ASSERT(BaseClass->Base == BaseClass); + + if (BaseClass->Desktop == Desktop) + { + /* it is most likely that a window is created on the same + desktop as the window class. */ + + return BaseClass; + } + + if (BaseClass->Desktop == NULL) + { + /* Classes are also located in the shared heap when the class + was created before the thread attached to a desktop. As soon + as a window is created for such a class located on the shared + heap, the class is cloned into the desktop heap on which the + window is created. */ + Class = NULL; + } + else + { + /* The user is asking for a class object on a different desktop, + try to find one! */ + Class = BaseClass->Clone; + while (Class != NULL) + { + if (Class->Desktop == Desktop) + { + ASSERT(Class->Base == BaseClass); + ASSERT(Class->Clone == NULL); + break; + } + + Class = Class->Next; + } + } + + if (Class == NULL) + { + /* The window is created on a different desktop, we need to + clone the class object to the desktop heap of the window! */ + ClassSize = (SIZE_T)BaseClass->ClassExtraDataOffset + + (SIZE_T)BaseClass->ClsExtra; + + Class = DesktopHeapAlloc(Desktop, + ClassSize); + if (Class != NULL) + { + /* simply clone the class */ + RtlCopyMemory(Class, + BaseClass, + ClassSize); + + /* update some pointers and link the class */ + Class->Next = BaseClass->Clone; + Class->Clone = NULL; + Class->Base = BaseClass; + Class->Desktop = Desktop; + Class->Windows = 0; + (void)InterlockedExchangePointer(&BaseClass->Clone, + Class); + } + else + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + } + } + + return Class; +} + +PWINDOWCLASS +IntReferenceClass(IN PWINDOWCLASS BaseClass, + IN PDESKTOP Desktop) +{ + PWINDOWCLASS Class; + + Class = IntGetClassForDesktop(BaseClass, + Desktop); + if (Class != NULL) + { + Class->Windows++; + } + + return Class; +} + +VOID +IntDereferenceClass(IN OUT PWINDOWCLASS Class, + IN PDESKTOP Desktop, + IN PW32PROCESSINFO pi) +{ + PWINDOWCLASS *PrevLink, BaseClass, CurrentClass; + + BaseClass = Class->Base; + + if (--Class->Windows == 0) + { + if (BaseClass == Class) + { + ASSERT(Class->Base == Class); + + /* check if there are clones of the class on other desktops, + link the first clone in if possible. If there are no clones + then leave the class on the desktop heap... */ + if (BaseClass->Clone != NULL) + { + PWINDOWCLASS NewBase = BaseClass->Clone; + + /* locate the base class and unlink it */ + if (BaseClass->System) + PrevLink = &pi->SystemClassList; + else if (BaseClass->Global) + PrevLink = &pi->GlobalClassList; + else + PrevLink = &pi->LocalClassList; + + CurrentClass = *PrevLink; + while (CurrentClass != BaseClass) + { + ASSERT(CurrentClass != NULL); + + PrevLink = &CurrentClass->Next; + CurrentClass = CurrentClass->Next; + } + + ASSERT(CurrentClass == BaseClass); + + NewBase->Clone = NewBase->Next; + NewBase->Next = BaseClass->Next; + NewBase->Base = NewBase; + + /* update all clones */ + CurrentClass = NewBase->Clone; + while (CurrentClass != NULL) + { + ASSERT(CurrentClass->Clone == NULL); + + CurrentClass->Base = NewBase; + + CurrentClass = CurrentClass->Next; + } + + /* link in the new base class */ + (void)InterlockedExchangePointer(PrevLink, + NewBase); + + /* destroy the class, there's still another clone of the class + that now serves as a base class. Make sure we don't destruct + resources shared by all classes (Base = NULL)! */ + BaseClass->Base = NULL; + BaseClass->Clone = NULL; + IntDestroyClass(BaseClass); + } + } + else + { + /* locate the cloned class and unlink it */ + PrevLink = &BaseClass->Clone; + CurrentClass = BaseClass->Clone; + while (CurrentClass != Class) + { + ASSERT(CurrentClass != NULL); + + PrevLink = &CurrentClass->Next; + CurrentClass = CurrentClass->Next; + } + + ASSERT(CurrentClass == Class); + + (void)InterlockedExchangePointer(PrevLink, + Class->Next); + + ASSERT(Class->Base == BaseClass); + ASSERT(Class->Clone == NULL); + + /* the class was just a clone, we don't need it anymore */ + IntDestroyClass(Class); + } + } +} + +static PWINDOWCLASS +IntCreateClass(IN CONST WNDCLASSEXW* lpwcx, + IN PUNICODE_STRING ClassName, + IN PUNICODE_STRING MenuName, + IN WNDPROC wpExtra, + IN DWORD dwFlags, + IN PDESKTOP Desktop, + IN PW32PROCESSINFO pi) +{ + SIZE_T ClassSize; + PWINDOWCLASS Class = NULL; + RTL_ATOM Atom; + NTSTATUS Status = STATUS_SUCCESS; + + if (!IntRegisterClassAtom(ClassName, + &Atom)) + { + DPRINT1("Failed to register class atom!\n"); + return NULL; + } + + ClassSize = sizeof(WINDOWCLASS) + lpwcx->cbClsExtra; + ClassSize += ClassName->Length + sizeof(UNICODE_NULL); + ClassSize += MenuName->Length + sizeof(UNICODE_NULL); + if (ClassName->Length != 0) + ClassSize += RtlUnicodeStringToAnsiSize(ClassName); + if (MenuName->Length != 0) + ClassSize += RtlUnicodeStringToAnsiSize(MenuName); + + if (Desktop != NULL) + { + Class = DesktopHeapAlloc(Desktop, + ClassSize); + } + else + { + /* FIXME - the class was created before being connected + to a desktop. It is possible for the desktop window, + but should it be allowed for any other case? */ + Class = UserHeapAlloc(ClassSize); + } + + if (Class != NULL) + { + RtlZeroMemory(Class, + sizeof(ClassSize)); + + Class->Desktop = Desktop; + Class->Base = Class; + Class->Atom = Atom; + + if (dwFlags & REGISTERCLASS_SYSTEM) + { + dwFlags &= ~REGISTERCLASS_ANSI; + Class->WndProcExtra = wpExtra; + Class->System = TRUE; + } + + _SEH_TRY + { + PWSTR strBuf; + PSTR strBufA; + ANSI_STRING AnsiString; + + /* need to protect with SEH since accessing the WNDCLASSEX structure + and string buffers might raise an exception! We don't want to + leak memory... */ + Class->WndProc = lpwcx->lpfnWndProc; + Class->Style = lpwcx->style; + Class->ClsExtra = lpwcx->cbClsExtra; + Class->WndExtra = lpwcx->cbWndExtra; + Class->hInstance = lpwcx->hInstance; + Class->hIcon = lpwcx->hIcon; /* FIXME */ + Class->hIconSm = lpwcx->hIconSm; /* FIXME */ + Class->hCursor = lpwcx->hCursor; /* FIXME */ + Class->hbrBackground = lpwcx->hbrBackground; + + /* make a copy of the string */ + strBuf = (PWSTR)(Class + 1); + if (MenuName->Length != 0) + { + Class->MenuName = strBuf; + RtlCopyMemory(Class->MenuName, + MenuName->Buffer, + MenuName->Length); + + strBuf += (MenuName->Length / sizeof(WCHAR)) + 1; + } + else + Class->MenuName = MenuName->Buffer; + + /* save an ansi copy of the string */ + strBufA = (PSTR)strBuf; + if (MenuName->Length != 0) + { + Class->AnsiMenuName = strBufA; + AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(MenuName); + AnsiString.Buffer = strBufA; + Status = RtlUnicodeStringToAnsiString(&AnsiString, + MenuName, + FALSE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to convert unicode menu name to ansi!\n"); + + /* life would've been much prettier if ntoskrnl exported RtlRaiseStatus()... */ + _SEH_LEAVE; + } + + strBufA += AnsiString.Length + 1; + } + else + Class->AnsiMenuName = (PSTR)MenuName->Buffer; + + /* calculate the offset of the extra data */ + Class->ClassExtraDataOffset = (ULONG_PTR)strBufA - (ULONG_PTR)Class; + + if (!(dwFlags & REGISTERCLASS_ANSI)) + Class->Unicode = TRUE; + + if (Class->Style & CS_GLOBALCLASS) + Class->Global = TRUE; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed creating the class: 0x%x\n", Status); + + SetLastNtError(Status); + + DesktopHeapFree(Desktop, + Class); + Class = NULL; + + IntDeregisterClassAtom(Atom); + } + } + else + { + DPRINT1("Failed to allocate class on Desktop 0x%p\n", Desktop); + + IntDeregisterClassAtom(Atom); + + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + } + + return Class; +} + +static PWINDOWCLASS +IntFindClass(IN RTL_ATOM Atom, + IN HINSTANCE hInstance, + IN PWINDOWCLASS *ClassList, + OUT PWINDOWCLASS **Link OPTIONAL) +{ + PWINDOWCLASS Class, *PrevLink = ClassList; + + Class = *PrevLink; + while (Class != NULL) + { + if (Class->Atom == Atom && + (hInstance == NULL || Class->hInstance == hInstance) && + !Class->Destroying) + { + ASSERT(Class->Base == Class); + + if (Link != NULL) + *Link = PrevLink; + break; + } + + PrevLink = &Class->Next; + Class = Class->Next; + } + + return Class; +} + +static WNDPROC +IntGetClassWndProc(IN PWINDOWCLASS Class, + IN PW32PROCESSINFO pi, + IN BOOL Ansi) +{ + if (Class->System) + { + return (Ansi ? Class->WndProcExtra : Class->WndProc); + } + else + { + if (!Ansi == Class->Unicode) + { + return Class->WndProc; + } + else + { + if (Class->CallProc != NULL) + { + return (WNDPROC)ObmObjectToHandle(Class->CallProc); + } + else + { + PCALLPROC NewCallProc, CallProc; + + if (pi == NULL) + return NULL; + + /* NOTE: use the interlocked functions, as this operation may be done even + when only the shared lock is held! */ + NewCallProc = CreateCallProc(Class->Desktop, + Class->WndProc, + Class->Unicode, + pi); + if (NewCallProc == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + CallProc = InterlockedCompareExchangePointer(&Class->CallProc, + NewCallProc, + NULL); + if (CallProc != NULL) + { + DestroyCallProc(Class->Desktop, + NewCallProc); + } + + return (WNDPROC)ObmObjectToHandle((CallProc == NULL ? NewCallProc : CallProc)); + } + } + } +} + +RTL_ATOM +IntGetClassAtom(IN PUNICODE_STRING ClassName, + IN HINSTANCE hInstance OPTIONAL, + IN PW32PROCESSINFO pi OPTIONAL, + OUT PWINDOWCLASS *BaseClass OPTIONAL, + OUT PWINDOWCLASS **Link OPTIONAL) +{ + RTL_ATOM Atom = (RTL_ATOM)0; + + if (ClassName->Length != 0) + { + WCHAR szBuf[65]; + PWSTR AtomName; + NTSTATUS Status; + + /* NOTE: Caller has to protect the call with SEH! */ + + if (ClassName->Length != 0) + { + /* FIXME - Don't limit to 64 characters! use SEH when allocating memory! */ + if (ClassName->Length / sizeof(WCHAR) >= sizeof(szBuf) / sizeof(szBuf[0])) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return (RTL_ATOM)0; + } + + /* We need to make a local copy of the class name! The caller could + modify the buffer and we could overflow in RtlLookupAtomInAtomTable. + We're protected by SEH, but the ranges that might be accessed were + not probed... */ + RtlCopyMemory(szBuf, + ClassName->Buffer, + ClassName->Length); + szBuf[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL; + AtomName = szBuf; + } + else + AtomName = ClassName->Buffer; + + /* lookup the atom */ + Status = RtlLookupAtomInAtomTable(gAtomTable, + AtomName, + &Atom); + if (!NT_SUCCESS(Status)) + { + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS); + } + else + { + SetLastNtError(Status); + } + } + } + else + { + ASSERT(IS_ATOM(ClassName->Buffer)); + Atom = (RTL_ATOM)((ULONG_PTR)ClassName->Buffer); + } + + if (BaseClass != NULL && Atom != (RTL_ATOM)0) + { + PWINDOWCLASS Class; + + /* attempt to locate the class object */ + + ASSERT(pi != NULL); + + /* Step 1: try to find an exact match of locally registered classes */ + Class = IntFindClass(Atom, + hInstance, + &pi->LocalClassList, + Link); + if (Class != NULL) + { + goto FoundClass; + } + + /* Step 2: try to find any globally registered class. The hInstance + is not relevant for global classes */ + Class = IntFindClass(Atom, + NULL, + &pi->GlobalClassList, + Link); + if (Class != NULL) + { + goto FoundClass; + } + + /* Step 3: try to find a system class */ + Class = IntFindClass(Atom, + NULL, + &pi->SystemClassList, + Link); + + if (Class == NULL) + { + SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); + return (RTL_ATOM)0; + } + +FoundClass: + *BaseClass = Class; + } + + return Atom; +} + +static PWINDOWCLASS +IntClassResizeInternal(IN OUT PWINDOWCLASS Class, + IN INT ClsExtraNew, + IN PWINDOWCLASS *List) +{ + PWINDOWCLASS *PrevLink, CurrentClass, NewClass; + SIZE_T NewSize; + + /* temporarily unlink the class, as resizing it may change it's location */ + PrevLink = List; + CurrentClass = *PrevLink; + while (CurrentClass != Class) + { + ASSERT(CurrentClass != NULL); + + PrevLink = &CurrentClass->Next; + CurrentClass = CurrentClass->Next; + } + + ASSERT(CurrentClass == Class); + + (void)InterlockedExchangePointer(PrevLink, + Class->Next); + + NewSize = (SIZE_T)ClsExtraNew + Class->ClassExtraDataOffset; + if (Class->Desktop != NULL) + { + NewClass = DesktopHeapReAlloc(Class->Desktop, + Class, + NewSize); + } + else + { + NewClass = UserHeapReAlloc(Class, + NewSize); + } + + if (NewClass == NULL) + { + /* link in the class again */ + (void)InterlockedExchangePointer(PrevLink, + Class); + + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + if (Class != NewClass) + { + /* adjust the menu name pointers, if neccessary */ + if (NewClass->MenuName != NULL && !IS_INTRESOURCE(NewClass->MenuName) && + NewClass->MenuName == (PWSTR)(NewClass + 1)) + { + ULONG_PTR PtrDelta = (ULONG_PTR)NewClass - (ULONG_PTR)Class; + + NewClass->MenuName = (PWSTR)((ULONG_PTR)NewClass->MenuName + PtrDelta); + NewClass->AnsiMenuName = (PSTR)((ULONG_PTR)NewClass->MenuName + PtrDelta); + } + + Class = NewClass; + } + + if (Class->ClsExtra < ClsExtraNew) + { + /* zero the memory allocated */ + RtlZeroMemory((PVOID)((ULONG_PTR)Class + Class->ClassExtraDataOffset + Class->ClsExtra), + ClsExtraNew - Class->ClsExtra); + } + + /* link in the class again */ + (void)InterlockedExchangePointer(PrevLink, + Class); + + return Class; +} + +static BOOL +IntClassResize(IN OUT PWINDOWCLASS Class, + IN PW32PROCESSINFO pi, + IN INT ClsExtraNew) +{ + PWINDOWCLASS *List, *CloneList, NewClass, Clone, FailedResize = NULL; + BOOL FailOnResize; + + if (pi == NULL) + return FALSE; + + /* first modify the base class, then the clones */ + Class = Class->Base; + + if (ClsExtraNew < 0 || + (ULONG_PTR)ClsExtraNew + Class->ClassExtraDataOffset < Class->ClassExtraDataOffset) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (Class->System) + List = &pi->SystemClassList; + else if (Class->Global) + List = &pi->GlobalClassList; + else + List = &pi->LocalClassList; + + FailOnResize = Class->ClsExtra < ClsExtraNew; + + /* resize the base class */ + NewClass = IntClassResizeInternal(Class, + ClsExtraNew, + List); + if (NewClass == NULL) + { + if (FailOnResize) + { + DPRINT1("Failed to resize the base class\n"); + return FALSE; + } + } + else + Class = NewClass; + + /* resize the clones */ + CloneList = &Class->Clone; + Clone = Class->Clone; + while (Clone != NULL) + { + NewClass = IntClassResizeInternal(Clone, + ClsExtraNew, + CloneList); + + if (NewClass == NULL) + { + if (FailOnResize) + { + /* roll back all changes */ + FailedResize = Clone; + break; + } + } + else + Clone = NewClass; + + /* save the pointer to the base class in case it changed */ + Clone->Base = Class; + + Clone = Clone->Next; + } + + if (FailedResize != NULL) + { + /* failed to resize one clone, roll back the changes to all + other clones and to the base class */ + DPRINT1("Failed to resize the cloned class 0x%p\n", FailedResize); + + /* roll back the changes made to the base class */ + NewClass = IntClassResizeInternal(Class, + Class->ClsExtra, + List); + if (NewClass != NULL) + Class = NewClass; + + /* roll back all changes made to the class clones */ + CloneList = &Class->Clone; + Clone = Class->Clone; + while (Clone != FailedResize) + { + ASSERT(Clone != NULL); + + NewClass = IntClassResizeInternal(Clone, + Class->ClsExtra, + CloneList); + if (NewClass != NULL) + Clone = NewClass; + + /* save the pointer to the base class in case it changed */ + Clone->Base = Class; + + CloneList = &Clone->Next; + Clone = Clone->Next; + } + + return FALSE; + } + else + { + /* all classes were successfully resized, + save the new extra data size */ + Class->ClsExtra = ClsExtraNew; + Clone = Class->Clone; + while (Clone != NULL) + { + Clone->ClsExtra = ClsExtraNew; + Clone = Clone->Next; + } + + return TRUE; + } +} + +RTL_ATOM +UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx, + IN PUNICODE_STRING ClassName, + IN PUNICODE_STRING MenuName, + IN HANDLE hMenu, /* FIXME */ + IN WNDPROC wpExtra, + IN DWORD dwFlags) +{ + PW32THREADINFO ti; + PW32PROCESSINFO pi; + PWINDOWCLASS Class; + RTL_ATOM ClassAtom; + RTL_ATOM Ret = (RTL_ATOM)0; + + /* NOTE: Accessing the buffers in ClassName and MenuName may raise exceptions! */ + + ti = GetW32ThreadInfo(); + if (ti == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return (RTL_ATOM)0; + } + + pi = ti->kpi; + + /* try to find a previously registered class */ + ClassAtom = IntGetClassAtom(ClassName, + NULL, + NULL, + NULL, + NULL); + if (ClassAtom != (RTL_ATOM)0) + { + Class = IntFindClass(ClassAtom, + lpwcx->hInstance, + &pi->LocalClassList, + NULL); + if (Class != NULL) + { + goto ClassAlreadyExists; + } + + /* if CS_GLOBALCLASS is set, try to find a previously registered global class. + Re-registering system classes as global classes seems to be allowed, + so we don't fail */ + if (lpwcx->style & CS_GLOBALCLASS) + { + Class = IntFindClass(ClassAtom, + NULL, + ((dwFlags & REGISTERCLASS_SYSTEM) ? + &pi->SystemClassList : &pi->GlobalClassList), + NULL); + if (Class != NULL) + { +ClassAlreadyExists: + DPRINT1("Class 0x%p does already exist!\n", ClassAtom); + SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS); + return (RTL_ATOM)0; + } + } + } + + ASSERT(ti->Desktop != NULL); + + Class = IntCreateClass(lpwcx, + ClassName, + MenuName, + wpExtra, + dwFlags, + ti->Desktop, + pi); + + if (Class != NULL) + { + PWINDOWCLASS *List; + + /* FIXME - pass the PMENU pointer to IntCreateClass instead! */ + Class->hMenu = hMenu; + + /* Register the class */ + if (Class->System) + List = &pi->SystemClassList; + else if (Class->Global) + List = &pi->GlobalClassList; + else + List = &pi->LocalClassList; + + Class->Next = *List; + (void)InterlockedExchangePointer(List, + Class); + + Ret = Class->Atom; + } + + return Ret; +} + +BOOL +UserUnregisterClass(IN PUNICODE_STRING ClassName, + IN HINSTANCE hInstance) +{ + PWINDOWCLASS *Link; + PW32PROCESSINFO pi; + RTL_ATOM ClassAtom; + PWINDOWCLASS Class; + + pi = GetW32ProcessInfo(); + if (pi == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* NOTE: Accessing the buffer in ClassName may raise an exception! */ + ClassAtom = IntGetClassAtom(ClassName, + hInstance, + pi, + &Class, + &Link); + if (ClassAtom == (RTL_ATOM)0) + { + return FALSE; + } + + ASSERT(Class != NULL); + + if (Class->System) + { + DPRINT1("Attempted to unregister system class 0x%p!\n", ClassAtom); + SetLastWin32Error(ERROR_ACCESS_DENIED); + return FALSE; + } + + if (Class->Windows != 0 || + Class->Clone != NULL) + { + SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS); + return FALSE; + } + + /* must be a base class! */ + ASSERT(Class->Base == Class); + + /* unlink the class */ + *Link = Class->Next; + + /* finally free the resources */ + IntDestroyClass(Class); + return TRUE; +} + +INT +UserGetClassName(IN PWINDOWCLASS Class, + IN OUT PUNICODE_STRING ClassName, + IN BOOL Ansi) +{ + NTSTATUS Status = STATUS_SUCCESS; + WCHAR szStaticTemp[32]; + PWSTR szTemp = NULL; + ULONG BufLen = sizeof(szStaticTemp); + INT Ret = 0; + + /* Note: Accessing the buffer in ClassName may raise an exception! */ + + _SEH_TRY + { + if (Ansi) + { + PANSI_STRING AnsiClassName = (PANSI_STRING)ClassName; + UNICODE_STRING UnicodeClassName; + + /* limit the size of the static buffer on the stack to the + size of the buffer provided by the caller */ + if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength) + { + BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR); + } + + /* find out how big the buffer needs to be */ + Status = RtlQueryAtomInAtomTable(gAtomTable, + Class->Atom, + NULL, + NULL, + szStaticTemp, + &BufLen); + if (Status == STATUS_BUFFER_TOO_SMALL) + { + if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength) + { + /* the buffer required exceeds the ansi buffer provided, + pretend like we're using the ansi buffer and limit the + size to the buffer size provided */ + BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR); + } + + /* allocate a temporary buffer that can hold the unicode class name */ + szTemp = ExAllocatePool(PagedPool, + BufLen); + if (szTemp == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + _SEH_LEAVE; + } + + /* query the class name */ + Status = RtlQueryAtomInAtomTable(gAtomTable, + Class->Atom, + NULL, + NULL, + szTemp, + &BufLen); + } + else + szTemp = szStaticTemp; + + if (NT_SUCCESS(Status)) + { + /* convert the atom name to ansi */ + + RtlInitUnicodeString(&UnicodeClassName, + szTemp); + + Status = RtlUnicodeStringToAnsiString(AnsiClassName, + &UnicodeClassName, + FALSE); + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + _SEH_LEAVE; + } + } + + Ret = BufLen / sizeof(WCHAR); + } + else /* !Ansi */ + { + BufLen = ClassName->MaximumLength; + + /* query the atom name */ + Status = RtlQueryAtomInAtomTable(gAtomTable, + Class->Atom, + NULL, + NULL, + ClassName->Buffer, + &BufLen); + + if (NT_SUCCESS(Status)) + { + SetLastNtError(Status); + _SEH_LEAVE; + } + + Ret = BufLen / sizeof(WCHAR); + } + } + _SEH_HANDLE + { + SetLastNtError(_SEH_GetExceptionCode()); + } + _SEH_END; + + if (Ansi && szTemp != NULL && szTemp != szStaticTemp) + { + ExFreePool(szTemp); + } + + return Ret; +} + +ULONG_PTR +UserGetClassLongPtr(IN PWINDOWCLASS Class, + IN INT Index, + IN BOOL Ansi) +{ + ULONG_PTR Ret = 0; + + if (Index > 0) + { + PULONG_PTR Data; + + if (Index + sizeof(ULONG_PTR) < Index || + Index + sizeof(ULONG_PTR) > Class->ClsExtra) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return 0; + } + + Data = (PULONG_PTR)((ULONG_PTR)Class + Class->ClassExtraDataOffset); + + /* FIXME - Data might be a unaligned pointer! Might be a problem on + certain architectures, maybe using RtlCopyMemory is a + better choice for those architectures! */ + return *Data; + } + + switch (Index) + { + case GCL_CBWNDEXTRA: + Ret = (ULONG_PTR)Class->WndExtra; + break; + + case GCL_CBCLSEXTRA: + Ret = (ULONG_PTR)Class->ClsExtra; + break; + + case GCLP_HBRBACKGROUND: + Ret = (ULONG_PTR)Class->hbrBackground; + break; + + case GCLP_HCURSOR: + /* FIXME - get handle from pointer to CURSOR object */ + Ret = (ULONG_PTR)Class->hCursor; + break; + + case GCLP_HICON: + /* FIXME - get handle from pointer to ICON object */ + Ret = (ULONG_PTR)Class->hIcon; + break; + + case GCLP_HICONSM: + /* FIXME - get handle from pointer to ICON object */ + Ret = (ULONG_PTR)Class->hIconSm; + break; + + case GCLP_HMODULE: + Ret = (ULONG_PTR)Class->hInstance; + break; + + case GCLP_MENUNAME: + /* NOTE: Returns pointer in kernel heap! */ + if (Ansi) + Ret = (ULONG_PTR)Class->AnsiMenuName; + else + Ret = (ULONG_PTR)Class->MenuName; + break; + + case GCL_STYLE: + Ret = (ULONG_PTR)Class->Style; + break; + + case GCLP_WNDPROC: + Ret = (ULONG_PTR)IntGetClassWndProc(Class, + GetW32ProcessInfo(), + Ansi); + break; + + case GCW_ATOM: + Ret = (ULONG_PTR)Class->Atom; + break; + + default: + SetLastWin32Error(ERROR_INVALID_INDEX); + break; + } + + return Ret; +} + +static BOOL +IntSetClassMenuName(IN PWINDOWCLASS Class, + IN PUNICODE_STRING MenuName) +{ + BOOL Ret = FALSE; + + /* change the base class first */ + Class = Class->Base; + + if (MenuName->Length != 0) + { + ANSI_STRING AnsiString; + PWSTR strBufW; + + AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(MenuName); + + strBufW = UserHeapAlloc(MenuName->Length + sizeof(UNICODE_NULL) + + AnsiString.MaximumLength); + if (strBufW != NULL) + { + _SEH_TRY + { + NTSTATUS Status; + + /* copy the unicode string */ + RtlCopyMemory(strBufW, + MenuName->Buffer, + MenuName->Length); + strBufW[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL; + + /* create an ansi copy of the string */ + AnsiString.Buffer = (PSTR)(strBufW + (MenuName->Length / sizeof(WCHAR)) + 1); + Status = RtlUnicodeStringToAnsiString(&AnsiString, + MenuName, + FALSE); + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + _SEH_LEAVE; + } + + Ret = TRUE; + } + _SEH_HANDLE + { + SetLastNtError(_SEH_GetExceptionCode()); + } + _SEH_END; + + if (Ret) + { + /* update the base class */ + IntFreeClassMenuName(Class); + Class->MenuName = strBufW; + Class->AnsiMenuName = AnsiString.Buffer; + + /* update the clones */ + Class = Class->Clone; + while (Class != NULL) + { + Class->MenuName = strBufW; + Class->AnsiMenuName = AnsiString.Buffer; + + Class = Class->Next; + } + } + else + { + DPRINT1("Failed to copy class menu name!\n"); + UserHeapFree(strBufW); + } + } + else + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + } + else + { + ASSERT(IS_INTRESOURCE(MenuName->Buffer)); + + /* update the base class */ + IntFreeClassMenuName(Class); + Class->MenuName = MenuName->Buffer; + Class->AnsiMenuName = (PSTR)MenuName->Buffer; + + /* update the clones */ + Class = Class->Clone; + while (Class != NULL) + { + Class->MenuName = MenuName->Buffer; + Class->AnsiMenuName = (PSTR)MenuName->Buffer; + + Class = Class->Next; + } + + Ret = TRUE; + } + + return Ret; +} + +ULONG_PTR +UserSetClassLongPtr(IN PWINDOWCLASS Class, + IN INT Index, + IN ULONG_PTR NewLong, + IN BOOL Ansi) +{ + ULONG_PTR Ret = 0; + + /* NOTE: For GCLP_MENUNAME and GCW_ATOM this function may raise an exception! */ + + /* change the information in the base class first, then update the clones */ + Class = Class->Base; + + if (Index > 0) + { + PULONG_PTR Data; + + if (Index + sizeof(ULONG_PTR) < Index || + Index + sizeof(ULONG_PTR) > Class->ClsExtra) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return 0; + } + + Data = (PULONG_PTR)((ULONG_PTR)Class + Class->ClassExtraDataOffset); + + /* FIXME - Data might be a unaligned pointer! Might be a problem on + certain architectures, maybe using RtlCopyMemory is a + better choice for those architectures! */ + Ret = *Data; + *Data = NewLong; + + /* update the clones */ + Class = Class->Clone; + while (Class != NULL) + { + *(PULONG_PTR)((ULONG_PTR)Class + Class->ClassExtraDataOffset) = NewLong; + Class = Class->Next; + } + + return Ret; + } + + switch (Index) + { + case GCL_CBWNDEXTRA: + Ret = (ULONG_PTR)Class->WndExtra; + Class->WndExtra = (INT)NewLong; + + /* update the clones */ + Class = Class->Clone; + while (Class != NULL) + { + Class->WndExtra = (INT)NewLong; + Class = Class->Next; + } + + break; + + case GCL_CBCLSEXTRA: + Ret = (ULONG_PTR)Class->ClsExtra; + if (Class->ClsExtra != (INT)NewLong) + { + if (!IntClassResize(Class, + GetW32ProcessInfo(), + (INT)NewLong)) + { + Ret = 0; + } + } + break; + + case GCLP_HBRBACKGROUND: + Ret = (ULONG_PTR)Class->hbrBackground; + Class->hbrBackground = (HBRUSH)NewLong; + + /* update the clones */ + Class = Class->Clone; + while (Class != NULL) + { + Class->hbrBackground = (HBRUSH)NewLong; + Class = Class->Next; + } + break; + + case GCLP_HCURSOR: + /* FIXME - get handle from pointer to CURSOR object */ + Ret = (ULONG_PTR)Class->hCursor; + Class->hCursor = (HANDLE)NewLong; + + /* update the clones */ + Class = Class->Clone; + while (Class != NULL) + { + Class->hCursor = (HANDLE)NewLong; + Class = Class->Next; + } + break; + + case GCLP_HICON: + /* FIXME - get handle from pointer to ICON object */ + Ret = (ULONG_PTR)Class->hIcon; + Class->hIcon = (HANDLE)NewLong; + + /* update the clones */ + Class = Class->Clone; + while (Class != NULL) + { + Class->hIcon = (HANDLE)NewLong; + Class = Class->Next; + } + break; + + case GCLP_HICONSM: + /* FIXME - get handle from pointer to ICON object */ + Ret = (ULONG_PTR)Class->hIconSm; + Class->hIconSm = (HANDLE)NewLong; + + /* update the clones */ + Class = Class->Clone; + while (Class != NULL) + { + Class->hIconSm = (HANDLE)NewLong; + Class = Class->Next; + } + break; + + case GCLP_HMODULE: + Ret = (ULONG_PTR)Class->hInstance; + Class->hInstance = (HINSTANCE)NewLong; + + /* update the clones */ + Class = Class->Clone; + while (Class != NULL) + { + Class->hInstance = (HINSTANCE)NewLong; + Class = Class->Next; + } + break; + + case GCLP_MENUNAME: + { + PUNICODE_STRING Value = (PUNICODE_STRING)NewLong; + + if (!IntSetClassMenuName(Class, + Value)) + { + DPRINT("Setting the class menu name failed!\n"); + } + + /* FIXME - really return NULL? Wine does so... */ + break; + } + + case GCL_STYLE: + Ret = (ULONG_PTR)Class->Style; + Class->Style = (UINT)NewLong; + + /* FIXME - what if the CS_GLOBALCLASS style is changed? should we + move the class to the appropriate list? For now, we save + the original value in Class->Global, so we can always + locate the appropriate list */ + + /* update the clones */ + Class = Class->Clone; + while (Class != NULL) + { + Class->Style = (UINT)NewLong; + Class = Class->Next; + } + break; + + case GCLP_WNDPROC: + Ret = (ULONG_PTR)IntSetClassWndProc(Class, + (WNDPROC)NewLong, + Ansi); + break; + + case GCW_ATOM: + { + PUNICODE_STRING Value = (PUNICODE_STRING)NewLong; + + Ret = (ULONG_PTR)Class->Atom; + if (!IntSetClassAtom(Class, + Value)) + { + Ret = 0; + } + break; + } + + default: + SetLastWin32Error(ERROR_INVALID_INDEX); + break; + } + + return Ret; +} + +static BOOL +UserGetClassInfo(IN PWINDOWCLASS Class, + OUT PWNDCLASSEXW lpwcx, + IN BOOL Ansi) +{ + lpwcx->style = Class->Style; + + if (Class->System) + { + lpwcx->lpfnWndProc = (!Ansi ? Class->WndProc : Class->WndProcExtra); + } + else + { + if (!Ansi == Class->Unicode) + { + lpwcx->lpfnWndProc = Class->WndProc; + } + else + { + /* FIXME - return callproc handle or function pointer? */ + lpwcx->lpfnWndProc = Class->CallProc->WndProc; + } + } + + lpwcx->cbClsExtra = Class->ClsExtra; + lpwcx->cbWndExtra = Class->WndExtra; + lpwcx->hInstance = Class->hInstance; + lpwcx->hIcon = Class->hIcon; /* FIXME - get handle from pointer */ + lpwcx->hCursor = Class->hCursor; /* FIXME - get handle from pointer */ + lpwcx->hbrBackground = Class->hbrBackground; + + if (Ansi) + ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->AnsiMenuName; + else + lpwcx->lpszMenuName = Class->MenuName; + + lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->Atom); /* FIXME - return the string? */ + + lpwcx->hIconSm = Class->hIconSm; /* FIXME - get handle from pointer */ + + return TRUE; +} + /* SYSCALLS *****************************************************************/
-RTL_ATOM STDCALL -NtUserRegisterClassExWOW( - CONST WNDCLASSEXW* lpwcx, - PUNICODE_STRING ClassName, - PUNICODE_STRING ClassNameCopy,//huhuhuhu??? - PUNICODE_STRING MenuName, - WNDPROC wpExtra, - DWORD Flags, - DWORD Unknown7, - HMENU hMenu) +RTL_ATOM NTAPI +NtUserRegisterClassEx(IN CONST WNDCLASSEXW* lpwcx, + IN PUNICODE_STRING ClassName, + IN PUNICODE_STRING MenuName, + IN WNDPROC wpExtra, + IN DWORD Flags, + IN HMENU hMenu)
/* * FUNCTION: @@ -452,149 +1819,204 @@ * Atom identifying the new class */ { - WNDCLASSEXW SafeClass; - NTSTATUS Status; - RTL_ATOM Atom; - DECLARE_RETURN(RTL_ATOM); - - DPRINT("Enter NtUserRegisterClassExWOW\n"); - UserEnterExclusive(); - - if (!lpwcx) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - RETURN( (RTL_ATOM)0); - } - - if (Flags & ~REGISTERCLASS_ALL) - { - SetLastWin32Error(ERROR_INVALID_FLAGS); - RETURN( (RTL_ATOM)0); - } - - Status = MmCopyFromCaller(&SafeClass, lpwcx, sizeof(WNDCLASSEXW)); - if (!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - RETURN( (RTL_ATOM)0); - } - - /* Deny negative sizes */ - if (lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - RETURN( (RTL_ATOM)0); - } - - if (!lpwcx->hInstance) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - RETURN( (RTL_ATOM)0); - } - - //FIXME: make ClassName ptr the atom, not buffer - if (ClassName->Length > 0) - { - DPRINT("NtUserRegisterClassExWOW(%S)\n", ClassName->Buffer); - /* FIXME - Safely copy/verify the buffer first!!! */ - Status = RtlAddAtomToAtomTable(gAtomTable, - ClassName->Buffer, - &Atom); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed adding class name (%S) to atom table\n", - ClassName->Buffer); - SetLastNtError(Status); - RETURN((RTL_ATOM)0); - } - } - else - { - Atom = (RTL_ATOM)(ULONG)ClassName->Buffer; - } - - if (!Atom) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - RETURN(0); - } - - if (!IntRegisterClass(&SafeClass, Flags, wpExtra, MenuName, Atom, hMenu)) - { - if (ClassName->Length) - { - RtlDeleteAtomFromAtomTable(gAtomTable, Atom); - } - DPRINT("Failed creating window class object\n"); - RETURN((RTL_ATOM)0); - } - - RETURN(Atom); - -CLEANUP: - DPRINT("Leave NtUserRegisterClassExWOW, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} - - - -DWORD STDCALL -NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi) -{ - PWINDOW_OBJECT Window; - DECLARE_RETURN(DWORD); - - DPRINT("Enter NtUserGetClassLong\n"); - UserEnterExclusive(); - - if (!(Window = UserGetWindowObject(hWnd))) - { - RETURN(0); - } - - RETURN(IntGetClassLong(Window, Offset, Ansi)); - -CLEANUP: - DPRINT("Leave NtUserGetClassLong, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} - - - -DWORD STDCALL + WNDCLASSEXW CapturedClassInfo = {0}; + UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0}; + RTL_ATOM Ret = (RTL_ATOM)0; + + if (Flags & ~REGISTERCLASS_ALL) + { + SetLastWin32Error(ERROR_INVALID_FLAGS); + return Ret; + } + + UserEnterExclusive(); + + _SEH_TRY + { + /* Probe the parameters and basic parameter checks */ + if (ProbeForReadUint(&lpwcx->cbSize) != sizeof(WNDCLASSEXW)) + { + goto InvalidParameter; + } + + ProbeForRead(lpwcx, + sizeof(WNDCLASSEXW), + sizeof(ULONG)); + RtlCopyMemory(&CapturedClassInfo, + lpwcx, + sizeof(WNDCLASSEXW)); + + CapturedName = ProbeForReadUnicodeString(ClassName); + CapturedMenuName = ProbeForReadUnicodeString(MenuName); + + if (CapturedName.Length & 1 || CapturedMenuName.Length & 1 || + CapturedClassInfo.cbClsExtra < 0 || + CapturedClassInfo.cbClsExtra + CapturedName.Length + + CapturedMenuName.Length + sizeof(WINDOWCLASS) < CapturedClassInfo.cbClsExtra || + CapturedClassInfo.cbWndExtra < 0 || + CapturedClassInfo.hInstance == NULL) + { + goto InvalidParameter; + } + + if (CapturedName.Length != 0) + { + ProbeForRead(CapturedName.Buffer, + CapturedName.Length, + sizeof(WCHAR)); + } + else + { + if (!IS_ATOM(CapturedName.Buffer)) + { + goto InvalidParameter; + } + } + + if (CapturedMenuName.Length != 0) + { + ProbeForRead(CapturedMenuName.Buffer, + CapturedMenuName.Length, + sizeof(WCHAR)); + } + else if (CapturedMenuName.Buffer != NULL && + !IS_INTRESOURCE(CapturedMenuName.Buffer)) + { +InvalidParameter: + SetLastWin32Error(ERROR_INVALID_PARAMETER); + _SEH_LEAVE; + } + + /* Register the class */ + Ret = UserRegisterClass(&CapturedClassInfo, + &CapturedName, + &CapturedMenuName, + hMenu, /* FIXME - pass pointer */ + wpExtra, + Flags); + + } + _SEH_HANDLE + { + SetLastNtError(_SEH_GetExceptionCode()); + } + _SEH_END; + + UserLeave(); + + return Ret; +} + + + +ULONG_PTR NTAPI +NtUserGetClassLong(IN HWND hWnd, + IN INT Offset, + IN BOOL Ansi) +{ + PWINDOW_OBJECT Window; + ULONG_PTR Ret = 0; + + UserEnterShared(); + + Window = UserGetWindowObject(hWnd); + if (Window != NULL) + { + Ret = UserGetClassLongPtr(Window->Class, + Offset, + Ansi); + + if (Ret != 0 && Offset == GCLP_MENUNAME && !IS_INTRESOURCE(Ret)) + { + Ret = (ULONG_PTR)DesktopHeapAddressToUser(Window->Class->Desktop, + (PVOID)Ret); + } + } + + UserLeave(); + + return Ret; +} + + + +ULONG_PTR STDCALL NtUserSetClassLong(HWND hWnd, - DWORD Offset, - LONG dwNewLong, + INT Offset, + ULONG_PTR dwNewLong, BOOL Ansi) { - PWINDOW_OBJECT Window; - LONG Ret; - USER_REFERENCE_ENTRY Ref; - DECLARE_RETURN(DWORD); - - DPRINT("Enter NtUserSetClassLong\n"); - UserEnterExclusive(); - - if (!(Window = UserGetWindowObject(hWnd))) - { - RETURN(0); - } - - UserRefObjectCo(Window, &Ref); - - Ret = IntGetClassLong(Window, Offset, Ansi); - co_IntSetClassLong(Window, Offset, dwNewLong, Ansi); - - UserDerefObjectCo(Window); - - RETURN(Ret); - -CLEANUP: - DPRINT("Leave NtUserSetClassLong, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; + PW32PROCESSINFO pi; + PWINDOW_OBJECT Window; + ULONG_PTR Ret = 0; + + UserEnterExclusive(); + + pi = GetW32ProcessInfo(); + if (pi == NULL) + goto Cleanup; + + Window = UserGetWindowObject(hWnd); + if (Window != NULL) + { + if (Window->ti->kpi != pi) + { + SetLastWin32Error(ERROR_ACCESS_DENIED); + goto Cleanup; + } + + _SEH_TRY + { + UNICODE_STRING Value; + + /* probe the parameters */ + if (Offset == GCW_ATOM || Offset == GCLP_MENUNAME) + { + Value = ProbeForReadUnicodeString((PUNICODE_STRING)dwNewLong); + if (Value.Length & 1) + { + goto InvalidParameter; + } + + if (Value.Length != 0) + { + ProbeForRead(Value.Buffer, + Value.Length, + sizeof(WCHAR)); + } + else + { + if (Offset == GCW_ATOM && !IS_ATOM(Value.Buffer)) + { + goto InvalidParameter; + } + else if (Offset == GCLP_MENUNAME && !IS_INTRESOURCE(Value.Buffer)) + { +InvalidParameter: + SetLastWin32Error(ERROR_INVALID_PARAMETER); + _SEH_LEAVE; + } + } + + dwNewLong = (ULONG_PTR)&Value; + } + + Ret = UserSetClassLongPtr(Window->Class, + Offset, + dwNewLong, + Ansi); + } + _SEH_HANDLE + { + SetLastNtError(_SEH_GetExceptionCode()); + } + _SEH_END; + } + +Cleanup: + UserLeave(); + + return Ret; }
DWORD STDCALL @@ -602,164 +2024,232 @@ DWORD Unknown1, DWORD Unknown2) { - UNIMPLEMENTED; return(0); }
+BOOL NTAPI +NtUserUnregisterClass(IN PUNICODE_STRING ClassNameOrAtom, + IN HINSTANCE hInstance) +{ + UNICODE_STRING CapturedClassName; + BOOL Ret = FALSE; + + UserEnterExclusive(); + + _SEH_TRY + { + /* probe the paramters */ + CapturedClassName = ProbeForReadUnicodeString(ClassNameOrAtom); + if (CapturedClassName.Length & 1) + { + goto InvalidParameter; + } + + if (CapturedClassName.Length != 0) + { + ProbeForRead(CapturedClassName.Buffer, + CapturedClassName.Length, + sizeof(WCHAR)); + } + else + { + if (!IS_ATOM(CapturedClassName.Buffer)) + { +InvalidParameter: + SetLastWin32Error(ERROR_INVALID_PARAMETER); + _SEH_LEAVE; + } + } + + /* unregister the class */ + Ret = UserUnregisterClass(&CapturedClassName, + hInstance); + } + _SEH_HANDLE + { + SetLastNtError(_SEH_GetExceptionCode()); + } + _SEH_END; + + UserLeave(); + + return Ret; +} + +/* NOTE: for system classes hInstance is not NULL here, but User32Instance */ BOOL STDCALL -NtUserUnregisterClass( - LPCWSTR ClassNameOrAtom, - HINSTANCE hInstance, /* can be 0 */ - DWORD Unknown) -{ - PWNDCLASS_OBJECT Class; - DECLARE_RETURN(BOOL); - - DPRINT("Enter NtUserUnregisterClass(%S)\n", ClassNameOrAtom); - UserEnterExclusive(); - - if (!ClassNameOrAtom) - { - SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); - RETURN(FALSE); - } - - if (!(Class = ClassGetClassByNameOrAtom(ClassNameOrAtom, hInstance))) - { - SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); - RETURN(FALSE); - } - - if (Class->refs) - { - /* NOTE: the class will not be freed when its refs become 0 ie. no more - * windows are using it. I dunno why that is but its how Windows does it (and Wine). - * The class will hang around until the process exit. -Gunnar - */ - SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS); - RETURN(FALSE); - } - - DestroyClass(Class); - - RETURN(TRUE); - -CLEANUP: - DPRINT("Leave NtUserUnregisterClass, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} - -/* NOTE: for system classes hInstance is not NULL here, but User32Instance */ -DWORD STDCALL NtUserGetClassInfo( HINSTANCE hInstance, - LPCWSTR lpClassName, + PUNICODE_STRING ClassName, LPWNDCLASSEXW lpWndClassEx, - BOOL Ansi, - DWORD unknown3) -{ - PWNDCLASS_OBJECT Class; - RTL_ATOM Atom; - DECLARE_RETURN(DWORD); - - if (IS_ATOM(lpClassName)) - DPRINT("NtUserGetClassInfo - %x (%lx)\n", lpClassName, hInstance); - else - DPRINT("NtUserGetClassInfo - %S (%lx)\n", lpClassName, hInstance); - - UserEnterExclusive(); - - if (!hInstance) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - RETURN(0); - } - - if (!(Class = ClassGetClassByNameOrAtom(lpClassName, hInstance))) - { - SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); - RETURN(0); - } - - lpWndClassEx->cbSize = sizeof(WNDCLASSEXW); - lpWndClassEx->style = Class->style; - if (Ansi) - lpWndClassEx->lpfnWndProc = Class->lpfnWndProcA; - else - lpWndClassEx->lpfnWndProc = Class->lpfnWndProcW; - lpWndClassEx->cbClsExtra = Class->cbClsExtra; - lpWndClassEx->cbWndExtra = Class->cbWndExtra; - /* This is not typo, we're really not going to use Class->hInstance here. */ - /* Well, i think its wrong so i changed it -Gunnar */ - lpWndClassEx->hInstance = Class->hInstance; - lpWndClassEx->hIcon = Class->hIcon; - lpWndClassEx->hCursor = Class->hCursor; - lpWndClassEx->hbrBackground = Class->hbrBackground; - if (Class->lpszMenuName.MaximumLength) - RtlCopyUnicodeString((PUNICODE_STRING)lpWndClassEx->lpszMenuName, &Class->lpszMenuName); - else - lpWndClassEx->lpszMenuName = Class->lpszMenuName.Buffer; - lpWndClassEx->lpszClassName = lpClassName; - lpWndClassEx->hIconSm = Class->hIconSm; - Atom = Class->Atom; - - RETURN(Atom); - -CLEANUP: - DPRINT("Leave NtUserGetClassInfo, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} - - - -DWORD STDCALL -NtUserGetClassName ( - HWND hWnd, - LPWSTR lpClassName, - ULONG nMaxCount /* in TCHARS */ - ) -{ - PWINDOW_OBJECT Window; - DECLARE_RETURN(DWORD); - NTSTATUS Status; - - UserEnterShared(); - DPRINT("Enter NtUserGetClassName\n"); - - if (!(Window = UserGetWindowObject(hWnd))) - { - RETURN(0); - } - - nMaxCount *= sizeof(WCHAR); - - //FIXME: wrap in SEH to protect lpClassName access - Status = RtlQueryAtomInAtomTable(gAtomTable, - Window->Class->Atom, NULL, NULL, - lpClassName, &nMaxCount); - if (!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - RETURN(0); - } - - RETURN(nMaxCount / sizeof(WCHAR)); - -CLEANUP: - DPRINT("Leave NtUserGetClassName, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; + BOOL Ansi) +{ + UNICODE_STRING CapturedClassName; + PWINDOWCLASS Class; + RTL_ATOM ClassAtom; + PW32PROCESSINFO pi; + BOOL Ret = FALSE; + + UserEnterShared(); + + pi = GetW32ProcessInfo(); + if (pi == NULL) + { + goto Cleanup; + } + + _SEH_TRY + { + /* probe the paramters */ + CapturedClassName = ProbeForReadUnicodeString(ClassName); + if (CapturedClassName.Length & 1) + { + goto InvalidParameter; + } + + if (CapturedClassName.Length != 0) + { + ProbeForRead(CapturedClassName.Buffer, + CapturedClassName.Length, + sizeof(WCHAR)); + } + else + { + if (!IS_ATOM(CapturedClassName.Buffer)) + { + goto InvalidParameter; + } + } + + if (ProbeForReadUint(&lpWndClassEx->cbSize) != sizeof(WNDCLASSEXW)) + { +InvalidParameter: + SetLastWin32Error(ERROR_INVALID_PARAMETER); + _SEH_LEAVE; + } + + ProbeForWrite(lpWndClassEx, + sizeof(WNDCLASSEXW), + sizeof(ULONG)); + + ClassAtom = IntGetClassAtom(&CapturedClassName, + hInstance, + pi, + &Class, + NULL); + if (ClassAtom != (RTL_ATOM)0) + { + Ret = UserGetClassInfo(Class, + lpWndClassEx, + Ansi); + + if (Ret) + { + lpWndClassEx->lpszClassName = CapturedClassName.Buffer; + + /* FIXME - handle Class->Desktop == NULL!!!!! */ + + if (Class->MenuName != NULL && + !IS_INTRESOURCE(Class->MenuName)) + { + lpWndClassEx->lpszMenuName = DesktopHeapAddressToUser(Class->Desktop, + (Ansi ? + (PVOID)Class->AnsiMenuName : + (PVOID)Class->MenuName)); + } + } + } + } + _SEH_HANDLE + { + SetLastNtError(_SEH_GetExceptionCode()); + } + _SEH_END; + +Cleanup: + UserLeave(); + + return Ret; +} + + + +INT NTAPI +NtUserGetClassName (IN HWND hWnd, + OUT PUNICODE_STRING ClassName, + IN BOOL Ansi) +{ + PWINDOW_OBJECT Window; + UNICODE_STRING CapturedClassName; + INT Ret = 0; + + UserEnterShared(); + + Window = UserGetWindowObject(hWnd); + if (Window != NULL) + { + _SEH_TRY + { + ProbeForWriteUnicodeString(ClassName); + CapturedClassName = *ClassName; + + /* get the class name */ + Ret = UserGetClassName(Window->Class, + &CapturedClassName, + Ansi); + + if (Ret != 0) + { + /* update the Length field */ + ClassName->Length = CapturedClassName.Length; + } + } + _SEH_HANDLE + { + SetLastNtError(_SEH_GetExceptionCode()); + } + _SEH_END; + } + + UserLeave(); + + return Ret; }
DWORD STDCALL NtUserGetWOWClass(DWORD Unknown0, DWORD Unknown1) { - UNIMPLEMENTED; return(0); }
+BOOL NTAPI +NtUserDereferenceWndProcHandle(IN HANDLE wpHandle, + OUT PWNDPROC_INFO wpInfo) +{ + BOOL Ret = FALSE; + + UserEnterShared(); + + _SEH_TRY + { + ProbeForWrite(wpInfo, + sizeof(WNDPROC_INFO), + sizeof(ULONG)); + + Ret = UserGetCallProcInfo(wpHandle, + wpInfo); + } + _SEH_HANDLE + { + SetLastWin32Error(_SEH_GetExceptionCode()); + } + _SEH_END; + + UserLeave(); + + return Ret; +} + /* EOF */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c Wed Apr 5 12:05:55 2006 @@ -83,7 +83,7 @@ return NULL; }
- CurIcon = (PCURICON_OBJECT)UserGetObject(&gHandleTable, hCurIcon, otCursorIcon); + CurIcon = (PCURICON_OBJECT)UserGetObject(gHandleTable, hCurIcon, otCursorIcon); if (!CurIcon) { /* we never set ERROR_INVALID_ICON_HANDLE. lets hope noone ever checks for it */ @@ -397,7 +397,7 @@ PCURICON_OBJECT CurIcon; HANDLE hCurIcon;
- CurIcon = ObmCreateObject(&gHandleTable, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT)); + CurIcon = ObmCreateObject(gHandleTable, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT));
if(!CurIcon) {
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c Wed Apr 5 12:05:55 2006 @@ -43,6 +43,8 @@
BOOL g_PaintDesktopVersion = FALSE;
+static VOID IntFreeDesktopHeap(IN OUT PDESKTOP_OBJECT Desktop); + /* INITALIZATION FUNCTIONS ****************************************************/
static GENERIC_MAPPING IntDesktopMapping = @@ -121,6 +123,8 @@ RemoveEntryList(&Desktop->ListEntry);
RtlFreeUnicodeString(&Desktop->Name); + + IntFreeDesktopHeap(Desktop); }
/* PRIVATE FUNCTIONS **********************************************************/ @@ -723,7 +727,15 @@ return FALSE; }
- +static VOID +IntFreeDesktopHeap(IN OUT PDESKTOP_OBJECT Desktop) +{ + if (Desktop->DesktopHeapSection != NULL) + { + ObDereferenceObject(Desktop->DesktopHeapSection); + Desktop->DesktopHeapSection = NULL; + } +}
/* SYSCALLS *******************************************************************/ @@ -776,6 +788,8 @@ NTSTATUS Status; HDESK Desktop; CSR_API_MESSAGE Request; + PVOID DesktopHeapSystemBase = NULL; + SIZE_T DesktopInfoSize; DECLARE_RETURN(HDESK);
DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName); @@ -857,6 +871,39 @@ SetLastNtError(STATUS_UNSUCCESSFUL); RETURN( NULL); } + + DesktopObject->DesktopHeapSection = NULL; + DesktopObject->hDesktopHeap = UserCreateHeap(&DesktopObject->DesktopHeapSection, + &DesktopHeapSystemBase, + 4 * 1024 * 1024); /* FIXME */ + if (DesktopObject->hDesktopHeap == NULL) + { + ObDereferenceObject(DesktopObject); + DPRINT1("Failed to create desktop heap!\n"); + RETURN(NULL); + } + + DesktopInfoSize = FIELD_OFFSET(DESKTOP, + szDesktopName[(lpszDesktopName->Length / sizeof(WCHAR)) + 1]); + + DesktopObject->DesktopInfo = RtlAllocateHeap(DesktopObject->hDesktopHeap, + HEAP_NO_SERIALIZE, + DesktopInfoSize); + + if (DesktopObject->DesktopInfo == NULL) + { + ObDereferenceObject(DesktopObject); + DPRINT1("Failed to create the DESKTOP structure!\n"); + RETURN(NULL); + } + + RtlZeroMemory(DesktopObject->DesktopInfo, + DesktopInfoSize); + + DesktopObject->DesktopInfo->hKernelHeap = DesktopObject->hDesktopHeap; + RtlCopyMemory(DesktopObject->DesktopInfo->szDesktopName, + lpszDesktopName->Buffer, + lpszDesktopName->Length);
// init desktop area DesktopObject->WorkArea.left = 0; @@ -1216,7 +1263,7 @@ RETURN(FALSE); }
- DesktopBrush = (HBRUSH)IntGetClassLong(WndDesktop, GCL_HBRBACKGROUND, FALSE); //fixme: verify retval + DesktopBrush = (HBRUSH)UserGetClassLongPtr(WndDesktop->Class, GCL_HBRBACKGROUND, FALSE);
/* @@ -1560,6 +1607,183 @@ END_CLEANUP; }
+static NTSTATUS +IntUnmapDesktopView(IN PDESKTOP_OBJECT DesktopObject) +{ + PW32THREADINFO ti; + PW32HEAP_USER_MAPPING HeapMapping, *PrevLink = &PsGetWin32Process()->HeapMappings.Next; + NTSTATUS Status = STATUS_SUCCESS; + + /* unmap if we're the last thread using the desktop */ + HeapMapping = *PrevLink; + while (HeapMapping != NULL) + { + if (HeapMapping->KernelMapping == (PVOID)DesktopObject->hDesktopHeap) + { + if (--HeapMapping->Count == 0) + { + *PrevLink = HeapMapping->Next; + + Status = MmUnmapViewOfSection(PsGetCurrentProcess(), + HeapMapping->UserMapping); + + ObDereferenceObject(DesktopObject); + + UserHeapFree(HeapMapping); + break; + } + } + + PrevLink = &HeapMapping->Next; + HeapMapping = HeapMapping->Next; + } + + ti = GetW32ThreadInfo(); + if (ti != NULL) + { + if (ti->Desktop == DesktopObject->DesktopInfo) + { + ti->Desktop = NULL; + ti->DesktopHeapDelta = 0; + } + } + + return Status; +} + +static NTSTATUS +IntMapDesktopView(IN PDESKTOP_OBJECT DesktopObject) +{ + PW32THREADINFO ti; + PW32HEAP_USER_MAPPING HeapMapping, *PrevLink = &PsGetWin32Process()->HeapMappings.Next; + PVOID UserBase = NULL; + ULONG ViewSize = 0; + LARGE_INTEGER Offset; + NTSTATUS Status; + + /* find out if another thread already mapped the desktop heap */ + HeapMapping = *PrevLink; + while (HeapMapping != NULL) + { + if (HeapMapping->KernelMapping == (PVOID)DesktopObject->hDesktopHeap) + { + HeapMapping->Count++; + return STATUS_SUCCESS; + } + + PrevLink = &HeapMapping->Next; + HeapMapping = HeapMapping->Next; + } + + /* we're the first, map the heap */ + Offset.QuadPart = 0; + Status = MmMapViewOfSection(DesktopObject->DesktopHeapSection, + PsGetCurrentProcess(), + &UserBase, + 0, + 0, + &Offset, + &ViewSize, + ViewUnmap, + SEC_NO_CHANGE, + PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */ + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to map desktop\n"); + return Status; + } + + /* add the mapping */ + HeapMapping = UserHeapAlloc(sizeof(W32HEAP_USER_MAPPING)); + if (HeapMapping == NULL) + { + MmUnmapViewOfSection(PsGetCurrentProcess(), + UserBase); + return STATUS_NO_MEMORY; + } + + HeapMapping->Next = NULL; + HeapMapping->KernelMapping = (PVOID)DesktopObject->hDesktopHeap; + HeapMapping->UserMapping = UserBase; + HeapMapping->Count = 1; + + ObReferenceObject(DesktopObject); + + /* create a W32THREADINFO structure if not already done, or update it */ + ti = GetW32ThreadInfo(); + if (ti != NULL) + { + if (ti->Desktop == NULL) + { + ti->Desktop = DesktopObject->DesktopInfo; + ti->DesktopHeapDelta = DesktopHeapGetUserDelta(); + } + } + + return STATUS_SUCCESS; +} + +BOOL +IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject) +{ + PDESKTOP_OBJECT OldDesktop; + PW32THREAD W32Thread; + NTSTATUS Status; + BOOL MapHeap; + + MapHeap = (PsGetCurrentProcess() != PsInitialSystemProcess); + W32Thread = PsGetWin32Thread(); + + if (W32Thread->Desktop != DesktopObject) + { + OldDesktop = W32Thread->Desktop; + + W32Thread->Desktop = DesktopObject; + + if (MapHeap && DesktopObject != NULL) + { + Status = IntMapDesktopView(DesktopObject); + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return FALSE; + } + } + + if (DesktopObject != NULL) + { + ObReferenceObject(DesktopObject); + } + + if (OldDesktop != NULL) + { + if (MapHeap) + { + IntUnmapDesktopView(OldDesktop); + } + + ObDereferenceObject(OldDesktop); + + if (W32Thread != NULL && W32Thread->ThreadInfo != NULL && + W32Thread->ThreadInfo->Desktop != (DesktopObject != NULL ? DesktopObject->DesktopInfo : NULL)) + { + if (DesktopObject != NULL) + { + W32Thread->ThreadInfo->Desktop = DesktopObject->DesktopInfo; + W32Thread->ThreadInfo->DesktopHeapDelta = DesktopHeapGetUserDelta(); + } + else + { + W32Thread->ThreadInfo->Desktop = NULL; + W32Thread->ThreadInfo->DesktopHeapDelta = 0; + } + } + } + } + + return TRUE; +} + /* * NtUserSetThreadDesktop * @@ -1570,7 +1794,6 @@ BOOL STDCALL NtUserSetThreadDesktop(HDESK hDesktop) { - PW32THREAD W32Thread; PDESKTOP_OBJECT DesktopObject; NTSTATUS Status; DECLARE_RETURN(BOOL); @@ -1591,17 +1814,12 @@ RETURN(FALSE); }
- W32Thread = PsGetWin32Thread(); - /* FIXME: Should check here to see if the thread has any windows. */
- if (W32Thread->Desktop != NULL) - { - ObDereferenceObject(W32Thread->Desktop); - } - - W32Thread->Desktop = DesktopObject; - W32Thread->hDesktop = hDesktop; + if (!IntSetThreadDesktop(DesktopObject)) + { + RETURN(FALSE); + }
RETURN(TRUE);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/hook.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/hook.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/hook.c Wed Apr 5 12:05:55 2006 @@ -69,7 +69,7 @@ return NULL; }
- Hook = (PHOOK)UserGetObject(&gHandleTable, hHook, otHook); + Hook = (PHOOK)UserGetObject(gHandleTable, hHook, otHook); if (!Hook) { SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE); @@ -110,7 +110,7 @@ } }
- Hook = ObmCreateObject(&gHandleTable, &Handle, otHook, sizeof(HOOK)); + Hook = ObmCreateObject(gHandleTable, &Handle, otHook, sizeof(HOOK)); if (NULL == Hook) { return NULL;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/menu.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/menu.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/menu.c Wed Apr 5 12:05:55 2006 @@ -127,7 +127,7 @@ return NULL; }
- Menu = (PMENU_OBJECT)UserGetObject(&gHandleTable, hMenu, otMenu); + Menu = (PMENU_OBJECT)UserGetObject(gHandleTable, hMenu, otMenu); if (!Menu) { SetLastWin32Error(ERROR_INVALID_MENU_HANDLE); @@ -310,7 +310,7 @@ PMENU_OBJECT Menu;
Menu = (PMENU_OBJECT)ObmCreateObject( - &gHandleTable, Handle, + gHandleTable, Handle, otMenu, sizeof(MENU_OBJECT));
if(!Menu) @@ -419,7 +419,7 @@ return NULL;
Menu = (PMENU_OBJECT)ObmCreateObject( - &gHandleTable, &hMenu, + gHandleTable, &hMenu, otMenu, sizeof(MENU_OBJECT));
if(!Menu)
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/message.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/message.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/message.c Wed Apr 5 12:05:55 2006 @@ -378,28 +378,9 @@
MsgInfo.HandledByKernel = FALSE; Result = 0; - if (0xFFFF0000 != ((DWORD) Window->WndProcW & 0xFFFF0000)) - { - if (0xFFFF0000 != ((DWORD) Window->WndProcA & 0xFFFF0000)) - { - /* Both Unicode and Ansi winprocs are real, use whatever - usermode prefers */ - MsgInfo.Proc = (MsgInfo.Ansi ? Window->WndProcA - : Window->WndProcW); - } - else - { - /* Real Unicode winproc */ - MsgInfo.Ansi = FALSE; - MsgInfo.Proc = Window->WndProcW; - } - } - else - { - /* Must have real Ansi winproc */ - MsgInfo.Ansi = TRUE; - MsgInfo.Proc = Window->WndProcA; - } + + MsgInfo.Ansi = !Window->Unicode; + MsgInfo.Proc = Window->WndProc; } } } @@ -615,7 +596,7 @@ { /* generate double click messages, if necessary */ if ((((*HitTest) != HTCLIENT) || - (IntGetClassLong(Window, GCL_STYLE, FALSE) & CS_DBLCLKS)) && + (Window->Class->Style & CS_DBLCLKS)) && MsqIsDblClk(Msg, Remove)) { Msg->message += WM_LBUTTONDBLCLK - WM_LBUTTONDOWN; @@ -1401,16 +1382,9 @@ DPRINT1("Failed to pack message parameters\n"); RETURN( FALSE); } - if (0xFFFF0000 != ((DWORD) Window->WndProcW & 0xFFFF0000)) - { - Result = (ULONG_PTR)co_IntCallWindowProc(Window->WndProcW, FALSE, hWnd, Msg, wParam, - lParamPacked,lParamBufferSize); - } - else - { - Result = (ULONG_PTR)co_IntCallWindowProc(Window->WndProcA, TRUE, hWnd, Msg, wParam, - lParamPacked,lParamBufferSize); - } + + Result = (ULONG_PTR)co_IntCallWindowProc(Window->WndProc, !Window->Unicode, hWnd, Msg, wParam, + lParamPacked,lParamBufferSize);
if(uResult) { @@ -1580,32 +1554,16 @@ { /* Gather the information usermode needs to call the window proc directly */ Info.HandledByKernel = FALSE; - if (0xFFFF0000 != ((DWORD) Window->WndProcW & 0xFFFF0000)) - { - if (0xFFFF0000 != ((DWORD) Window->WndProcA & 0xFFFF0000)) - { - /* Both Unicode and Ansi winprocs are real, see what usermode prefers */ - Status = MmCopyFromCaller(&(Info.Ansi), &(UnsafeInfo->Ansi), - sizeof(BOOL)); - if (! NT_SUCCESS(Status)) - { - Info.Ansi = ! Window->Unicode; - } - Info.Proc = (Info.Ansi ? Window->WndProcA : Window->WndProcW); - } - else - { - /* Real Unicode winproc */ - Info.Ansi = FALSE; - Info.Proc = Window->WndProcW; - } - } - else - { - /* Must have real Ansi winproc */ - Info.Ansi = TRUE; - Info.Proc = Window->WndProcA; - } + + Status = MmCopyFromCaller(&(Info.Ansi), &(UnsafeInfo->Ansi), + sizeof(BOOL)); + if (! NT_SUCCESS(Status)) + { + Info.Ansi = ! Window->Unicode; + } + + Info.Ansi = !Window->Unicode; + Info.Proc = Window->WndProc; } else {
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/misc.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/misc.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/misc.c Wed Apr 5 12:05:55 2006 @@ -886,11 +886,22 @@ DECLARE_RETURN(DWORD);
DPRINT("Enter NtUserGetThreadState\n"); - UserEnterShared(); + if (Routine != THREADSTATE_GETTHREADINFO) + { + UserEnterShared(); + } + else + { + UserEnterExclusive(); + }
switch (Routine) { - case 0: + case THREADSTATE_GETTHREADINFO: + GetW32ThreadInfo(); + RETURN(0); + + case THREADSTATE_FOCUSWINDOW: RETURN( (DWORD)IntGetThreadFocusWindow()); } RETURN( 0); @@ -1829,4 +1840,106 @@ END_CLEANUP; }
+PW32PROCESSINFO +GetW32ProcessInfo(VOID) +{ + PW32PROCESSINFO pi; + PW32PROCESS W32Process = PsGetWin32Process(); + + if (W32Process == NULL) + { + /* FIXME - temporary hack for system threads... */ + return NULL; + } + + if (W32Process->ProcessInfo == NULL) + { + pi = UserHeapAlloc(sizeof(W32PROCESSINFO)); + if (pi != NULL) + { + RtlZeroMemory(pi, + sizeof(W32PROCESSINFO)); + + /* initialize it */ + pi->UserHandleTable = gHandleTable; + + if (InterlockedCompareExchangePointer(&W32Process->ProcessInfo, + pi, + NULL) != NULL) + { + UserHeapFree(pi); + } + } + else + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + } + } + + return W32Process->ProcessInfo; +} + +PW32THREADINFO +GetW32ThreadInfo(VOID) +{ + PTEB Teb; + PW32THREADINFO ti; + PW32THREAD W32Thread = PsGetWin32Thread(); + + if (W32Thread == NULL) + { + /* FIXME - temporary hack for system threads... */ + return NULL; + } + + /* allocate a W32THREAD structure if neccessary */ + if (W32Thread->ThreadInfo == NULL) + { + ti = UserHeapAlloc(sizeof(W32THREADINFO)); + if (ti != NULL) + { + RtlZeroMemory(ti, + sizeof(W32THREADINFO)); + + /* initialize it */ + ti->kpi = GetW32ProcessInfo(); + ti->pi = UserHeapAddressToUser(ti->kpi); + if (W32Thread->Desktop != NULL) + { + ti->Desktop = W32Thread->Desktop->DesktopInfo; + ti->DesktopHeapDelta = DesktopHeapGetUserDelta(); + } + else + { + ti->Desktop = NULL; + ti->DesktopHeapDelta = 0; + } + + W32Thread->ThreadInfo = ti; + /* update the TEB */ + Teb = NtCurrentTeb(); + _SEH_TRY + { + ProbeForWrite(Teb, + sizeof(TEB), + sizeof(ULONG)); + + Teb->Win32ThreadInfo = UserHeapAddressToUser(W32Thread->ThreadInfo); + } + _SEH_HANDLE + { + SetLastNtError(_SEH_GetExceptionCode()); + } + _SEH_END; + } + else + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + } + } + + return W32Thread->ThreadInfo; +} + + /* EOF */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c Wed Apr 5 12:05:55 2006 @@ -89,7 +89,7 @@ HANDLE Handle; PMONITOR_OBJECT Monitor;
- Monitor = ObmCreateObject(&gHandleTable, &Handle, otMonitor, sizeof (MONITOR_OBJECT)); + Monitor = ObmCreateObject(gHandleTable, &Handle, otMonitor, sizeof (MONITOR_OBJECT)); if (Monitor == NULL) { return NULL; @@ -133,7 +133,7 @@ }
- Monitor = (PMONITOR_OBJECT)UserGetObject(&gHandleTable, hMonitor, otMonitor); + Monitor = (PMONITOR_OBJECT)UserGetObject(gHandleTable, hMonitor, otMonitor); if (!Monitor) { SetLastWin32Error(ERROR_INVALID_MONITOR_HANDLE);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/object.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/object.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/object.c Wed Apr 5 12:05:55 2006 @@ -28,7 +28,7 @@ #include <debug.h>
int usedHandles=0; -USER_HANDLE_TABLE gHandleTable; +PUSER_HANDLE_TABLE gHandleTable = NULL;
PUSER_HANDLE_ENTRY handle_to_entry(PUSER_HANDLE_TABLE ht, HANDLE handle ) @@ -71,19 +71,17 @@ DPRINT1("Out of user handles!\n"); return NULL; #if 0 - - struct user_handle *new_handles; + PUSER_HANDLE_ENTRY new_handles; /* grow array by 50% (but at minimum 32 entries) */ - int growth = max( 32, allocated_handles / 2 ); - int new_size = min( allocated_handles + growth, (LAST_USER_HANDLE-FIRST_USER_HANDLE+1) >> 1 ); - if (new_size <= allocated_handles) + int growth = max( 32, ht->allocated_handles / 2 ); + int new_size = min( ht->allocated_handles + growth, (LAST_USER_HANDLE-FIRST_USER_HANDLE+1) >> 1 ); + if (new_size <= ht->allocated_handles) return NULL; - if (!(new_handles = realloc( handles, new_size * sizeof(*handles) ))) + if (!(new_handles = UserHeapReAlloc( ht->handles, new_size * sizeof(*ht->handles) ))) return NULL; - handles = new_handles; - allocated_handles = new_size; + ht->handles = new_handles; + ht->allocated_handles = new_size; #endif - }
entry = &ht->handles[ht->nb_handles++]; @@ -217,7 +215,7 @@ {
HANDLE hi; - PUSER_OBJECT_HEADER hdr = ExAllocatePool(PagedPool, size + sizeof(USER_OBJECT_HEADER)); + PUSER_OBJECT_HEADER hdr = UserHeapAlloc(size + sizeof(USER_OBJECT_HEADER));//ExAllocatePool(PagedPool, size + sizeof(USER_OBJECT_HEADER)); if (!hdr) return NULL;
@@ -225,7 +223,8 @@ hi = UserAllocHandle(ht, USER_HEADER_TO_BODY(hdr), type ); if (!hi) { - ExFreePool(hdr); + //ExFreePool(hdr); + UserHeapFree(hdr); return NULL; }
@@ -242,7 +241,7 @@ ObmDeleteObject(HANDLE h, USER_OBJECT_TYPE type ) { PUSER_OBJECT_HEADER hdr; - PVOID body = UserGetObject(&gHandleTable, h, type); + PVOID body = UserGetObject(gHandleTable, h, type); if (!body) return FALSE;
@@ -252,11 +251,12 @@ hdr->destroyed = TRUE; if (hdr->RefCount == 0) { - UserFreeHandle(&gHandleTable, h); + UserFreeHandle(gHandleTable, h);
memset(hdr, 0x55, sizeof(USER_OBJECT_HEADER));
- ExFreePool(hdr); + UserHeapFree(hdr); + //ExFreePool(hdr); return TRUE; }
@@ -274,6 +274,12 @@ hdr->RefCount++; }
+HANDLE FASTCALL ObmObjectToHandle(PVOID obj) +{ + PUSER_OBJECT_HEADER hdr = USER_BODY_TO_HEADER(obj); + return hdr->hSelf; +} +
BOOL FASTCALL ObmDereferenceObject2(PVOID obj) { @@ -287,11 +293,12 @@ { // DPRINT1("info: something destroyed bcaise of deref, in use=%i\n",usedHandles);
- UserFreeHandle(&gHandleTable, hdr->hSelf); + UserFreeHandle(gHandleTable, hdr->hSelf);
memset(hdr, 0x55, sizeof(USER_OBJECT_HEADER));
- ExFreePool(hdr); + UserHeapFree(hdr); + //ExFreePool(hdr);
return TRUE; } @@ -307,15 +314,24 @@ PVOID mem;
//FIXME: dont alloc all at once! must be mapped into umode also... - mem = ExAllocatePool(PagedPool, sizeof(USER_HANDLE_ENTRY) * 1024*2); + //mem = ExAllocatePool(PagedPool, sizeof(USER_HANDLE_ENTRY) * 1024*2); + mem = UserHeapAlloc(sizeof(USER_HANDLE_ENTRY) * 1024*2); if (!mem) { DPRINT1("Failed creating handle table\n"); return FALSE; }
+ gHandleTable = UserHeapAlloc(sizeof(USER_HANDLE_TABLE)); + if (gHandleTable == NULL) + { + UserHeapFree(mem); + DPRINT1("Failed creating handle table\n"); + return FALSE; + } + //FIXME: make auto growable - UserInitHandleTable(&gHandleTable, mem, sizeof(USER_HANDLE_ENTRY) * 1024*2); + UserInitHandleTable(gHandleTable, mem, sizeof(USER_HANDLE_ENTRY) * 1024*2);
return TRUE; }
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/windc.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/windc.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/windc.c Wed Apr 5 12:05:55 2006 @@ -353,7 +353,7 @@
if (!(Flags & DCX_WINDOW)) { - if (Window->Class->style & CS_PARENTDC) + if (Window->Class->Style & CS_PARENTDC) { Flags |= DCX_PARENTCLIP; } @@ -676,7 +676,7 @@ { if (pDCE == Window->Dce) /* owned or Class DCE*/ { - if (Window->Class->style & CS_OWNDC) /* owned DCE*/ + if (Window->Class->Style & CS_OWNDC) /* owned DCE*/ { pDCE = DceFreeDCE(pDCE, FALSE); Window->Dce = NULL;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/window.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c Wed Apr 5 12:05:55 2006 @@ -33,10 +33,6 @@ #define NDEBUG #include <debug.h>
-static WndProcHandle *WndProcHandlesArray = 0; -static WORD WndProcHandlesArraySize = 0; -#define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */ - /* dialog resources appear to pass this in 16 bits, handle them properly */ #define CW_USEDEFAULT16 (0x8000)
@@ -53,8 +49,6 @@ NTSTATUS FASTCALL InitWindowImpl(VOID) { - WndProcHandlesArray = ExAllocatePoolWithTag(PagedPool,WPH_SIZE * sizeof(WndProcHandle), TAG_WINPROCLST); - WndProcHandlesArraySize = WPH_SIZE; return STATUS_SUCCESS; }
@@ -67,9 +61,6 @@ NTSTATUS FASTCALL CleanupWindowImpl(VOID) { - ExFreePool(WndProcHandlesArray); - WndProcHandlesArray = 0; - WndProcHandlesArraySize = 0; return STATUS_SUCCESS; }
@@ -95,15 +86,26 @@ /* temp hack */ PWINDOW_OBJECT FASTCALL UserGetWindowObject(HWND hWnd) { + PW32THREADINFO ti; PWINDOW_OBJECT Window; - + + if (PsGetCurrentProcess() != PsInitialSystemProcess) + { + ti = GetW32ThreadInfo(); + if (ti == NULL) + { + SetLastWin32Error(ERROR_ACCESS_DENIED); + return NULL; + } + } + if (!hWnd) { SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE); return NULL; }
- Window = (PWINDOW_OBJECT)UserGetObject(&gHandleTable, hWnd, otWindow); + Window = (PWINDOW_OBJECT)UserGetObject(gHandleTable, hWnd, otWindow); if (!Window || 0 != (Window->Status & WINDOWSTATUS_DESTROYED)) { SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE); @@ -432,8 +434,16 @@
IntDestroyScrollBars(Window);
+ if (!Window->Class->System && Window->CallProc != NULL) + { + DestroyCallProc(Window->ti->Desktop, + Window->CallProc); + } + /* dereference the class */ - ClassDerefObject(Window->Class); + IntDereferenceClass(Window->Class, + Window->ti->Desktop, + Window->ti->kpi); Window->Class = NULL;
if(Window->WindowRegion) @@ -473,6 +483,57 @@ *cx = *cy = 0; } } +} + +static WNDPROC +IntGetWindowProc(IN PWINDOW_OBJECT Window, + IN BOOL Ansi) +{ + if (Window->IsSystem) + { + return (Ansi ? Window->WndProcExtra : Window->WndProc); + } + else + { + if (!Ansi == Window->Unicode) + { + return Window->WndProc; + } + else + { + if (Window->CallProc != NULL) + { + return (WNDPROC)ObmObjectToHandle(Window->CallProc); + } + else + { + PCALLPROC NewCallProc, CallProc; + + /* NOTE: use the interlocked functions, as this operation may be done even + when only the shared lock is held! */ + NewCallProc = CreateCallProc(Window->ti->Desktop, + Window->WndProc, + Window->Unicode, + Window->ti->kpi); + if (NewCallProc == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + CallProc = InterlockedCompareExchangePointer(&Window->CallProc, + NewCallProc, + NULL); + if (CallProc != NULL) + { + DestroyCallProc(Window->ti->Desktop, + NewCallProc); + } + + return (WNDPROC)ObmObjectToHandle((CallProc == NULL ? NewCallProc : CallProc)); + } + } + } }
BOOL FASTCALL @@ -1333,7 +1394,8 @@ BOOL bUnicodeWindow) { PWINSTATION_OBJECT WinSta; - PWNDCLASS_OBJECT Class = NULL; + PWINDOWCLASS Class = NULL; + RTL_ATOM ClassAtom; PWINDOW_OBJECT Window = NULL; PWINDOW_OBJECT ParentWindow = NULL, OwnerWindow; HWND ParentWindowHandle; @@ -1342,6 +1404,7 @@ HWND hWnd; POINT Pos; SIZE Size; + PW32THREADINFO ti = NULL; #if 0
POINT MaxSize, MaxPos, MinTrack, MaxTrack; @@ -1349,7 +1412,6 @@
POINT MaxPos; #endif - CREATESTRUCTW Cs; CBT_CREATEWNDW CbtCreate; LRESULT Result; @@ -1399,13 +1461,27 @@
/* FIXME: parent must belong to the current process */
+ /* Check the window station. */ + ti = GetW32ThreadInfo(); + if (ti == NULL || PsGetWin32Thread()->Desktop == NULL) + { + DPRINT1("Thread is not attached to a desktop! Cannot create window!\n"); + RETURN( (HWND)0); + } + /* Check the class. */ - Class = ClassGetClassByNameOrAtom(ClassName->Buffer, hInstance); - if (!Class) + + ClassAtom = IntGetClassAtom(ClassName, + hInstance, + ti->kpi, + &Class, + NULL); + + if (ClassAtom == (RTL_ATOM)0) { if (IS_ATOM(ClassName->Buffer)) { - DPRINT1("Class 0x%x not found\n", (DWORD_PTR) ClassName->Buffer); + DPRINT1("Class 0x%p not found\n", (DWORD_PTR) ClassName->Buffer); } else { @@ -1416,14 +1492,14 @@ RETURN((HWND)0); }
- ClassRefObject(Class); - - /* Check the window station. */ - if (PsGetWin32Thread()->Desktop == NULL) - { - DPRINT("Thread is not attached to a desktop! Cannot create window!\n"); - RETURN( (HWND)0); - } + Class = IntReferenceClass(Class, + ti->Desktop); + if (Class == NULL) + { + DPRINT1("Failed to reference window class!\n"); + RETURN(NULL); + } + WinSta = PsGetWin32Thread()->Desktop->WindowStation;
//FIXME: Reference thread/desktop instead @@ -1431,8 +1507,8 @@
/* Create the window object. */ Window = (PWINDOW_OBJECT) - ObmCreateObject(&gHandleTable, (PHANDLE)&hWnd, - otWindow, sizeof(WINDOW_OBJECT) + Class->cbWndExtra + ObmCreateObject(gHandleTable, (PHANDLE)&hWnd, + otWindow, sizeof(WINDOW_OBJECT) + Class->WndExtra );
DPRINT("Created object with handle %X\n", hWnd); @@ -1456,6 +1532,7 @@ /* * Fill out the structure describing it. */ + Window->ti = ti; Window->Class = Class; Window->SystemMenu = (HMENU)0; Window->ContextHelpId = 0; @@ -1474,7 +1551,7 @@ { IntSetMenu(Window, hMenu, &MenuChanged); } - + Window->MessageQueue = PsGetWin32Thread()->MessageQueue; IntReferenceMessageQueue(Window->MessageQueue); Window->Parent = ParentWindow; @@ -1491,27 +1568,38 @@ }
Window->UserData = 0; - - if ((((DWORD)Class->lpfnWndProcA & 0xFFFF0000) != 0xFFFF0000) - && (((DWORD)Class->lpfnWndProcW & 0xFFFF0000) != 0xFFFF0000)) - { - Window->Unicode = bUnicodeWindow; + + Window->IsSystem = Class->System; + if (Class->System) + { + Window->Unicode = bUnicodeWindow; + if (bUnicodeWindow) + { + Window->WndProc = Class->WndProc; + Window->WndProcExtra = Class->WndProcExtra; + } + else + { + Window->WndProc = Class->WndProcExtra; + Window->WndProcExtra = Class->WndProc; + } } else { - Window->Unicode = Class->Unicode; - } - Window->WndProcA = Class->lpfnWndProcA; - Window->WndProcW = Class->lpfnWndProcW; + Window->Unicode = Class->Unicode; + Window->WndProc = Class->WndProc; + Window->CallProc = NULL; + } + Window->OwnerThread = PsGetCurrentThread(); Window->FirstChild = NULL; Window->LastChild = NULL; Window->PrevSibling = NULL; Window->NextSibling = NULL; - Window->ExtraDataSize = Class->cbWndExtra; + Window->ExtraDataSize = Class->WndExtra;
/* extra window data */ - if (Class->cbWndExtra) + if (Class->WndExtra) Window->ExtraData = (PCHAR)(Window + 1);
InitializeListHead(&Window->PropListHead); @@ -1535,7 +1623,6 @@ { RtlInitUnicodeString(&Window->WindowName, NULL); } -
/* * This has been tested for WS_CHILD | WS_VISIBLE. It has not been @@ -1931,7 +2018,15 @@ CLEANUP: if (Window) UserDerefObjectCo(Window); if (ParentWindow) UserDerefObjectCo(ParentWindow); - if (!_ret_ && Class) ClassDerefObject(Class); /* only deref if failure (return 0) */ + if (!_ret_ && ti != NULL) + { + if (Class != NULL) + { + IntDereferenceClass(Class, + ti->Desktop, + ti->kpi); + } + } END_CLEANUP; }
@@ -1967,7 +2062,7 @@ SetLastNtError(Status); RETURN( NULL); } - if (! IS_ATOM(ClassName.Buffer)) + if (ClassName.Length != 0) { Status = IntSafeCopyUnicodeStringTerminateNULL(&ClassName, UnsafeClassName); if (! NT_SUCCESS(Status)) @@ -1975,6 +2070,11 @@ SetLastNtError(Status); RETURN( NULL); } + } + else if (! IS_INTRESOURCE(ClassName.Buffer)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return NULL; }
/* safely copy the window name */ @@ -3254,10 +3354,8 @@ break;
case GWL_WNDPROC: - if (Ansi) - Result = (LONG) Window->WndProcA; - else - Result = (LONG) Window->WndProcW; + Result = (LONG)IntGetWindowProc(Window, + Ansi); break;
case GWL_HINSTANCE: @@ -3390,22 +3488,28 @@ break;
case GWL_WNDPROC: + { /* FIXME: should check if window belongs to current process */ - if (Ansi) + if (Window->IsSystem) { - OldValue = (LONG) Window->WndProcA; - Window->WndProcA = (WNDPROC) NewValue; - Window->WndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,FALSE); - Window->Unicode = FALSE; + /* the user changes the window procedure, the window is no longer + directly derived from the system class, because it no longer + uses independent window procedures for ansi and unicode */ + Window->IsSystem = FALSE; + Window->CallProc = NULL; } - else + + /* update the window procedure */ + OldValue = (LONG)Window->WndProc; + Window->WndProc = (WNDPROC)NewValue; + if (Window->CallProc != NULL) { - OldValue = (LONG) Window->WndProcW; - Window->WndProcW = (WNDPROC) NewValue; - Window->WndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,TRUE); - Window->Unicode = TRUE; + Window->CallProc->WndProc = (WNDPROC)NewValue; + Window->CallProc->Unicode = !Ansi; } + Window->Unicode = !Ansi; break; + }
case GWL_HINSTANCE: OldValue = (LONG) Window->Instance; @@ -4404,99 +4508,6 @@ END_CLEANUP; }
-DWORD STDCALL -NtUserDereferenceWndProcHandle(WNDPROC wpHandle, WndProcHandle *Data) -{ - DECLARE_RETURN(DWORD); - WndProcHandle Entry; - - DPRINT("Enter NtUserDereferenceWndProcHandle\n"); - UserEnterShared(); - - if (((DWORD)wpHandle & 0xFFFF0000) == 0xFFFF0000) - { - Entry = WndProcHandlesArray[(DWORD)wpHandle & 0x0000FFFF]; - Data->WindowProc = Entry.WindowProc; - Data->IsUnicode = Entry.IsUnicode; - Data->ProcessID = Entry.ProcessID; - RETURN( TRUE); - } - else - { - RETURN( FALSE); - } - RETURN( FALSE); - -CLEANUP: - DPRINT("Leave NtUserDereferenceWndProcHandle, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} - -DWORD -IntAddWndProcHandle(WNDPROC WindowProc, BOOL IsUnicode) -{ - WORD i; - WORD FreeSpot = 0; - BOOL found; - WndProcHandle *OldArray; - WORD OldArraySize; - found = FALSE; - for (i = 0;i < WndProcHandlesArraySize;i++) - { - if (WndProcHandlesArray[i].WindowProc == NULL) - { - FreeSpot = i; - found = TRUE; - } - } - if (!found) - { - OldArray = WndProcHandlesArray; - OldArraySize = WndProcHandlesArraySize; - WndProcHandlesArray = ExAllocatePoolWithTag(PagedPool,(OldArraySize + WPH_SIZE) * sizeof(WndProcHandle), TAG_WINPROCLST); - WndProcHandlesArraySize = OldArraySize + WPH_SIZE; - RtlCopyMemory(WndProcHandlesArray,OldArray,OldArraySize * sizeof(WndProcHandle)); - ExFreePool(OldArray); - FreeSpot = OldArraySize + 1; - } - WndProcHandlesArray[FreeSpot].WindowProc = WindowProc; - WndProcHandlesArray[FreeSpot].IsUnicode = IsUnicode; - WndProcHandlesArray[FreeSpot].ProcessID = PsGetCurrentProcessId(); - return FreeSpot + 0xFFFF0000; -} - -DWORD -IntRemoveWndProcHandle(WNDPROC Handle) -{ - WORD position; - position = (DWORD)Handle & 0x0000FFFF; - if (position > WndProcHandlesArraySize) - { - return FALSE; - } - WndProcHandlesArray[position].WindowProc = NULL; - WndProcHandlesArray[position].IsUnicode = FALSE; - WndProcHandlesArray[position].ProcessID = NULL; - return TRUE; -} - -DWORD -IntRemoveProcessWndProcHandles(HANDLE ProcessID) -{ - WORD i; - for (i = 0;i < WndProcHandlesArraySize;i++) - { - if (WndProcHandlesArray[i].ProcessID == ProcessID) - { - WndProcHandlesArray[i].WindowProc = NULL; - WndProcHandlesArray[i].IsUnicode = FALSE; - WndProcHandlesArray[i].ProcessID = NULL; - } - } - return TRUE; -} - #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
BOOL
Modified: trunk/reactos/subsystems/win32/win32k/w32k.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/w32k... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/w32k.h (original) +++ trunk/reactos/subsystems/win32/win32k/w32k.h Wed Apr 5 12:05:55 2006 @@ -1,3 +1,5 @@ +#ifndef __W32K_H +#define __W32K_H /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Graphics Subsystem @@ -68,3 +70,77 @@ #define M_PI_2 1.57079632679489661923 #endif
+/* User heap */ +extern HANDLE GlobalUserHeap; + +HANDLE +UserCreateHeap(OUT PSECTION_OBJECT *SectionObject, + IN OUT PVOID *SystemBase, + IN ULONG HeapSize); + +static __inline PVOID +UserHeapAlloc(SIZE_T Bytes) +{ + return RtlAllocateHeap(GlobalUserHeap, + HEAP_NO_SERIALIZE, + Bytes); +} + +static __inline BOOL +UserHeapFree(PVOID lpMem) +{ + return RtlFreeHeap(GlobalUserHeap, + HEAP_NO_SERIALIZE, + lpMem); +} + +static __inline PVOID +UserHeapReAlloc(PVOID lpMem, + SIZE_T Bytes) +{ +#if 0 + /* NOTE: ntoskrnl doesn't export RtlReAllocateHeap... */ + return RtlReAllocateHeap(GlobalUserHeap, + HEAP_NO_SERIALIZE, + lpMem, + Bytes); +#else + SIZE_T PrevSize; + PVOID pNew; + + PrevSize = RtlSizeHeap(GlobalUserHeap, + HEAP_NO_SERIALIZE, + lpMem); + + if (PrevSize == Bytes) + return lpMem; + + pNew = RtlAllocateHeap(GlobalUserHeap, + HEAP_NO_SERIALIZE, + Bytes); + if (pNew != NULL) + { + if (PrevSize < Bytes) + Bytes = PrevSize; + + RtlCopyMemory(pNew, + lpMem, + Bytes); + + RtlFreeHeap(GlobalUserHeap, + HEAP_NO_SERIALIZE, + lpMem); + } + + return pNew; +#endif +} + +static __inline PVOID +UserHeapAddressToUser(PVOID lpMem) +{ + return (PVOID)(((ULONG_PTR)lpMem - (ULONG_PTR)GlobalUserHeap) + + (ULONG_PTR)PsGetWin32Process()->HeapMappings.UserMapping); +} + +#endif /* __W32K_H */
Modified: trunk/reactos/subsystems/win32/win32k/win32k.rbuild URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/win3... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/win32k.rbuild (original) +++ trunk/reactos/subsystems/win32/win32k/win32k.rbuild Wed Apr 5 12:05:55 2006 @@ -64,14 +64,15 @@ <file>err.c</file> <file>math.c</file> <file>copy.c</file> + <file>usrheap.c</file> </compilationunit> <directory name="i386"> - <file>cos_asm.s</file> - <file>sin_asm.s</file> - <file>atan2_asm.s</file> - <file>floor_asm.s</file> - <file>ceil_asm.s</file> - </directory> + <file>cos_asm.s</file> + <file>sin_asm.s</file> + <file>atan2_asm.s</file> + <file>floor_asm.s</file> + <file>ceil_asm.s</file> + </directory> </directory> <directory name="ntddraw"> <compilationunit name="ntddraw.c">
Modified: trunk/reactos/tools/nci/w32ksvc.db URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/tools/nci/w32ksvc.db?rev=214... ============================================================================== --- trunk/reactos/tools/nci/w32ksvc.db (original) +++ trunk/reactos/tools/nci/w32ksvc.db Wed Apr 5 12:05:55 2006 @@ -356,7 +356,7 @@ NtUserGetCapture 0 NtUserGetCaretBlinkTime 0 NtUserGetCaretPos 1 -NtUserGetClassInfo 5 +NtUserGetClassInfo 4 NtUserGetClassLong 3 NtUserGetClassName 3 NtUserGetClientOrigin 2 @@ -457,7 +457,7 @@ NtUserReleaseDC 2 NtUserRealChildWindowFromPoint 3 NtUserRedrawWindow 4 -NtUserRegisterClassExWOW 8 +NtUserRegisterClassEx 6 NtUserRegisterHotKey 4 NtUserRegisterTasklist 1 NtUserRegisterWindowMessage 1 @@ -536,7 +536,7 @@ NtUserUnhookWinEvent 1 NtUserUnloadKeyboardLayout 1 NtUserUnlockWindowStation 1 -NtUserUnregisterClass 3 +NtUserUnregisterClass 2 NtUserUnregisterHotKey 2 NtUserUpdateInputContext 3 NtUserUpdateInstance 3