diff --git a/reactos/include/user32/callback.h b/reactos/include/user32/callback.h index 5a9d7b45ec8..3e30731702f 100644 --- a/reactos/include/user32/callback.h +++ b/reactos/include/user32/callback.h @@ -2,7 +2,10 @@ #define __INCLUDE_USER32_CALLBACK_H #define USER32_CALLBACK_WINDOWPROC (0) -#define USER32_CALLBACK_MAXIMUM (1) +#define USER32_CALLBACK_SENDASYNCPROC (1) +#define USER32_CALLBACK_SENDNCCREATE (2) +#define USER32_C +#define USER32_CALLBACK_MAXIMUM (3) typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS { @@ -13,7 +16,27 @@ typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS LPARAM lParam; } WINDOWPROC_CALLBACK_ARGUMENTS, *PWINDOWPROC_CALLBACK_ARGUMENTS; +typedef struct _SENDASYNCPROC_CALLBACK_ARGUMENTS +{ + SENDASYNCPROC Proc; + HWND Wnd; + UINT Msg; + ULONG Data; + LRESULT Result; +} SENDASYNCPROC_CALLBACK_ARGUMENTS, *PSENDASYNCPROC_CALLBACK_ARGUMENTS; + +typedef struct _SENDNCREATEMESSAGE_CALLBACK_ARGUMENTS +{ + HWND Wnd; + CREATESTRUCT CreateStruct; +} SENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS, + *PSENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS; + NTSTATUS STDCALL User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength); +NTSTATUS STDCALL +User32CallSendAsyncProcForKernel(PVOID Arguments, ULONG ArgumentLength); +NTSTATUS STDCALL +User32SendNCCREATEMessageForKernel(PVOID Arguments, ULONG ArgumentLength); #endif /* __INCLUDE_USER32_CALLBACK_H */ diff --git a/reactos/include/win32k/ntuser.h b/reactos/include/win32k/ntuser.h index 73655d34908..78c0a569798 100644 --- a/reactos/include/win32k/ntuser.h +++ b/reactos/include/win32k/ntuser.h @@ -162,13 +162,11 @@ NtUserCheckMenuItem( DWORD Unknown1, DWORD Unknown2); -DWORD -STDCALL -NtUserChildWindowFromPointEx( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3); +DWORD STDCALL +NtUserChildWindowFromPointEx(HWND Parent, + LONG x, + LONG y, + UINT Flags); DWORD STDCALL @@ -287,18 +285,15 @@ NtUserDdeSetQualityOfService( DWORD Unknown1, DWORD Unknown2); -DWORD -STDCALL -NtUserDeferWindowPos( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3, - DWORD Unknown4, - DWORD Unknown5, - DWORD Unknown6, - DWORD Unknown7); - +DWORD STDCALL +NtUserDeferWindowPos(HDWP WinPosInfo, + HWND Wnd, + HWND WndInsertAfter, + LONG x, + LONG y, + LONG cx, + LONG cy, + UINT Flags); DWORD STDCALL NtUserDefSetText( @@ -328,10 +323,8 @@ STDCALL NtUserDestroyMenu( DWORD Unknown0); -DWORD -STDCALL -NtUserDestroyWindow( - DWORD Unknown0); +BOOLEAN STDCALL +NtUserDestroyWindow(HWND Wnd); LRESULT STDCALL @@ -1126,10 +1119,8 @@ STDCALL NtUserRegisterTasklist( DWORD Unknown0); -DWORD -STDCALL -NtUserRegisterWindowMessage( - DWORD Unknown0); +UINT STDCALL +NtUserRegisterWindowMessage(LPCWSTR MessageName); DWORD STDCALL diff --git a/reactos/lib/user32/misc/dllmain.c b/reactos/lib/user32/misc/dllmain.c index 8e720956cfc..7ebb88cdd11 100644 --- a/reactos/lib/user32/misc/dllmain.c +++ b/reactos/lib/user32/misc/dllmain.c @@ -25,6 +25,10 @@ Init(VOID) /* Set up the kernel callbacks. */ NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_WINDOWPROC] = (PVOID)User32CallWindowProcFromKernel; + NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_SENDASYNCPROC] = + (PVOID)User32CallSendAsyncProcForKernel; + NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_SENDNCCREATE] = + (PVOID)User32SendNCCREATEMessageForKernel; //ProcessWindowStation = CreateWindowStationW(L"WinStaName",0,GENERIC_ALL,NULL); //Desktop = CreateDesktopA(NULL,NULL,NULL,0,0,NULL); diff --git a/reactos/lib/user32/misc/stubs.c b/reactos/lib/user32/misc/stubs.c index 932262f9a2e..2cc394bb011 100644 --- a/reactos/lib/user32/misc/stubs.c +++ b/reactos/lib/user32/misc/stubs.c @@ -1,4 +1,4 @@ -/* $Id: stubs.c,v 1.6 2001/11/03 16:48:06 chorns Exp $ +/* $Id: stubs.c,v 1.7 2002/05/06 22:20:31 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -3358,21 +3358,6 @@ RegisterHotKey( return FALSE; } -UINT -STDCALL -RegisterWindowMessageA( - LPCSTR lpString) -{ - return 0; -} - -UINT -STDCALL -RegisterWindowMessageW( - LPCWSTR lpString) -{ - return 0; -} WINBOOL STDCALL diff --git a/reactos/lib/user32/windows/message.c b/reactos/lib/user32/windows/message.c index 918dcc52a99..26b950d2365 100644 --- a/reactos/lib/user32/windows/message.c +++ b/reactos/lib/user32/windows/message.c @@ -1,4 +1,4 @@ -/* $Id: message.c,v 1.4 2001/06/12 17:50:27 chorns Exp $ +/* $Id: message.c,v 1.5 2002/05/06 22:20:31 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -266,4 +266,28 @@ WaitMessage(VOID) return FALSE; } +UINT STDCALL +RegisterWindowMessageA(LPCSTR lpString) +{ + UNICODE_STRING String; + BOOLEAN Result; + UINT Atom; + + Result = RtlCreateUnicodeStringFromAsciiz(&String, lpString); + if (!Result) + { + return(0); + } + Atom = RegisterWindowMessageW(String.Buffer); + RtlFreeUnicodeString(&String); + return(Atom); +} + +UINT STDCALL +RegisterWindowMessageW(LPCWSTR lpString) +{ + return(NtUserRegisterWindowMessage(lpString)); +} + + /* EOF */ diff --git a/reactos/lib/user32/windows/window.c b/reactos/lib/user32/windows/window.c index c37ae119092..14b3e0992f8 100644 --- a/reactos/lib/user32/windows/window.c +++ b/reactos/lib/user32/windows/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.4 2002/01/27 01:11:23 dwelch Exp $ +/* $Id: window.c,v 1.5 2002/05/06 22:20:31 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -19,6 +19,40 @@ /* FUNCTIONS *****************************************************************/ +NTSTATUS STDCALL +User32SendNCCREATEMessageForKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PSENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS CallbackArgs; + WNDPROC Proc; + LRESULT Result; + + CallbackArgs = (PSENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS)Arguments; + if (ArgumentLength != sizeof(SENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS)) + { + return(STATUS_INFO_LENGTH_MISMATCH); + } + Proc = (WNDPROC)GetWindowLong(CallbackArgs->Wnd, GWL_WNDPROC); + Result = CallWindowProc(Proc, CallbackArgs->Wnd, WM_NCCREATE, 0, + (LPARAM)&CallbackArgs->CreateStruct); + ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS); + /* Doesn't return. */ +} + +NTSTATUS STDCALL +User32CallSendAsyncProcForKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PSENDASYNCPROC_CALLBACK_ARGUMENTS CallbackArgs; + + CallbackArgs = (PSENDASYNCPROC_CALLBACK_ARGUMENTS)Arguments; + if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)) + { + return(STATUS_INFO_LENGTH_MISMATCH); + } + CallbackArgs->Proc(CallbackArgs->Wnd, CallbackArgs->Msg, + CallbackArgs->Data, CallbackArgs->Result); + return(STATUS_SUCCESS); +} + NTSTATUS STDCALL User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength) { @@ -30,8 +64,14 @@ User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength) { return(STATUS_INFO_LENGTH_MISMATCH); } - Result = CallbackArgs->Proc(CallbackArgs->Wnd, CallbackArgs->Msg, - CallbackArgs->wParam, CallbackArgs->lParam); + if (CallbackArgs->Proc == NULL) + { + CallbackArgs->Proc = (WNDPROC)GetWindowLong(CallbackArgs->Wnd, + GWL_WNDPROC); + } + Result = CallWindowProc(CallbackArgs->Proc, CallbackArgs->Wnd, + CallbackArgs->Msg, CallbackArgs->wParam, + CallbackArgs->lParam); ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS); /* Doesn't return. */ } @@ -133,6 +173,7 @@ CreateWindowExA(DWORD dwExStyle, UNICODE_STRING WindowName; UNICODE_STRING ClassName; HWND Handle; + INT sw; if (IS_ATOM(lpClassName)) { @@ -158,6 +199,56 @@ CreateWindowExA(DWORD dwExStyle, return (HWND)0; } + /* Fixup default coordinates. */ + sw = SW_SHOW; + if (x == CW_USEDEFAULT || nWidth == CW_USEDEFAULT) + { + if (dwStyle & (WS_CHILD | WS_POPUP)) + { + if (x == CW_USEDEFAULT) + { + x = y = 0; + } + if (nWidth == CW_USEDEFAULT) + { + nWidth = nHeight = 0; + } + } + else + { + STARTUPINFOA info; + + GetStartupInfoA(&info); + + if (x == CW_USEDEFAULT) + { + if (y != CW_USEDEFAULT) + { + sw = y; + } + x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0; + y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0; + } + + if (nWidth == CW_USEDEFAULT) + { + if (info.dwFlags & STARTF_USESIZE) + { + nWidth = info.dwXSize; + nHeight = info.dwYSize; + } + else + { + RECT r; + + SystemParametersInfoA(SPI_GETWORKAREA, 0, &r, 0); + nWidth = (((r.right - r.left) * 3) / 4) - x; + nHeight = (((r.bottom - r.top) * 3) / 4) - y; + } + } + } + } + Handle = NtUserCreateWindowEx(dwExStyle, &ClassName, &WindowName, @@ -170,7 +261,7 @@ CreateWindowExA(DWORD dwExStyle, hMenu, hInstance, lpParam, - 0); + sw); RtlFreeUnicodeString(&WindowName); @@ -199,6 +290,7 @@ CreateWindowExW(DWORD dwExStyle, UNICODE_STRING WindowName; UNICODE_STRING ClassName; HANDLE Handle; + UINT sw; if (IS_ATOM(lpClassName)) { @@ -212,6 +304,56 @@ CreateWindowExW(DWORD dwExStyle, RtlInitUnicodeString(&WindowName, lpWindowName); + /* Fixup default coordinates. */ + sw = SW_SHOW; + if (x == CW_USEDEFAULT || nWidth == CW_USEDEFAULT) + { + if (dwStyle & (WS_CHILD | WS_POPUP)) + { + if (x == CW_USEDEFAULT) + { + x = y = 0; + } + if (nWidth == CW_USEDEFAULT) + { + nWidth = nHeight = 0; + } + } + else + { + STARTUPINFOW info; + + GetStartupInfoW(&info); + + if (x == CW_USEDEFAULT) + { + if (y != CW_USEDEFAULT) + { + sw = y; + } + x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0; + y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0; + } + + if (nWidth == CW_USEDEFAULT) + { + if (info.dwFlags & STARTF_USESIZE) + { + nWidth = info.dwXSize; + nHeight = info.dwYSize; + } + else + { + RECT r; + + SystemParametersInfoW(SPI_GETWORKAREA, 0, &r, 0); + nWidth = (((r.right - r.left) * 3) / 4) - x; + nHeight = (((r.bottom - r.top) * 3) / 4) - y; + } + } + } + } + Handle = NtUserCreateWindowEx(dwExStyle, &ClassName, &WindowName, diff --git a/reactos/subsys/win32k/include/callback.h b/reactos/subsys/win32k/include/callback.h index 7ccdb4f7981..db404b8df02 100644 --- a/reactos/subsys/win32k/include/callback.h +++ b/reactos/subsys/win32k/include/callback.h @@ -7,5 +7,9 @@ W32kCallWindowProc(WNDPROC Proc, UINT Message, WPARAM wParam, LPARAM lParam); +LRESULT STDCALL +W32kSendNCCREATEMessage(HWND Wnd, CREATESTRUCT* CreateStruct); +LRESULT STDCALL +W32kSendCREATEMessage(HWND Wnd, CREATESTRUCT* CreateStruct); #endif /* __SUBSYS_WIN32K_INCLUDE_CALLBACK_H */ diff --git a/reactos/subsys/win32k/include/msgqueue.h b/reactos/subsys/win32k/include/msgqueue.h index 474d21e7a2e..a0909746d0a 100644 --- a/reactos/subsys/win32k/include/msgqueue.h +++ b/reactos/subsys/win32k/include/msgqueue.h @@ -9,11 +9,35 @@ typedef struct _USER_MESSAGE MSG Msg; } USER_MESSAGE, *PUSER_MESSAGE; +struct _USER_MESSAGE_QUEUE; + +typedef struct _USER_SENT_MESSAGE +{ + LIST_ENTRY ListEntry; + MSG Msg; + PKEVENT CompletionEvent; + LRESULT* Result; + struct _USER_MESSAGE_QUEUE* CompletionQueue; + SENDASYNCPROC CompletionCallback; + ULONG_PTR CompletionCallbackContext; +} USER_SENT_MESSAGE, *PUSER_SENT_MESSAGE; + +typedef struct _USER_SENT_MESSAGE_NOTIFY +{ + SENDASYNCPROC CompletionCallback; + ULONG_PTR CompletionCallbackContext; + LRESULT Result; + HWND hWnd; + UINT Msg; + LIST_ENTRY ListEntry; +} USER_SENT_MESSAGE_NOTIFY, *PUSER_SENT_MESSAGE_NOTIFY; + typedef struct _USER_MESSAGE_QUEUE { LIST_ENTRY SentMessagesListHead; LIST_ENTRY PostedMessagesListHead; LIST_ENTRY HardwareMessagesListHead; + LIST_ENTRY NotifyMessagesListHead; FAST_MUTEX Lock; BOOLEAN QuitPosted; ULONG QuitExitCode; @@ -22,7 +46,9 @@ typedef struct _USER_MESSAGE_QUEUE HWND FocusWindow; } USER_MESSAGE_QUEUE, *PUSER_MESSAGE_QUEUE; - +VOID +MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, + PUSER_SENT_MESSAGE Message); VOID MsqInitializeMessage(PUSER_MESSAGE Message, LPMSG Msg); @@ -57,6 +83,8 @@ MsqWaitForNewMessage(PUSER_MESSAGE_QUEUE MessageQueue); NTSTATUS MsqInitializeImpl(VOID); +#define MAKE_LONG(x, y) ((((y) & 0xFFFF) << 16) | ((x) & 0xFFFF)) + #endif /* __WIN32K_MSGQUEUE_H */ /* EOF */ diff --git a/reactos/subsys/win32k/include/window.h b/reactos/subsys/win32k/include/window.h index 96d09ad1edf..90b43ed072a 100644 --- a/reactos/subsys/win32k/include/window.h +++ b/reactos/subsys/win32k/include/window.h @@ -7,21 +7,46 @@ typedef struct _WINDOW_OBJECT { + /* Pointer to the window class. */ PWNDCLASS_OBJECT Class; + /* Extended style. */ DWORD ExStyle; + /* Window name. */ UNICODE_STRING WindowName; + /* Style. */ DWORD Style; - int x; - int y; - int Width; - int Height; - HWND Parent; + /* Initial window position. */ + INT x; + INT y; + INT Width; + INT Height; + /* Parent window handle. */ + HWND ParentHandle; + struct _WINDOW_OBJECT* Parent; + /* Window menu handle. */ HMENU Menu; + /* Handle of the module that created the window. */ HINSTANCE Instance; + /* Unknown. */ LPVOID Parameters; + /* Entry in the thread's list of windows. */ LIST_ENTRY ListEntry; + /* Pointer to the extra data associated with the window. */ + PULONG ExtraData; + /* Size of the extra data associated with the window. */ + ULONG ExtraDataSize; + /* Position of the window. */ + RECT WindowRect; + /* Position of the window's client area. */ + RECT ClientRect; + /* Handle for the window. */ + HANDLE Self; + /* Window flags. */ + ULONG Flags; + UINT IDMenu; } WINDOW_OBJECT, *PWINDOW_OBJECT; +#define WINDOWOBJECT_NEED_SIZE (0x00000001) NTSTATUS InitWindowImpl(VOID); diff --git a/reactos/subsys/win32k/include/winpos.h b/reactos/subsys/win32k/include/winpos.h new file mode 100644 index 00000000000..6593019175a --- /dev/null +++ b/reactos/subsys/win32k/include/winpos.h @@ -0,0 +1,12 @@ +LRESULT +WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect); +VOID +WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos, + POINT* MinTrack, POINT* MaxTrack); +VOID +WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos); +BOOLEAN +WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx, + INT cy, UINT flags); +BOOLEAN +WinPosShowWindow(HWND Wnd, INT Cmd); diff --git a/reactos/subsys/win32k/makefile b/reactos/subsys/win32k/makefile index 747e99bfb03..fbc1b86b2c3 100644 --- a/reactos/subsys/win32k/makefile +++ b/reactos/subsys/win32k/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.42 2002/01/27 01:11:24 dwelch Exp $ +# $Id: makefile,v 1.43 2002/05/06 22:20:32 dwelch Exp $ PATH_TO_TOP = ../.. @@ -24,7 +24,8 @@ LDR_OBJECTS = ldr/loader.o NTUSER_OBJECTS = ntuser/class.o ntuser/guicheck.o ntuser/hook.o \ ntuser/message.o ntuser/msgqueue.o ntuser/stubs.o \ ntuser/userobj.o ntuser/window.o ntuser/winsta.o \ - ntuser/input.o ntuser/keyboard.o ntuser/callback.o + ntuser/input.o ntuser/keyboard.o ntuser/callback.o \ + ntuser/winpos.o OBJECTS_OBJECTS = objects/bitmaps.o objects/brush.o objects/cliprgn.o \ objects/color.o objects/coord.o objects/dc.o \ objects/fillshap.o objects/gdiobj.o objects/icm.o \ diff --git a/reactos/subsys/win32k/ntuser/callback.c b/reactos/subsys/win32k/ntuser/callback.c index bea5098ca10..db5561bc7e9 100644 --- a/reactos/subsys/win32k/ntuser/callback.c +++ b/reactos/subsys/win32k/ntuser/callback.c @@ -1,4 +1,4 @@ -/* $Id: callback.c,v 1.1 2002/01/27 14:47:44 dwelch Exp $ +/* $Id: callback.c,v 1.2 2002/05/06 22:20:32 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -25,6 +25,51 @@ /* FUNCTIONS *****************************************************************/ +VOID STDCALL +W32kCallSentMessageCallback(SENDASYNCPROC CompletionCallback, + HWND hWnd, + UINT Msg, + ULONG_PTR CompletionCallbackContext, + LRESULT Result) +{ +} + +LRESULT STDCALL +W32kSendNCCALCSIZEMessage(HWND Wnd, BOOL Validate, RECT Rect1, + RECT Rect2, RECT Rect3, PWINDOWPOS Pos) +{ +} + +LRESULT STDCALL +W32kSendCREATEMessage(HWND Wnd, CREATESTRUCT* CreateStruct) +{ +} + +LRESULT STDCALL +W32kSendNCCREATEMessage(HWND Wnd, CREATESTRUCT* CreateStruct) +{ + SENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS Arguments; + LRESULT Result; + NTSTATUS Status; + PVOID ResultPointer; + DWORD ResultLength; + + Arguments.Wnd = Wnd; + Arguments.CreateStruct = *CreateStruct; + ResultPointer = &Result; + ResultLength = sizeof(LRESULT); + Status = NtW32Call(USER32_CALLBACK_WINDOWPROC, + &Arguments, + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS), + &ResultPointer, + &ResultLength); + if (!NT_SUCCESS(Status)) + { + return(0); + } + return(Result); +} + LRESULT STDCALL W32kCallWindowProc(WNDPROC Proc, HWND Wnd, diff --git a/reactos/subsys/win32k/ntuser/message.c b/reactos/subsys/win32k/ntuser/message.c index 245c005a039..240d972bf3b 100644 --- a/reactos/subsys/win32k/ntuser/message.c +++ b/reactos/subsys/win32k/ntuser/message.c @@ -1,4 +1,4 @@ -/* $Id: message.c,v 1.4 2002/01/27 01:11:24 dwelch Exp $ +/* $Id: message.c,v 1.5 2002/05/06 22:20:32 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -221,6 +221,14 @@ NtUserQuerySendMessage(DWORD Unknown0) return 0; } +BOOL STDCALL +NtUserSendMessage(HWND hWnd, + UINT Msg, + WPARAM Wparam, + LPARAM lParam) +{ +} + BOOL STDCALL NtUserSendMessageCallback(HWND hWnd, UINT Msg, diff --git a/reactos/subsys/win32k/ntuser/msgqueue.c b/reactos/subsys/win32k/ntuser/msgqueue.c index 6e3defb7961..451c055b54c 100644 --- a/reactos/subsys/win32k/ntuser/msgqueue.c +++ b/reactos/subsys/win32k/ntuser/msgqueue.c @@ -1,4 +1,4 @@ -/* $Id: msgqueue.c,v 1.2 2002/01/13 22:52:08 dwelch Exp $ +/* $Id: msgqueue.c,v 1.3 2002/05/06 22:20:32 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -76,6 +76,103 @@ MsqDestroyMessage(PUSER_MESSAGE Message) ExFreePool(Message); } +VOID +MsqDispatchSentNotifyMessages(PUSER_MESSAGE_QUEUE MessageQueue) +{ + PLIST_ENTRY ListEntry; + PUSER_SENT_MESSAGE_NOTIFY Message; + + while (!IsListEmpty(&MessageQueue->SentMessagesListHead)) + { + ExAcquireFastMutex(&MessageQueue->Lock); + ListEntry = RemoveHeadList(&MessageQueue->SentMessagesListHead); + Message = CONTAINING_RECORD(ListEntry, USER_SENT_MESSAGE_NOTIFY, + ListEntry); + ExReleaseFastMutex(&MessageQueue->Lock); + + W32kCallSentMessageCallback(Message->CompletionCallback, + Message->hWnd, + Message->Msg, + Message->CompletionCallbackContext, + Message->Result); + } +} + +BOOLEAN +MsqPeekSentMessages(PUSER_MESSAGE_QUEUE MessageQueue) +{ + return(!IsListEmpty(&MessageQueue->SentMessagesListHead)); +} + +VOID +MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue) +{ + PUSER_SENT_MESSAGE Message; + PLIST_ENTRY Entry; + LRESULT Result; + PUSER_SENT_MESSAGE_NOTIFY NotifyMessage; + + ExAcquireFastMutex(&MessageQueue->Lock); + Entry = RemoveHeadList(&MessageQueue->SentMessagesListHead); + Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry); + ExReleaseFastMutex(&MessageQueue->Lock); + + /* Call the window procedure. */ + Result = W32kCallWindowProc(W32kGetWindowProc(Message->Msg.hwnd), + Message->Msg.hwnd, + Message->Msg.message, + Message->Msg.wParam, + Message->Msg.lParam); + + /* Let the sender know the result. */ + if (Message->Result != NULL) + { + *Message->Result = Result; + } + + /* Notify the sender. */ + if (Message->CompletionEvent != NULL) + { + KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE); + } + + /* Notify the sender if they specified a callback. */ + if (Message->CompletionCallback != NULL) + { + NotifyMessage = ExAllocatePool(NonPagedPool, + sizeof(USER_SENT_MESSAGE_NOTIFY)); + NotifyMessage->CompletionCallback = + Message->CompletionCallback; + NotifyMessage->CompletionCallbackContext = + Message->CompletionCallbackContext; + NotifyMessage->Result = Result; + NotifyMessage->hWnd = Message->Msg.hwnd; + NotifyMessage->Msg = Message->Msg.message; + MsqSendNotifyMessage(Message->CompletionQueue); + } + + ExFreePool(Message); +} + +VOID +MsqSendNotifyMessage(PUSER_MESSAGE_QUEUE MessageQueue, + PUSER_SENT_MESSAGE_NOTIFY NotifyMessage) +{ + ExAcquireFastMutex(&MessageQueue->Lock); + InsertTailList(&MessageQueue->NotifyMessagesListHead, + &NotifyMessage->ListEntry); + ExReleaseFastMutex(&MessageQueue->Lock); +} + +VOID +MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, + PUSER_SENT_MESSAGE Message) +{ + ExAcquireFastMutex(&MessageQueue->Lock); + InsertTailList(&MessageQueue->SentMessagesListHead, &Message->ListEntry); + ExReleaseFastMutex(&MessageQueue->Lock); +} + VOID MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, PUSER_MESSAGE Message, diff --git a/reactos/subsys/win32k/ntuser/window.c b/reactos/subsys/win32k/ntuser/window.c index 98ef5b6c775..73966898086 100644 --- a/reactos/subsys/win32k/ntuser/window.c +++ b/reactos/subsys/win32k/ntuser/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.5 2002/01/27 01:11:24 dwelch Exp $ +/* $Id: window.c,v 1.6 2002/05/06 22:20:32 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -18,12 +18,35 @@ #include #include #include +#include +#include +#include #define NDEBUG #include /* FUNCTIONS *****************************************************************/ +BOOL +W32kOffsetRect(LPRECT Rect, INT x, INT y) +{ + Rect->left += x; + Rect->right += x; + Rect->top += y; + Rect->bottom += y; + return(TRUE); +} + +HWND +W32kGetActiveWindow(VOID) +{ +} + +WNDPROC +W32kGetWindowProc(HWND Wnd) +{ +} + NTSTATUS InitWindowImpl(VOID) { @@ -48,10 +71,10 @@ NtUserAlterWindowStyle(DWORD Unknown0, } DWORD STDCALL -NtUserChildWindowFromPointEx(DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3) +NtUserChildWindowFromPointEx(HWND Parent, + LONG x, + LONG y, + UINT Flags) { UNIMPLEMENTED @@ -71,7 +94,7 @@ NtUserCreateWindowEx(DWORD dwExStyle, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam, - DWORD Unknown12) + DWORD dwShowMode) { PWINSTATION_OBJECT WinStaObject; PWNDCLASS_OBJECT ClassObject; @@ -79,22 +102,29 @@ NtUserCreateWindowEx(DWORD dwExStyle, UNICODE_STRING WindowName; NTSTATUS Status; HANDLE Handle; + POINT MaxSize, MaxPos, MinTrack, MaxTrack; + CREATESTRUCT Cs; + LRESULT Result; W32kGuiCheck(); + if (!RtlCreateUnicodeString(&WindowName, lpWindowName->Buffer)) + { + SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); + return((HWND)0); + } + + /* FIXME: Validate the parent window. */ + + /* Check the class. */ Status = ClassReferenceClassByNameOrAtom(&ClassObject, lpClassName->Buffer); if (!NT_SUCCESS(Status)) { - return (HWND)0; - } - - if (!RtlCreateUnicodeString(&WindowName, lpWindowName->Buffer)) - { - ObmDereferenceObject(ClassObject); - SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); - return (HWND)0; + RtlFreeUnicodeString(&WindowName); + return((HWND)0); } + /* Check the window station. */ Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(), KernelMode, 0, @@ -108,6 +138,7 @@ NtUserCreateWindowEx(DWORD dwExStyle, return (HWND)0; } + /* Create the window object. */ WindowObject = (PWINDOW_OBJECT) ObmCreateObject(PsGetWin32Process()->HandleTable, &Handle, otWindow, sizeof(WINDOW_OBJECT)); @@ -119,9 +150,11 @@ NtUserCreateWindowEx(DWORD dwExStyle, SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); return (HWND)0; } - ObDereferenceObject(WinStaObject); - + + /* + * Fill out the structure describing it. + */ WindowObject->Class = ClassObject; WindowObject->ExStyle = dwExStyle; WindowObject->Style = dwStyle; @@ -133,34 +166,181 @@ NtUserCreateWindowEx(DWORD dwExStyle, WindowObject->Menu = hMenu; WindowObject->Instance = hInstance; WindowObject->Parameters = lpParam; + WindowObject->Self = Handle; + + /* FIXME: Add the window parent. */ RtlInitUnicodeString(&WindowObject->WindowName, WindowName.Buffer); + RtlFreeUnicodeString(&WindowName); + + if (ClassObject->Class.cbWndExtra != 0) + { + WindowObject->ExtraData = + ExAllocatePool(PagedPool, + ClassObject->Class.cbWndExtra * sizeof(DWORD)); + WindowObject->ExtraDataSize = ClassObject->Class.cbWndExtra; + } + else + { + WindowObject->ExtraData = NULL; + WindowObject->ExtraDataSize = 0; + } + /* Correct the window style. */ + if (!(dwStyle & WS_CHILD)) + { + WindowObject->Style |= WS_CLIPSIBLINGS; + if (!(dwStyle & WS_POPUP)) + { + WindowObject->Style |= WS_CAPTION; + /* FIXME: Note the window needs a size. */ + } + } + + /* Insert the window into the process's window list. */ ExAcquireFastMutexUnsafe (&PsGetWin32Process()->WindowListLock); InsertTailList (&PsGetWin32Process()->WindowListHead, &WindowObject->ListEntry); ExReleaseFastMutexUnsafe (&PsGetWin32Process()->WindowListLock); - return (HWND)Handle; + /* FIXME: Maybe allocate a DCE for this window. */ + + /* Initialize the window dimensions. */ + WindowObject->WindowRect.left = x; + WindowObject->WindowRect.top = y; + WindowObject->WindowRect.right = x + nWidth; + WindowObject->WindowRect.bottom = y + nHeight; + WindowObject->ClientRect = WindowObject->WindowRect; + + /* + * Get the size and position of the window. + */ + if ((dwStyle & WS_THICKFRAME) || !(dwStyle & (WS_POPUP | WS_CHILD))) + { + WinPosGetMinMaxInfo(WindowObject, &MaxSize, &MaxPos, &MinTrack, + &MaxTrack); + x = min(MaxSize.x, y); + y = min(MaxSize.y, y); + x = max(MinTrack.x, x); + y = max(MinTrack.y, y); + } + + WindowObject->WindowRect.left = x; + WindowObject->WindowRect.top = y; + WindowObject->WindowRect.right = x + nWidth; + WindowObject->WindowRect.bottom = y + nHeight; + WindowObject->ClientRect = WindowObject->WindowRect; + + /* FIXME: Initialize the window menu. */ + + /* Send a NCCREATE message. */ + Cs.lpCreateParams = lpParam; + Cs.hInstance = hInstance; + Cs.hMenu = hMenu; + Cs.hwndParent = hWndParent; + Cs.cx = nWidth; + Cs.cy = nHeight; + Cs.x = x; + Cs.y = y; + Cs.style = dwStyle; + Cs.lpszName = lpWindowName->Buffer; + Cs.lpszClass = lpClassName->Buffer; + Cs.dwExStyle = dwExStyle; + Result = W32kSendNCCREATEMessage(WindowObject->Self, &Cs); + if (!Result) + { + /* FIXME: Cleanup. */ + return(NULL); + } + + /* Calculate the non-client size. */ + MaxPos.x = WindowObject->WindowRect.left; + MaxPos.y = WindowObject->WindowRect.top; + Result = WinPosGetNonClientSize(WindowObject->Self, + &WindowObject->WindowRect, + &WindowObject->ClientRect); + W32kOffsetRect(&WindowObject->WindowRect, + MaxPos.x - WindowObject->WindowRect.left, + MaxPos.y - WindowObject->WindowRect.top); + + /* Send the CREATE message. */ + Result = W32kSendCREATEMessage(WindowObject->Self, &Cs); + if (!Result) + { + /* FIXME: Cleanup. */ + return(NULL); + } + + /* Send move and size messages. */ + if (!(WindowObject->Flags & WINDOWOBJECT_NEED_SIZE)) + { + LONG lParam; + + lParam = + MAKE_LONG(WindowObject->ClientRect.right - + WindowObject->ClientRect.left, + WindowObject->ClientRect.bottom - + WindowObject->ClientRect.top); + W32kCallWindowProc(NULL, WindowObject->Self, WM_SIZE, SIZE_RESTORED, + lParam); + lParam = + MAKE_LONG(WindowObject->ClientRect.left, + WindowObject->ClientRect.top); + W32kCallWindowProc(NULL, WindowObject->Self, WM_MOVE, 0, lParam); + } + + /* Show or maybe minimize or maximize the window. */ + if (WindowObject->Style & (WS_MINIMIZE | WS_MAXIMIZE)) + { + RECT NewPos; + UINT16 SwFlag; + + SwFlag = (WindowObject->Style & WS_MINIMIZE) ? SW_MINIMIZE : + SW_MAXIMIZE; + WinPosMinMaximize(WindowObject, SwFlag, &NewPos); + SwFlag = + ((WindowObject->Style & WS_CHILD) || W32kGetActiveWindow()) ? + SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED : + SWP_NOZORDER | SWP_FRAMECHANGED; + WinPosSetWindowPos(WindowObject->Self, 0, NewPos.left, NewPos.top, + NewPos.right, NewPos.bottom, SwFlag); + } + + /* Notify the parent window of a new child. */ + if ((WindowObject->Style & WS_CHILD) || + (!(WindowObject->ExStyle & WS_EX_NOPARENTNOTIFY))) + { + W32kCallWindowProc(NULL, WindowObject->Parent->Self, + WM_PARENTNOTIFY, + MAKEWPARAM(WM_CREATE, WindowObject->IDMenu), + (LPARAM)WindowObject->Self); + } + + if (dwStyle & WS_VISIBLE) + { + WinPosShowWindow(WindowObject->Self, dwShowMode); + } + + return((HWND)Handle); } DWORD STDCALL -NtUserDeferWindowPos(DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3, - DWORD Unknown4, - DWORD Unknown5, - DWORD Unknown6, - DWORD Unknown7) +NtUserDeferWindowPos(HDWP WinPosInfo, + HWND Wnd, + HWND WndInsertAfter, + LONG x, + LONG y, + LONG cx, + LONG cy, + UINT Flags) { UNIMPLEMENTED return 0; } -DWORD STDCALL -NtUserDestroyWindow(DWORD Unknown0) +BOOLEAN STDCALL +NtUserDestroyWindow(HWND Wnd) { UNIMPLEMENTED @@ -348,12 +528,12 @@ NtUserRedrawWindow(DWORD Unknown0, return 0; } -DWORD STDCALL -NtUserRegisterWindowMessage(DWORD Unknown0) +UINT STDCALL +NtUserRegisterWindowMessage(LPCWSTR MessageName) { UNIMPLEMENTED - return 0; + return(0); } DWORD STDCALL diff --git a/reactos/subsys/win32k/ntuser/winpos.c b/reactos/subsys/win32k/ntuser/winpos.c new file mode 100644 index 00000000000..9751f257b73 --- /dev/null +++ b/reactos/subsys/win32k/ntuser/winpos.c @@ -0,0 +1,263 @@ +/* $Id: winpos.c,v 1.1 2002/05/06 22:20:32 dwelch Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Windows + * FILE: subsys/win32k/ntuser/window.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define MINMAX_NOSWP (0x00010000) + +/* FUNCTIONS *****************************************************************/ + +UINT +WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos) +{ +} + +UINT +WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos, + POINT* MaxTrack) +{ +} + +BOOLEAN +WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx, + INT cy, UINT flags) +{ + PWINDOW_OBJECT Window; + NTSTATUS Status; + + /* FIXME: Get current active window from active queue. */ + + /* FIXME: Check if the window is for a desktop. */ + + Status = ObmReferenceObjectByHandle(PsGetWin32Process()->HandleTable, + Wnd, + otWindow, + (PVOID*)&Window); + if (!NT_SUCCESS(Status)) + { + return(FALSE); + } + + /* Fix up the flags. */ + if (Window->Style & WS_VISIBLE) + { + flags &= ~SWP_SHOWWINDOW; + } + else + { + if (!(flags & SWP_SHOWWINDOW)) + { + flags |= SWP_NOREDRAW; + } + flags &= ~SWP_HIDEWINDOW; + } + + if (cx < 0) + { + cx = 0; + } + if (cy < 0) + { + cy = 0; + } + + +} + +LRESULT +WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect) +{ + LRESULT Result; + + Result = + W32kSendNCCALCSIZEMessage(Wnd, FALSE, WindowRect, NULL, + NULL, NULL, ClientRect); + return(Result); +} + +BOOLEAN +WinPosShowWindow(HWND Wnd, INT Cmd) +{ + BOOLEAN WasVisible; + PWINDOW_OBJECT Window; + NTSTATUS Status; + UINT Swp = 0; + RECT NewPos; + BOOLEAN ShowFlag; + + Status = ObmReferenceObjectByHandle(PsGetWin32Process()->HandleTable, + Wnd, + otWindow, + (PVOID*)&Window); + if (!NT_SUCCESS(Status)) + { + return(FALSE); + } + + WasVisible = (Window->Style & WS_VISIBLE) != 0; + + switch (Cmd) + { + case SW_HIDE: + { + if (!WasVisible) + { + ObmDereferenceObject(Window); + return(FALSE); + } + Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | + SWP_NOZORDER; + break; + } + + case SW_SHOWMINNOACTIVE: + Swp |= SWP_NOACTIVATE | SWP_NOZORDER; + /* Fall through. */ + case SW_SHOWMINIMIZED: + Swp |= SWP_SHOWWINDOW; + /* Fall through. */ + case SW_MINIMIZE: + { + Swp |= SWP_FRAMECHANGED; + if (!(Window->Style & WS_MINIMIZE)) + { + Swp |= WinPosMinMaximize(Window, SW_MINIMIZE, &NewPos); + } + else + { + Swp |= SWP_NOSIZE | SWP_NOMOVE; + } + break; + } + + case SW_SHOWMAXIMIZED: + { + Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED; + if (!(Window->Style & WS_MAXIMIZE)) + { + Swp |= WinPosMinMaximize(Window, SW_MAXIMIZE, &NewPos); + } + else + { + Swp |= SWP_NOSIZE | SWP_NOMOVE; + } + break; + } + + case SW_SHOWNA: + Swp |= SWP_NOACTIVATE | SWP_NOZORDER; + /* Fall through. */ + case SW_SHOW: + Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; + /* Don't activate the topmost window. */ + break; + + case SW_SHOWNOACTIVATE: + Swp |= SWP_NOZORDER; + /* Fall through. */ + case SW_SHOWNORMAL: + case SW_SHOWDEFAULT: + case SW_RESTORE: + Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED; + if (Window->Style & (WS_MINIMIZE | WS_MAXIMIZE)) + { + Swp |= WinPosMinMaximize(Window, SW_RESTORE, &NewPos); + } + else + { + Swp |= SWP_NOSIZE | SWP_NOMOVE; + } + break; + } + + ShowFlag = (Cmd != SW_HIDE); + if (ShowFlag != WasVisible) + { + NtUserSendMessage(Wnd, WM_SHOWWINDOW, ShowFlag, 0); + /* + * FIXME: Need to check the window wasn't destroyed during the + * window procedure. + */ + } + + if (Window->Style & WS_CHILD && + /* !IsWindowVisible(WindowObject->Parent->Self) && */ + (Swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE)) + { + if (Cmd == SW_HIDE) + { + Window->Style &= ~WS_VISIBLE; + } + else + { + Window->Style |= WS_VISIBLE; + } + } + else + { + if (Window->Style & WS_CHILD && + !(Window->ExStyle & WS_EX_MDICHILD)) + { + Swp |= SWP_NOACTIVATE | SWP_NOZORDER; + } + if (!(Swp & MINMAX_NOSWP)) + { + WinPosSetWindowPos(Wnd, HWND_TOP, NewPos.left, NewPos.top, + NewPos.right, NewPos.bottom, LOWORD(Swp)); + if (Cmd == SW_HIDE) + { + /* Hide the window. */ + } + } + /* FIXME: Check for window destruction. */ + /* FIXME: Show title for minimized windows. */ + } + + if (Window->Flags & WINDOWOBJECT_NEED_SIZE) + { + WPARAM wParam = SIZE_RESTORED; + + Window->Flags &= ~WINDOWOBJECT_NEED_SIZE; + if (Window->Style & WS_MAXIMIZE) + { + wParam = SIZE_MAXIMIZED; + } + else if (Window->Style & WS_MINIMIZE) + { + wParam = SIZE_MINIMIZED; + } + + NtUserSendMessage(Wnd, WM_SIZE, wParam, + MAKELONG(Window->ClientRect.right - + Window->ClientRect.left, + Window->ClientRect.bottom - + Window->ClientRect.top)); + NtUserSendMessage(Wnd, WM_MOVE, 0, + MAKELONG(Window->ClientRect.left, + Window->ClientRect.top)); + } + ObmDereferenceObject(Window); + return(WasVisible); +}