From 765f09416de3925d9870a8ec2fd03767b3c6c3e7 Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Sun, 28 Oct 2012 10:34:41 +0000 Subject: [PATCH 01/16] - Rewrite NtUserCreateDesktop and move the desktop thread completely in win32k like in windows in order to let desktop objects to be destroyed - Disable deleting the desktop heap until CORE-6729 is fixed - See CORE-6723 for more details svn path=/trunk/; revision=57632 --- reactos/ntoskrnl/ex/win32k.c | 42 ++ reactos/ntoskrnl/ps/win32.c | 4 + reactos/win32ss/gdi/ntgdi/device.c | 8 +- reactos/win32ss/pch.h | 1 + reactos/win32ss/user/ntuser/accelerator.c | 2 +- reactos/win32ss/user/ntuser/callback.c | 27 +- reactos/win32ss/user/ntuser/callproc.c | 1 + reactos/win32ss/user/ntuser/class.c | 21 +- reactos/win32ss/user/ntuser/class.h | 2 +- reactos/win32ss/user/ntuser/clipboard.c | 5 +- reactos/win32ss/user/ntuser/csr.c | 70 --- reactos/win32ss/user/ntuser/cursoricon.c | 2 +- reactos/win32ss/user/ntuser/desktop.c | 402 +++++++++++------- reactos/win32ss/user/ntuser/desktop.h | 9 + reactos/win32ss/user/ntuser/event.c | 2 +- reactos/win32ss/user/ntuser/hook.c | 2 +- reactos/win32ss/user/ntuser/input.c | 1 + reactos/win32ss/user/ntuser/kbdlayout.c | 4 +- reactos/win32ss/user/ntuser/main.c | 13 +- reactos/win32ss/user/ntuser/menu.c | 8 +- reactos/win32ss/user/ntuser/message.c | 23 + reactos/win32ss/user/ntuser/monitor.c | 2 +- reactos/win32ss/user/ntuser/msgqueue.c | 2 +- reactos/win32ss/user/ntuser/msgqueue.h | 9 + reactos/win32ss/user/ntuser/object.c | 10 +- reactos/win32ss/user/ntuser/object.h | 2 +- reactos/win32ss/user/ntuser/simplecall.c | 3 +- reactos/win32ss/user/ntuser/timer.c | 2 +- reactos/win32ss/user/ntuser/window.c | 39 +- reactos/win32ss/user/ntuser/window.h | 8 +- reactos/win32ss/user/ntuser/winsta.c | 10 +- .../win32ss/user/user32/windows/cursoricon.c | 10 +- reactos/win32ss/user/win32csr/desktopbg.c | 320 +------------- reactos/win32ss/user/win32csr/dllmain.c | 18 +- 34 files changed, 481 insertions(+), 603 deletions(-) diff --git a/reactos/ntoskrnl/ex/win32k.c b/reactos/ntoskrnl/ex/win32k.c index c710db56081..7abfd29fc6e 100644 --- a/reactos/ntoskrnl/ex/win32k.c +++ b/reactos/ntoskrnl/ex/win32k.c @@ -40,6 +40,8 @@ PKWIN32_DELETEMETHOD_CALLOUT ExpWindowStationObjectDelete = NULL; PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpWindowStationObjectOkToClose = NULL; PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpDesktopObjectOkToClose = NULL; PKWIN32_DELETEMETHOD_CALLOUT ExpDesktopObjectDelete = NULL; +PKWIN32_OPENMETHOD_CALLOUT ExpDesktopObjectOpen = NULL; +PKWIN32_CLOSEMETHOD_CALLOUT ExpDesktopObjectClose = NULL; /* FUNCTIONS ****************************************************************/ @@ -133,6 +135,44 @@ ExpDesktopDelete(PVOID DeletedObject) ExpDesktopObjectDelete(&Parameters); } +NTSTATUS +NTAPI +ExpDesktopOpen(IN OB_OPEN_REASON Reason, + IN PEPROCESS Process OPTIONAL, + IN PVOID ObjectBody, + IN ACCESS_MASK GrantedAccess, + IN ULONG HandleCount) +{ + WIN32_OPENMETHOD_PARAMETERS Parameters; + + Parameters.OpenReason = Reason; + Parameters.Process = Process; + Parameters.Object = ObjectBody; + Parameters.GrantedAccess = GrantedAccess; + Parameters.HandleCount = HandleCount; + + return ExpDesktopObjectOpen(&Parameters); +} + +VOID +NTAPI +ExpDesktopClose(IN PEPROCESS Process OPTIONAL, + IN PVOID Object, + IN ACCESS_MASK GrantedAccess, + IN ULONG ProcessHandleCount, + IN ULONG SystemHandleCount) +{ + WIN32_CLOSEMETHOD_PARAMETERS Parameters; + + Parameters.Process = Process; + Parameters.Object = Object; + Parameters.AccessMask = GrantedAccess; + Parameters.ProcessHandleCount = ProcessHandleCount; + Parameters.SystemHandleCount = SystemHandleCount; + + ExpDesktopObjectClose(&Parameters); +} + BOOLEAN INIT_FUNCTION NTAPI @@ -169,6 +209,8 @@ ExpWin32kInit(VOID) ObjectTypeInitializer.DeleteProcedure = ExpDesktopDelete; ObjectTypeInitializer.ParseProcedure = NULL; ObjectTypeInitializer.OkayToCloseProcedure = ExpDesktopOkToClose; + ObjectTypeInitializer.OpenProcedure = ExpDesktopOpen; + ObjectTypeInitializer.CloseProcedure = ExpDesktopClose; ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, diff --git a/reactos/ntoskrnl/ps/win32.c b/reactos/ntoskrnl/ps/win32.c index 19dd4e9c43d..04c857fbfb0 100644 --- a/reactos/ntoskrnl/ps/win32.c +++ b/reactos/ntoskrnl/ps/win32.c @@ -23,6 +23,8 @@ extern PKWIN32_DELETEMETHOD_CALLOUT ExpWindowStationObjectDelete; extern PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpWindowStationObjectOkToClose; extern PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpDesktopObjectOkToClose; extern PKWIN32_DELETEMETHOD_CALLOUT ExpDesktopObjectDelete; +extern PKWIN32_OPENMETHOD_CALLOUT ExpDesktopObjectOpen; +extern PKWIN32_CLOSEMETHOD_CALLOUT ExpDesktopObjectClose; extern PKWIN32_POWEREVENT_CALLOUT PopEventCallout; /* PRIVATE FUNCTIONS *********************************************************/ @@ -121,6 +123,8 @@ PsEstablishWin32Callouts(IN PWIN32_CALLOUTS_FPNS CalloutData) ExpWindowStationObjectOkToClose = CalloutData->WindowStationOkToCloseProcedure; ExpDesktopObjectOkToClose = CalloutData->DesktopOkToCloseProcedure; ExpDesktopObjectDelete = CalloutData->DesktopDeleteProcedure; + ExpDesktopObjectOpen = CalloutData->DesktopOpenProcedure; + ExpDesktopObjectClose = CalloutData->DesktopCloseProcedure; PopEventCallout = CalloutData->PowerEventCallout; KeGdiFlushUserBatch = CalloutData->BatchFlushRoutine; } diff --git a/reactos/win32ss/gdi/ntgdi/device.c b/reactos/win32ss/gdi/ntgdi/device.c index 94ac8ede26b..a54acdeda34 100644 --- a/reactos/win32ss/gdi/ntgdi/device.c +++ b/reactos/win32ss/gdi/ntgdi/device.c @@ -32,16 +32,16 @@ IntCreatePrimarySurface(VOID) SURFOBJ *pso; PDESKTOP rpDesk; + /* Create surface */ + pso = &PDEVOBJ_pSurface(gppdevPrimary)->SurfObj; + SurfSize = pso->sizlBitmap; + /* Attach monitor */ UserAttachMonitor((HDEV)gppdevPrimary); DPRINT("IntCreatePrimarySurface, gppdevPrimary=%p, gppdevPrimary->pSurface = %p\n", gppdevPrimary, gppdevPrimary->pSurface); - /* Create surface */ - pso = &PDEVOBJ_pSurface(gppdevPrimary)->SurfObj; - SurfSize = pso->sizlBitmap; - /* Put the pointer in the center of the screen */ gpsi->ptCursor.x = pso->sizlBitmap.cx / 2; gpsi->ptCursor.y = pso->sizlBitmap.cy / 2; diff --git a/reactos/win32ss/pch.h b/reactos/win32ss/pch.h index 921f4588644..af27b477f76 100644 --- a/reactos/win32ss/pch.h +++ b/reactos/win32ss/pch.h @@ -36,6 +36,7 @@ /* Win32 headers */ /* FIXME: Defines in winbase.h that we need... */ typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; +#define MAKEINTATOM(i) (LPWSTR)((ULONG_PTR)((WORD)(i))) #define WINBASEAPI #define STARTF_USESIZE 2 #define STARTF_USEPOSITION 4 diff --git a/reactos/win32ss/user/ntuser/accelerator.c b/reactos/win32ss/user/ntuser/accelerator.c index c09782390a8..24d1b61400b 100644 --- a/reactos/win32ss/user/ntuser/accelerator.c +++ b/reactos/win32ss/user/ntuser/accelerator.c @@ -257,7 +257,7 @@ NtUserCreateAcceleratorTable( RETURN( (HACCEL) NULL ); } - Accel = UserCreateObject(gHandleTable, NULL, (PHANDLE)&hAccel, otAccel, sizeof(ACCELERATOR_TABLE)); + Accel = UserCreateObject(gHandleTable, NULL, NULL, (PHANDLE)&hAccel, otAccel, sizeof(ACCELERATOR_TABLE)); if (Accel == NULL) { diff --git a/reactos/win32ss/user/ntuser/callback.c b/reactos/win32ss/user/ntuser/callback.c index 4d84db4a410..e1a69488488 100644 --- a/reactos/win32ss/user/ntuser/callback.c +++ b/reactos/win32ss/user/ntuser/callback.c @@ -130,6 +130,9 @@ co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName, BOOL bResult; ULONG_PTR pLibNameBuffer = 0, pInitFuncBuffer = 0; + /* Do not allow the desktop thread to do callback to user mode */ + ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); + TRACE("co_IntClientLoadLibrary: %S, %S, %d, %d\n", pstrLibName->Buffer, pstrLibName->Buffer, Unload, ApiHook); /* Calculate the size of the argument */ @@ -236,6 +239,9 @@ co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback, ULONG ResultLength; NTSTATUS Status; + /* Do not allow the desktop thread to do callback to user mode */ + ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); + Arguments.Callback = CompletionCallback; Arguments.Wnd = hWnd; Arguments.Msg = Msg; @@ -281,6 +287,9 @@ co_IntCallWindowProc(WNDPROC Proc, ULONG ArgumentLength; LRESULT Result; + /* Do not allow the desktop thread to do callback to user mode */ + ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); + if (0 < lParamBufferSize) { ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + lParamBufferSize; @@ -364,6 +373,9 @@ co_IntLoadSysMenuTemplate() PVOID ResultPointer; ULONG ResultLength; + /* Do not allow the desktop thread to do callback to user mode */ + ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); + ResultPointer = NULL; ResultLength = sizeof(LRESULT); @@ -394,6 +406,8 @@ co_IntLoadSysMenuTemplate() return (HMENU)Result; } +extern HCURSOR gDesktopCursor; + BOOL APIENTRY co_IntLoadDefaultCursors(VOID) { @@ -402,8 +416,11 @@ co_IntLoadDefaultCursors(VOID) ULONG ResultLength; BOOL DefaultCursor = TRUE; + /* Do not allow the desktop thread to do callback to user mode */ + ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); + ResultPointer = NULL; - ResultLength = sizeof(LRESULT); + ResultLength = sizeof(HCURSOR); UserLeaveCo(); @@ -415,6 +432,9 @@ co_IntLoadDefaultCursors(VOID) UserEnterCo(); + /* HACK: The desktop class doen't have a proper cursor yet, so set it here */ + gDesktopCursor = *((HCURSOR*)ResultPointer); + if (!NT_SUCCESS(Status)) { return FALSE; @@ -448,6 +468,8 @@ co_IntCallHookProc(INT HookId, UINT lParamSize = 0; ASSERT(Proc); + /* Do not allow the desktop thread to do callback to user mode */ + ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); pti = PsGetCurrentThreadWin32Thread(); if (pti->TIF_flags & TIF_INCLEANUP) @@ -834,6 +856,9 @@ co_IntClientThreadSetup(VOID) ULONG ArgumentLength, ResultLength; PVOID Argument, ResultPointer; + /* Do not allow the desktop thread to do callback to user mode */ + ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); + ArgumentLength = ResultLength = 0; Argument = ResultPointer = NULL; diff --git a/reactos/win32ss/user/ntuser/callproc.c b/reactos/win32ss/user/ntuser/callproc.c index 5284847afaf..3d0f2fc998c 100644 --- a/reactos/win32ss/user/ntuser/callproc.c +++ b/reactos/win32ss/user/ntuser/callproc.c @@ -35,6 +35,7 @@ CreateCallProc(IN PDESKTOP Desktop, NewCallProc = (PCALLPROCDATA)UserCreateObject(gHandleTable, Desktop, + NULL, &Handle, otCallProc, sizeof(CALLPROCDATA)); diff --git a/reactos/win32ss/user/ntuser/class.c b/reactos/win32ss/user/ntuser/class.c index a5b7a14b666..afba9eb9399 100644 --- a/reactos/win32ss/user/ntuser/class.c +++ b/reactos/win32ss/user/ntuser/class.c @@ -641,9 +641,17 @@ IntReferenceClass(IN OUT PCLS BaseClass, PCLS Class; ASSERT(BaseClass->pclsBase == BaseClass); - Class = IntGetClassForDesktop(BaseClass, - ClassLink, - Desktop); + if (Desktop != NULL) + { + Class = IntGetClassForDesktop(BaseClass, + ClassLink, + Desktop); + } + else + { + Class = BaseClass; + } + if (Class != NULL) { Class->cWndReferenceCount++; @@ -1286,13 +1294,16 @@ FoundClass: } PCLS -IntGetAndReferenceClass(PUNICODE_STRING ClassName, HINSTANCE hInstance) +IntGetAndReferenceClass(PUNICODE_STRING ClassName, HINSTANCE hInstance, BOOL bDesktopThread) { PCLS *ClassLink, Class = NULL; RTL_ATOM ClassAtom; PTHREADINFO pti; - pti = PsGetCurrentThreadWin32Thread(); + if (bDesktopThread) + pti = gptiDesktopThread; + else + pti = PsGetCurrentThreadWin32Thread(); if ( !(pti->ppi->W32PF_flags & W32PF_CLASSESREGISTERED )) { diff --git a/reactos/win32ss/user/ntuser/class.h b/reactos/win32ss/user/ntuser/class.h index d6603b64418..f2d79781902 100644 --- a/reactos/win32ss/user/ntuser/class.h +++ b/reactos/win32ss/user/ntuser/class.h @@ -39,7 +39,7 @@ IntDereferenceClass(IN OUT PCLS Class, IN PPROCESSINFO pi); PCLS -IntGetAndReferenceClass(PUNICODE_STRING ClassName, HINSTANCE hInstance); +IntGetAndReferenceClass(PUNICODE_STRING ClassName, HINSTANCE hInstance, BOOL bDesktopThread); BOOL FASTCALL UserRegisterSystemClasses(VOID); diff --git a/reactos/win32ss/user/ntuser/clipboard.c b/reactos/win32ss/user/ntuser/clipboard.c index cfe6fd8626a..e238e54a6be 100644 --- a/reactos/win32ss/user/ntuser/clipboard.c +++ b/reactos/win32ss/user/ntuser/clipboard.c @@ -181,6 +181,7 @@ IntSynthesizeDib( /* Create the clipboard data */ pClipboardData = (PCLIPBOARDDATA)UserCreateObject(gHandleTable, + NULL, NULL, &hMem, otClipBoardData, @@ -293,7 +294,7 @@ IntAddSynthesizedFormats(PWINSTATION_OBJECT pWinStaObj) PCLIPBOARDDATA pMemObj; HANDLE hMem; - pMemObj = (PCLIPBOARDDATA)UserCreateObject(gHandleTable, NULL, &hMem, otClipBoardData, + pMemObj = (PCLIPBOARDDATA)UserCreateObject(gHandleTable, NULL, NULL, &hMem, otClipBoardData, sizeof(CLIPBOARDDATA) + sizeof(LCID)); if (pMemObj) { @@ -1080,7 +1081,7 @@ NtUserConvertMemHandle( UserEnterExclusive(); /* Create Clipboard data object */ - pMemObj = UserCreateObject(gHandleTable, NULL, &hMem, otClipBoardData, sizeof(CLIPBOARDDATA) + cbData); + pMemObj = UserCreateObject(gHandleTable, NULL, NULL, &hMem, otClipBoardData, sizeof(CLIPBOARDDATA) + cbData); if (!pMemObj) goto cleanup; diff --git a/reactos/win32ss/user/ntuser/csr.c b/reactos/win32ss/user/ntuser/csr.c index af757006a69..2b622e846a5 100644 --- a/reactos/win32ss/user/ntuser/csr.c +++ b/reactos/win32ss/user/ntuser/csr.c @@ -88,74 +88,4 @@ co_CsrNotify(PCSR_API_MESSAGE Request) return Status; } - -NTSTATUS -APIENTRY -CsrInsertObject(HANDLE ObjectHandle, - ACCESS_MASK DesiredAccess, - PHANDLE Handle) -{ - NTSTATUS Status; - HANDLE CsrProcessHandle; - OBJECT_ATTRIBUTES ObjectAttributes; - CLIENT_ID Cid; - - /* Put CSR'S CID */ - Cid.UniqueProcess = CsrProcess->UniqueProcessId; - Cid.UniqueThread = 0; - - /* Empty Attributes */ - InitializeObjectAttributes(&ObjectAttributes, - NULL, - 0, - NULL, - NULL); - - /* Get a Handle to Csrss */ - Status = ZwOpenProcess(&CsrProcessHandle, - PROCESS_DUP_HANDLE, - &ObjectAttributes, - &Cid); - - if ((NT_SUCCESS(Status))) - { - /* Duplicate the Handle */ - Status = ZwDuplicateObject(NtCurrentProcess(), - ObjectHandle, - CsrProcessHandle, - Handle, - DesiredAccess, - OBJ_INHERIT, - 0); - - /* Close our handle to CSRSS */ - ZwClose(CsrProcessHandle); - } - - return Status; -} - -NTSTATUS FASTCALL -CsrCloseHandle(HANDLE Handle) -{ - NTSTATUS Status; - PEPROCESS OldProcess; - - /* Switch to the process in which the handle is valid */ - OldProcess = PsGetCurrentProcess(); - if (CsrProcess != OldProcess) - { - KeAttachProcess(&CsrProcess->Pcb); - } - - Status = ZwClose(Handle); - - if (CsrProcess != OldProcess) - { - KeDetachProcess(); - } - - return Status; -} - /* EOF */ diff --git a/reactos/win32ss/user/ntuser/cursoricon.c b/reactos/win32ss/user/ntuser/cursoricon.c index 4be2e643144..593e6ae7874 100644 --- a/reactos/win32ss/user/ntuser/cursoricon.c +++ b/reactos/win32ss/user/ntuser/cursoricon.c @@ -209,7 +209,7 @@ IntCreateCurIconHandle() PCURICON_OBJECT CurIcon; HANDLE hCurIcon; - CurIcon = UserCreateObject(gHandleTable, NULL, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT)); + CurIcon = UserCreateObject(gHandleTable, NULL, NULL, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT)); if (!CurIcon) { diff --git a/reactos/win32ss/user/ntuser/desktop.c b/reactos/win32ss/user/ntuser/desktop.c index fdad25e3c51..da909322245 100644 --- a/reactos/win32ss/user/ntuser/desktop.c +++ b/reactos/win32ss/user/ntuser/desktop.c @@ -11,11 +11,17 @@ #include DBG_DEFAULT_CHANNEL(UserDesktop); -static -VOID -IntFreeDesktopHeap( - IN OUT PDESKTOP Desktop -); +static NTSTATUS +UserInitializeDesktop(PDESKTOP pdesk, PUNICODE_STRING DesktopName, PWINSTATION_OBJECT pwinsta); + +static NTSTATUS +IntMapDesktopView(IN PDESKTOP pdesk); + +static NTSTATUS +IntUnmapDesktopView(IN PDESKTOP pdesk); + +static VOID +IntFreeDesktopHeap(IN PDESKTOP pdesk); /* GLOBALS *******************************************************************/ @@ -23,6 +29,8 @@ IntFreeDesktopHeap( PDESKTOP InputDesktop = NULL; HDESK InputDesktopHandle = NULL; HDC ScreenDeviceContext = NULL; +PTHREADINFO gptiDesktopThread; +HCURSOR gDesktopCursor = NULL; /* OBJECT CALLBACKS **********************************************************/ @@ -112,17 +120,16 @@ IntDesktopObjectParse(IN PVOID ParseObject, sizeof(DESKTOP), 0, 0, - (PVOID)&Desktop); + (PVOID*)&Desktop); if (!NT_SUCCESS(Status)) return Status; - /* Initialize shell hook window list and set the parent */ - RtlZeroMemory(Desktop, sizeof(DESKTOP)); - InitializeListHead(&Desktop->ShellHookWindows); - Desktop->rpwinstaParent = (PWINSTATION_OBJECT)ParseObject; - - /* Put the desktop on the window station's list of associated desktops */ - InsertTailList(&Desktop->rpwinstaParent->DesktopListHead, - &Desktop->ListEntry); + /* Initialize the desktop */ + Status = UserInitializeDesktop(Desktop, RemainingName, WinStaObject); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Desktop); + return Status; + } /* Set the desktop object and return success */ *Object = Desktop; @@ -133,22 +140,29 @@ IntDesktopObjectParse(IN PVOID ParseObject, VOID APIENTRY IntDesktopObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters) { - PDESKTOP Desktop = (PDESKTOP)Parameters->Object; + PDESKTOP pdesk = (PDESKTOP)Parameters->Object; - TRACE("Deleting desktop object 0x%p\n", Desktop); + TRACE("Deleting desktop object 0x%p\n", pdesk); + + ASSERT(pdesk->pDeskInfo->spwnd->spwndChild == NULL); + + if (pdesk->pDeskInfo->spwnd) + co_UserDestroyWindow(pdesk->pDeskInfo->spwnd); + + if (pdesk->spwndMessage) + co_UserDestroyWindow(pdesk->spwndMessage); /* Remove the desktop from the window station's list of associcated desktops */ - RemoveEntryList(&Desktop->ListEntry); + RemoveEntryList(&pdesk->ListEntry); - IntFreeDesktopHeap(Desktop); + /* Free the heap */ + IntFreeDesktopHeap(pdesk); } NTSTATUS NTAPI IntDesktopOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters) { - PTHREADINFO pti; - - pti = PsGetCurrentThreadWin32Thread(); + PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); if( pti == NULL) { @@ -166,6 +180,29 @@ IntDesktopOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters) return STATUS_SUCCESS; } +NTSTATUS NTAPI IntDesktopObjectOpen(PWIN32_OPENMETHOD_PARAMETERS Parameters) +{ + PPROCESSINFO ppi = PsGetProcessWin32Process(Parameters->Process); + if (ppi == NULL) + return STATUS_SUCCESS; + + return IntMapDesktopView((PDESKTOP)Parameters->Object); +} + +NTSTATUS NTAPI IntDesktopObjectClose(PWIN32_CLOSEMETHOD_PARAMETERS Parameters) +{ + PPROCESSINFO ppi = PsGetProcessWin32Process(Parameters->Process); + if (ppi == NULL) + { + /* This happens when the process leaks desktop handles. + * At this point the PPROCESSINFO is already destroyed */ + return STATUS_SUCCESS; + } + + return IntUnmapDesktopView((PDESKTOP)Parameters->Object); +} + + /* PRIVATE FUNCTIONS **********************************************************/ INIT_FUNCTION @@ -596,8 +633,66 @@ DesktopWindowProc(PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lRe case WM_SYSCOLORCHANGE: co_UserRedrawWindow(Wnd, NULL, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN); return TRUE; + case WM_SETCURSOR: + { + PCURICON_OBJECT pcurOld, pcurNew; + pcurNew = UserGetCurIconObject(gDesktopCursor); + if (!pcurNew) + { + return TRUE; + } + pcurOld = UserSetCursor(pcurNew, FALSE); + if (pcurOld) + { + UserDereferenceObject(pcurOld); + } + } } - return FALSE; // Not processed so go with callback. + return TRUE; /* We are done. Do not do any callbacks to user mode */ +} + +BOOL FASTCALL +UserMessageWindowProc(PWND pwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lResult) +{ + *lResult = 0; + + switch(Msg) + { + case WM_NCCREATE: + pwnd->fnid |= FNID_MESSAGEWND; + *lResult = (LRESULT)TRUE; + break; + case WM_DESTROY: + pwnd->fnid |= FNID_DESTROY; + break; + } + + return TRUE; /* We are done. Do not do any callbacks to user mode */ +} + +VOID NTAPI DesktopThreadMain() +{ + BOOL Ret; + MSG Msg; + + gptiDesktopThread = PsGetCurrentThreadWin32Thread(); + + UserEnterExclusive(); + + /* Register system classes. This thread does not belong to any desktop so the + classes will be allocated from the shared heap */ + UserRegisterSystemClasses(); + + while(TRUE) + { + Ret = co_IntGetPeekMessage(&Msg, 0, 0, 0, PM_REMOVE, TRUE); + if (Ret) + { + IntDispatchMessage(&Msg); + } + } + + UserLeave(); } HDC FASTCALL @@ -813,6 +908,8 @@ BOOL IntDeRegisterShellHookWindow(HWND hWnd) static VOID IntFreeDesktopHeap(IN OUT PDESKTOP Desktop) { + /* FIXME: Disable until unmapping works in mm */ +#if 0 if (Desktop->pheapDesktop != NULL) { MmUnmapViewInSessionSpace(Desktop->pheapDesktop); @@ -824,6 +921,7 @@ IntFreeDesktopHeap(IN OUT PDESKTOP Desktop) ObDereferenceObject(Desktop->hsectionDesktop); Desktop->hsectionDesktop = NULL; } +#endif } BOOL FASTCALL @@ -1030,6 +1128,61 @@ IntPaintDesktop(HDC hDC) return TRUE; } +static NTSTATUS +UserInitializeDesktop(PDESKTOP pdesk, PUNICODE_STRING DesktopName, PWINSTATION_OBJECT pwinsta) +{ + PVOID DesktopHeapSystemBase = NULL; + ULONG_PTR HeapSize = 400 * 1024; + SIZE_T DesktopInfoSize; + ULONG i; + + TRACE("UserInitializeDesktop desktop 0x%p with name %wZ\n", pdesk, DesktopName); + + RtlZeroMemory(pdesk, sizeof(DESKTOP)); + + /* Link the desktop with the parent window station */ + pdesk->rpwinstaParent = pwinsta; + InsertTailList(&pwinsta->DesktopListHead, &pdesk->ListEntry); + + /* Create the desktop heap */ + pdesk->hsectionDesktop = NULL; + pdesk->pheapDesktop = UserCreateHeap(&pdesk->hsectionDesktop, + &DesktopHeapSystemBase, + HeapSize); + if (pdesk->pheapDesktop == NULL) + { + ERR("Failed to create desktop heap!\n"); + return STATUS_NO_MEMORY; + } + + /* Create DESKTOPINFO */ + DesktopInfoSize = sizeof(DESKTOPINFO) + DesktopName->Length + sizeof(WCHAR); + pdesk->pDeskInfo = RtlAllocateHeap(pdesk->pheapDesktop, + HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, + DesktopInfoSize); + if (pdesk->pDeskInfo == NULL) + { + ERR("Failed to create the DESKTOP structure!\n"); + return STATUS_NO_MEMORY; + } + + /* Initialize the DESKTOPINFO */ + pdesk->pDeskInfo->pvDesktopBase = DesktopHeapSystemBase; + pdesk->pDeskInfo->pvDesktopLimit = (PVOID)((ULONG_PTR)DesktopHeapSystemBase + HeapSize); + RtlCopyMemory(pdesk->pDeskInfo->szDesktopName, + DesktopName->Buffer, + DesktopName->Length + sizeof(WCHAR)); + for (i = 0; i < NB_HOOKS; i++) + { + InitializeListHead(&pdesk->pDeskInfo->aphkStart[i]); + } + + InitializeListHead(&pdesk->ShellHookWindows); + InitializeListHead(&pdesk->PtiList); + + return STATUS_SUCCESS; +} + /* SYSCALLS *******************************************************************/ /* @@ -1073,43 +1226,35 @@ NtUserCreateDesktop( DWORD dwFlags, ACCESS_MASK dwDesiredAccess) { - PDESKTOP DesktopObject; - UNICODE_STRING DesktopName; + PDESKTOP pdesk = NULL; NTSTATUS Status = STATUS_SUCCESS; - HDESK Desktop; - CSR_API_MESSAGE Request; - PVOID DesktopHeapSystemBase = NULL; - SIZE_T DesktopInfoSize; + HDESK hdesk; BOOLEAN Context; - ULONG_PTR HeapSize = 400 * 1024; /* FIXME: Windows uses 200KB by default */ UNICODE_STRING ClassName; LARGE_STRING WindowName; BOOL NoHooks = FALSE; PWND pWnd = NULL; CREATESTRUCTW Cs; - INT i; PTHREADINFO ptiCurrent; + PCLS pcls; + DECLARE_RETURN(HDESK); TRACE("Enter NtUserCreateDesktop\n"); UserEnterExclusive(); ptiCurrent = PsGetCurrentThreadWin32Thread(); - if (ptiCurrent) - { + ASSERT(ptiCurrent); + ASSERT(gptiDesktopThread); + /* Turn off hooks when calling any CreateWindowEx from inside win32k. */ - NoHooks = (ptiCurrent->TIF_flags & TIF_DISABLEHOOKS); - ptiCurrent->TIF_flags |= TIF_DISABLEHOOKS; - ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; - } - /*else - {ERR("NtUserCreateDesktop: No ptiCurrent\n");}*/ - DesktopName.Buffer = NULL; + NoHooks = (ptiCurrent->TIF_flags & TIF_DISABLEHOOKS); + ptiCurrent->TIF_flags |= TIF_DISABLEHOOKS; + ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; /* * Try to open already existing desktop */ - Status = ObOpenObjectByName( ObjectAttributes, ExDesktopObjectType, @@ -1117,142 +1262,99 @@ NtUserCreateDesktop( NULL, dwDesiredAccess, (PVOID)&Context, - (HANDLE*)&Desktop); - if (!NT_SUCCESS(Status)) RETURN(NULL); + (HANDLE*)&hdesk); + if (!NT_SUCCESS(Status)) + { + ERR("ObOpenObjectByName failed to open/create desktop\n"); + SetLastNtError(Status); + RETURN(NULL); + } /* In case the object was not created (eg if it existed), return now */ if (Context == FALSE) { TRACE("NtUserCreateDesktop opened desktop %wZ\n", ObjectAttributes->ObjectName); - RETURN( Desktop); - } - - /* Capture desktop name */ - _SEH2_TRY - { - ProbeForRead( ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), 1); - - Status = IntSafeCopyUnicodeStringTerminateNULL(&DesktopName, ObjectAttributes->ObjectName); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Status = _SEH2_GetExceptionCode(); - } - _SEH2_END - - if (! NT_SUCCESS(Status)) - { - ERR("Failed reading Object Attributes from user space.\n"); - SetLastNtError(Status); - RETURN( NULL); + RETURN( hdesk); } /* Reference the desktop */ - Status = ObReferenceObjectByHandle(Desktop, + Status = ObReferenceObjectByHandle(hdesk, 0, ExDesktopObjectType, KernelMode, - (PVOID)&DesktopObject, + (PVOID*)&pdesk, NULL); if (!NT_SUCCESS(Status)) { ERR("Failed to reference desktop object\n"); + SetLastNtError(Status); RETURN(NULL); } - TRACE("NtUserCreateDesktop created desktop 0x%p with name %wZ\n", DesktopObject, &DesktopName); + if (!ptiCurrent->rpdesk) IntSetThreadDesktop(hdesk,FALSE); - DesktopObject->hsectionDesktop = NULL; - DesktopObject->pheapDesktop = UserCreateHeap(&DesktopObject->hsectionDesktop, - &DesktopHeapSystemBase, - HeapSize); - if (DesktopObject->pheapDesktop == NULL) - { - ObDereferenceObject(DesktopObject); - ERR("Failed to create desktop heap!\n"); - RETURN(NULL); - } - - DesktopInfoSize = sizeof(DESKTOPINFO) + DesktopName.Length + sizeof(WCHAR); - - DesktopObject->pDeskInfo = RtlAllocateHeap(DesktopObject->pheapDesktop, - HEAP_NO_SERIALIZE, - DesktopInfoSize); - - if (DesktopObject->pDeskInfo == NULL) - { - ObDereferenceObject(DesktopObject); - ERR("Failed to create the DESKTOP structure!\n"); - RETURN(NULL); - } - - RtlZeroMemory(DesktopObject->pDeskInfo, - DesktopInfoSize); - - DesktopObject->pDeskInfo->pvDesktopBase = DesktopHeapSystemBase; - DesktopObject->pDeskInfo->pvDesktopLimit = (PVOID)((ULONG_PTR)DesktopHeapSystemBase + HeapSize); - RtlCopyMemory(DesktopObject->pDeskInfo->szDesktopName, - DesktopName.Buffer, - DesktopName.Length + sizeof(WCHAR)); - - /* Initialize some local (to win32k) desktop state. */ - InitializeListHead(&DesktopObject->PtiList); - DesktopObject->ActiveMessageQueue = NULL; - - /* Setup Global Hooks. */ - for (i = 0; i < NB_HOOKS; i++) - { - InitializeListHead(&DesktopObject->pDeskInfo->aphkStart[i]); - } - - /* - * Create a handle for CSRSS and notify CSRSS for Creating Desktop Background Windows and Threads. + /* Get the desktop window class. The thread desktop does not belong to any desktop + * so the classes created there (including the desktop class) are allocated in the shared heap + * It would cause problems if we used a class that belongs to the caller */ - Request.Type = MAKE_CSR_API(CREATE_DESKTOP, CSR_GUI); - Status = CsrInsertObject(Desktop, - GENERIC_ALL, - (HANDLE*)&Request.Data.CreateDesktopRequest.DesktopHandle); - if (! NT_SUCCESS(Status)) - { - ERR("Failed to create desktop handle for CSRSS\n"); - ZwClose(Desktop); - SetLastNtError(Status); - RETURN( NULL); - } - - Status = co_CsrNotify(&Request); - if (! NT_SUCCESS(Status)) - { - CsrCloseHandle(Request.Data.CreateDesktopRequest.DesktopHandle); - ERR("Failed to notify CSRSS about new desktop\n"); - ZwClose(Desktop); - SetLastNtError(Status); - RETURN( NULL); - } - - if (ptiCurrent && !ptiCurrent->rpdesk) IntSetThreadDesktop(Desktop,FALSE); - - ClassName.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(gpsi->atomSysClass[ICLS_HWNDMESSAGE]))); + ClassName.Buffer = WC_DESKTOP; ClassName.Length = 0; - RtlZeroMemory(&WindowName, sizeof(WindowName)); + pcls = IntGetAndReferenceClass(&ClassName, 0, TRUE); + if (pcls == NULL) + { + ASSERT(FALSE); + RETURN(NULL); + } + RtlZeroMemory(&WindowName, sizeof(WindowName)); RtlZeroMemory(&Cs, sizeof(Cs)); - Cs.cx = Cs.cy = 100; + Cs.x = UserGetSystemMetrics(SM_XVIRTUALSCREEN), + Cs.y = UserGetSystemMetrics(SM_YVIRTUALSCREEN), + Cs.cx = UserGetSystemMetrics(SM_CXVIRTUALSCREEN), + Cs.cy = UserGetSystemMetrics(SM_CYVIRTUALSCREEN), Cs.style = WS_POPUP|WS_CLIPCHILDREN; - Cs.hInstance = hModClient; // hModuleWin; // Server side winproc! Leave it to Timo to not pass on notes! + Cs.hInstance = hModClient; // hModuleWin; // Server side winproc! Cs.lpszName = (LPCWSTR) &WindowName; Cs.lpszClass = (LPCWSTR) &ClassName; - pWnd = co_UserCreateWindowEx(&Cs, &ClassName, &WindowName, NULL); - if (!pWnd) + /* Use IntCreateWindow instead of co_UserCreateWindowEx cause the later expects a thread with a desktop */ + pWnd = IntCreateWindow(&Cs, &WindowName, pcls, NULL, NULL, NULL, pdesk); + if (pWnd == NULL) { - ERR("Failed to create Message window handle\n"); + ERR("Failed to create desktop window for the new desktop\n"); + RETURN(NULL); } - else + + pdesk->DesktopWindow = pWnd->head.h; + pdesk->pDeskInfo->spwnd = pWnd; + pWnd->fnid = FNID_DESKTOP; + + ClassName.Buffer = MAKEINTATOM(gpsi->atomSysClass[ICLS_HWNDMESSAGE]); + ClassName.Length = 0; + pcls = IntGetAndReferenceClass(&ClassName, 0, TRUE); + if (pcls == NULL) { - DesktopObject->spwndMessage = pWnd; + ASSERT(FALSE); + RETURN(NULL); } + RtlZeroMemory(&WindowName, sizeof(WindowName)); + RtlZeroMemory(&Cs, sizeof(Cs)); + Cs.cx = Cs.cy = 100; + Cs.style = WS_POPUP|WS_CLIPCHILDREN; + Cs.hInstance = hModClient; // hModuleWin; // Server side winproc! + Cs.lpszName = (LPCWSTR) &WindowName; + Cs.lpszClass = (LPCWSTR) &ClassName; + pWnd = IntCreateWindow(&Cs, &WindowName, pcls, NULL, NULL, NULL, pdesk); + if (pWnd == NULL) + { + ERR("Failed to create message window for the new desktop\n"); + RETURN(NULL); + } + + pdesk->spwndMessage = pWnd; + pWnd->fnid = FNID_MESSAGEWND; + /* Now,,, if !(WinStaObject->Flags & WSF_NOIO) is (not set) for desktop input output mode (see wiki) Create Tooltip. Saved in DesktopObject->spwndTooltip. @@ -1261,14 +1363,18 @@ NtUserCreateDesktop( The rest is same as message window. http://msdn.microsoft.com/en-us/library/bb760250(VS.85).aspx */ - RETURN( Desktop); + RETURN( hdesk); CLEANUP: - if(DesktopName.Buffer != NULL) + if (pdesk != NULL) { - ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING); + ObDereferenceObject(pdesk); } - if (!NoHooks && ptiCurrent) + if (_ret_ == NULL && hdesk != NULL) + { + ObCloseHandle(hdesk, UserMode); + } + if (!NoHooks) { ptiCurrent->TIF_flags &= ~TIF_DISABLEHOOKS; ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; diff --git a/reactos/win32ss/user/ntuser/desktop.h b/reactos/win32ss/user/ntuser/desktop.h index df87eb3a14d..c05ae1ffc63 100644 --- a/reactos/win32ss/user/ntuser/desktop.h +++ b/reactos/win32ss/user/ntuser/desktop.h @@ -73,6 +73,7 @@ extern PDESKTOP InputDesktop; extern HDESK InputDesktopHandle; extern PCLS DesktopWindowClass; extern HDC ScreenDeviceContext; +extern PTHREADINFO gptiDesktopThread; typedef struct _SHELL_HOOK_WINDOW { @@ -104,6 +105,12 @@ IntDesktopObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters); NTSTATUS NTAPI IntDesktopOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters); +NTSTATUS NTAPI +IntDesktopObjectOpen(PWIN32_OPENMETHOD_PARAMETERS Parameters); + +NTSTATUS NTAPI +IntDesktopObjectClose(PWIN32_CLOSEMETHOD_PARAMETERS Parameters); + HDC FASTCALL IntGetScreenDC(VOID); @@ -283,4 +290,6 @@ PWND FASTCALL IntGetThreadDesktopWindow(PTHREADINFO); PWND FASTCALL co_GetDesktopWindow(PWND); BOOL FASTCALL IntPaintDesktop(HDC); BOOL FASTCALL DesktopWindowProc(PWND, UINT, WPARAM, LPARAM, LRESULT *); +BOOL FASTCALL UserMessageWindowProc(PWND pwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lResult); +VOID NTAPI DesktopThreadMain(); /* EOF */ diff --git a/reactos/win32ss/user/ntuser/event.c b/reactos/win32ss/user/ntuser/event.c index ef10b9bce9c..964119cb53d 100644 --- a/reactos/win32ss/user/ntuser/event.c +++ b/reactos/win32ss/user/ntuser/event.c @@ -378,7 +378,7 @@ NtUserSetWinEventHook( } } // Creator, pti is set here. - pEH = UserCreateObject(gHandleTable, NULL, &Handle, otEvent, sizeof(EVENTHOOK)); + pEH = UserCreateObject(gHandleTable, NULL, NULL, &Handle, otEvent, sizeof(EVENTHOOK)); if (pEH) { InsertTailList(&GlobalEvents->Events, &pEH->Chain); diff --git a/reactos/win32ss/user/ntuser/hook.c b/reactos/win32ss/user/ntuser/hook.c index 09f9a3760fc..31ebcbd486a 100644 --- a/reactos/win32ss/user/ntuser/hook.c +++ b/reactos/win32ss/user/ntuser/hook.c @@ -1569,7 +1569,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, } ObDereferenceObject(WinStaObj); - Hook = UserCreateObject(gHandleTable, NULL, (PHANDLE)&Handle, otHook, sizeof(HOOK)); + Hook = UserCreateObject(gHandleTable, NULL, NULL, (PHANDLE)&Handle, otHook, sizeof(HOOK)); if (!Hook) { diff --git a/reactos/win32ss/user/ntuser/input.c b/reactos/win32ss/user/ntuser/input.c index b34f256646e..a3e48596de3 100644 --- a/reactos/win32ss/user/ntuser/input.c +++ b/reactos/win32ss/user/ntuser/input.c @@ -304,6 +304,7 @@ CreateSystemThreads(UINT Type) switch (Type) { case 0: RawInputThreadMain(); break; + case 1: DesktopThreadMain(); break; default: ERR("Wrong type: %x\n", Type); } diff --git a/reactos/win32ss/user/ntuser/kbdlayout.c b/reactos/win32ss/user/ntuser/kbdlayout.c index 256ddea78e7..0aa11206085 100644 --- a/reactos/win32ss/user/ntuser/kbdlayout.c +++ b/reactos/win32ss/user/ntuser/kbdlayout.c @@ -131,7 +131,7 @@ UserLoadKbdFile(PUNICODE_STRING pwszKLID) L"Control\\Keyboard Layouts\\"; /* Create keyboard layout file object */ - pkf = UserCreateObject(gHandleTable, NULL, NULL, otKBDfile, sizeof(KBDFILE)); + pkf = UserCreateObject(gHandleTable, NULL, NULL, NULL, otKBDfile, sizeof(KBDFILE)); if (!pkf) { ERR("Failed to create object!\n"); @@ -206,7 +206,7 @@ UserLoadKbdLayout(PUNICODE_STRING pwszKLID, HKL hKL) PKL pKl; /* Create keyboard layout object */ - pKl = UserCreateObject(gHandleTable, NULL, NULL, otKBDlayout, sizeof(KL)); + pKl = UserCreateObject(gHandleTable, NULL, NULL, NULL, otKBDlayout, sizeof(KL)); if (!pKl) { ERR("Failed to create object!\n"); diff --git a/reactos/win32ss/user/ntuser/main.c b/reactos/win32ss/user/ntuser/main.c index 92217d6a9e2..27404c4eaa4 100644 --- a/reactos/win32ss/user/ntuser/main.c +++ b/reactos/win32ss/user/ntuser/main.c @@ -304,6 +304,7 @@ UserCreateThreadInfo(struct _ETHREAD *Thread) if (ptiCurrent->KeyboardLayout) UserReferenceObject(ptiCurrent->KeyboardLayout); ptiCurrent->TIF_flags &= ~TIF_INCLEANUP; + ptiCurrent->pcti = &ptiCurrent->cti; /* Initialize the CLIENTINFO */ pci = (PCLIENTINFO)pTeb->Win32ClientInfo; @@ -624,14 +625,16 @@ DriverEntry( DPRINT("Win32k hInstance 0x%p!\n",hModuleWin); /* Register Object Manager Callbacks */ - CalloutData.WindowStationParseProcedure = IntWinStaObjectParse; - CalloutData.WindowStationDeleteProcedure = IntWinStaObjectDelete; - CalloutData.DesktopDeleteProcedure = IntDesktopObjectDelete; CalloutData.ProcessCallout = Win32kProcessCallback; CalloutData.ThreadCallout = Win32kThreadCallback; - CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch; - CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose; + CalloutData.WindowStationParseProcedure = IntWinStaObjectParse; + CalloutData.WindowStationDeleteProcedure = IntWinStaObjectDelete; CalloutData.WindowStationOkToCloseProcedure = IntWinstaOkToClose; + CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose; + CalloutData.DesktopDeleteProcedure = IntDesktopObjectDelete; + CalloutData.DesktopCloseProcedure = IntDesktopObjectClose; + CalloutData.DesktopOpenProcedure = IntDesktopObjectOpen; + CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch; /* Register our per-process and per-thread structures. */ PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData); diff --git a/reactos/win32ss/user/ntuser/menu.c b/reactos/win32ss/user/ntuser/menu.c index aae4f7dd697..fe870b857cb 100644 --- a/reactos/win32ss/user/ntuser/menu.c +++ b/reactos/win32ss/user/ntuser/menu.c @@ -249,7 +249,8 @@ IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar) PPROCESSINFO CurrentWin32Process; Menu = (PMENU_OBJECT)UserCreateObject( gHandleTable, - NULL, + NULL, + NULL, Handle, otMenu, sizeof(MENU_OBJECT)); @@ -360,8 +361,9 @@ IntCloneMenu(PMENU_OBJECT Source) return NULL; Menu = (PMENU_OBJECT)UserCreateObject( gHandleTable, - NULL, - &hMenu, + NULL, + NULL, + &hMenu, otMenu, sizeof(MENU_OBJECT)); if(!Menu) diff --git a/reactos/win32ss/user/ntuser/message.c b/reactos/win32ss/user/ntuser/message.c index 23cb63cad10..e39057fe177 100644 --- a/reactos/win32ss/user/ntuser/message.c +++ b/reactos/win32ss/user/ntuser/message.c @@ -714,6 +714,13 @@ IntDispatchMessage(PMSG pMsg) pMsg->lParam, &retval); break; + case FNID_MESSAGEWND: + DoCallBack = !UserMessageWindowProc( Window, + pMsg->message, + pMsg->wParam, + pMsg->lParam, + &retval); + break; } } @@ -1307,6 +1314,9 @@ co_IntSendMessageTimeoutSingle( HWND hWnd, case FNID_DESKTOP: DoCallBack = !DesktopWindowProc(Window, Msg, wParam, lParam,(LRESULT*)&Result); break; + case FNID_MESSAGEWND: + DoCallBack = !UserMessageWindowProc(Window, Msg, wParam, lParam,(LRESULT*)&Result); + break; } if (!DoCallBack) { @@ -1590,6 +1600,9 @@ co_IntSendMessageWithCallBack( HWND hWnd, case FNID_DESKTOP: DoCallBack = !DesktopWindowProc(Window, Msg, wParam, lParamPacked, (LRESULT*)&Result); break; + case FNID_MESSAGEWND: + DoCallBack = !UserMessageWindowProc(Window, Msg, wParam, lParam,(LRESULT*)&Result); + break; } } @@ -2233,6 +2246,16 @@ NtUserMessageCall( HWND hWnd, } break; } + + case FNID_MESSAGEWND: + { + Window = UserGetWindowObject(hWnd); + if (Window) + { + Ret = !UserMessageWindowProc(Window, Msg, wParam, lParam,&lResult); + } + break; + } case FNID_DEFWINDOWPROC: /* Validate input */ if (hWnd) diff --git a/reactos/win32ss/user/ntuser/monitor.c b/reactos/win32ss/user/ntuser/monitor.c index c6e0d61e2b6..03a4d65d2b8 100644 --- a/reactos/win32ss/user/ntuser/monitor.c +++ b/reactos/win32ss/user/ntuser/monitor.c @@ -32,7 +32,7 @@ static PMONITOR IntCreateMonitorObject() { - return UserCreateObject(gHandleTable, NULL, NULL, otMonitor, sizeof(MONITOR)); + return UserCreateObject(gHandleTable, NULL, NULL, NULL, otMonitor, sizeof(MONITOR)); } /* IntDestroyMonitorObject diff --git a/reactos/win32ss/user/ntuser/msgqueue.c b/reactos/win32ss/user/ntuser/msgqueue.c index 6188a1973b2..084f04ddfe7 100644 --- a/reactos/win32ss/user/ntuser/msgqueue.c +++ b/reactos/win32ss/user/ntuser/msgqueue.c @@ -101,7 +101,7 @@ IntTopLevelWindowFromPoint(INT x, INT y) } /* Window has not been found */ - return NULL; + return pwndDesktop; } PCURICON_OBJECT diff --git a/reactos/win32ss/user/ntuser/msgqueue.h b/reactos/win32ss/user/ntuser/msgqueue.h index 8cac101c69b..e20d1028417 100644 --- a/reactos/win32ss/user/ntuser/msgqueue.h +++ b/reactos/win32ss/user/ntuser/msgqueue.h @@ -298,4 +298,13 @@ UserSetCursor(PCURICON_OBJECT NewCursor, DWORD APIENTRY IntGetQueueStatus(DWORD); UINT lParamMemorySize(UINT Msg, WPARAM wParam, LPARAM lParam); + +BOOL FASTCALL +co_IntGetPeekMessage( PMSG pMsg, + HWND hWnd, + UINT MsgFilterMin, + UINT MsgFilterMax, + UINT RemoveMsg, + BOOL bGMSG ); + /* EOF */ diff --git a/reactos/win32ss/user/ntuser/object.c b/reactos/win32ss/user/ntuser/object.c index 375e3bfbaa2..94242ef83fe 100644 --- a/reactos/win32ss/user/ntuser/object.c +++ b/reactos/win32ss/user/ntuser/object.c @@ -315,20 +315,24 @@ PVOID FASTCALL UserCreateObject( PUSER_HANDLE_TABLE ht, PDESKTOP pDesktop, + PTHREADINFO pti, HANDLE* h, USER_OBJECT_TYPE type, ULONG size) { HANDLE hi; PVOID Object; - PTHREADINFO pti; PPROCESSINFO ppi; BOOL dt; PDESKTOP rpdesk = pDesktop; - pti = GetW32ThreadInfo(); - ppi = pti->ppi; + /* We could get the desktop for the new object from the pti however this is + * not always the case for example when creating a new desktop window for + * the desktop thread*/ + + if (!pti) pti = GetW32ThreadInfo(); if (!pDesktop) rpdesk = pti->rpdesk; + ppi = pti->ppi; switch (type) { diff --git a/reactos/win32ss/user/ntuser/object.h b/reactos/win32ss/user/ntuser/object.h index cad7ce2e0df..976fd463af6 100644 --- a/reactos/win32ss/user/ntuser/object.h +++ b/reactos/win32ss/user/ntuser/object.h @@ -33,7 +33,7 @@ extern PUSER_HANDLE_TABLE gHandleTable; VOID FASTCALL UserReferenceObject(PVOID obj); PVOID FASTCALL UserReferenceObjectByHandle(HANDLE handle, USER_OBJECT_TYPE type); BOOL FASTCALL UserDereferenceObject(PVOID obj); -PVOID FASTCALL UserCreateObject(PUSER_HANDLE_TABLE ht, struct _DESKTOP* pDesktop, HANDLE* h,USER_OBJECT_TYPE type , ULONG size); +PVOID FASTCALL UserCreateObject(PUSER_HANDLE_TABLE ht, struct _DESKTOP* pDesktop, PTHREADINFO pti, HANDLE* h,USER_OBJECT_TYPE type , ULONG size); BOOL FASTCALL UserDeleteObject(HANDLE h, USER_OBJECT_TYPE type ); PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, USER_OBJECT_TYPE type ); PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE, HANDLE, USER_OBJECT_TYPE); diff --git a/reactos/win32ss/user/ntuser/simplecall.c b/reactos/win32ss/user/ntuser/simplecall.c index da3041ad97f..4278ddd2f0a 100644 --- a/reactos/win32ss/user/ntuser/simplecall.c +++ b/reactos/win32ss/user/ntuser/simplecall.c @@ -183,7 +183,8 @@ NtUserCallOneParam( if (count == 0) count = 8; psmwp = (PSMWP) UserCreateObject( gHandleTable, - NULL, + NULL, + NULL, (PHANDLE)&hDwp, otSMWP, sizeof(SMWP)); diff --git a/reactos/win32ss/user/ntuser/timer.c b/reactos/win32ss/user/ntuser/timer.c index 33ac0614b69..8e679d30f4d 100644 --- a/reactos/win32ss/user/ntuser/timer.c +++ b/reactos/win32ss/user/ntuser/timer.c @@ -56,7 +56,7 @@ CreateTimer(VOID) HANDLE Handle; PTIMER Ret = NULL; - Ret = UserCreateObject(gHandleTable, NULL, &Handle, otTimer, sizeof(TIMER)); + Ret = UserCreateObject(gHandleTable, NULL, NULL, &Handle, otTimer, sizeof(TIMER)); if (Ret) { Ret->head.h = Handle; diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index 0aeb7440729..6735dfe7b3d 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -1661,7 +1661,8 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, PCLS Class, PWND ParentWindow, PWND OwnerWindow, - PVOID acbiBuffer) + PVOID acbiBuffer, + PDESKTOP pdeskCreated) { PWND pWnd = NULL; HWND hWnd; @@ -1670,7 +1671,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, BOOL MenuChanged; BOOL bUnicodeWindow; - pti = PsGetCurrentThreadWin32Thread(); + pti = pdeskCreated ? gptiDesktopThread : GetW32ThreadInfo(); if (!(Cs->dwExStyle & WS_EX_LAYOUTRTL)) { @@ -1690,8 +1691,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, */ if ( Class->fnid != FNID_DIALOG ) { - PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); - if (ppi->dwLayout & LAYOUT_RTL) + if (pti->ppi->dwLayout & LAYOUT_RTL) { Cs->dwExStyle |= WS_EX_LAYOUTRTL; } @@ -1713,7 +1713,8 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, /* Allocate the new window */ pWnd = (PWND) UserCreateObject( gHandleTable, - pti->rpdesk, + pdeskCreated ? pdeskCreated : pti->rpdesk, + pti, (PHANDLE)&hWnd, otWindow, sizeof(WND) + Class->cbwndExtra); @@ -1723,14 +1724,14 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, goto AllocError; } - TRACE("Created object with handle %X\n", hWnd); + TRACE("Created window object with handle %X\n", hWnd); - if (NULL == pti->rpdesk->DesktopWindow) + if (pdeskCreated && pdeskCreated->DesktopWindow == NULL ) { /* HACK: Helper for win32csr/desktopbg.c */ /* If there is no desktop window yet, we must be creating it */ TRACE("CreateWindow setting desktop.\n"); - pti->rpdesk->DesktopWindow = hWnd; - pti->rpdesk->pDeskInfo->spwnd = pWnd; + pdeskCreated->DesktopWindow = hWnd; + pdeskCreated->pDeskInfo->spwnd = pWnd; } /* @@ -2010,7 +2011,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, pCbtCreate = NULL; /* Get the class and reference it */ - Class = IntGetAndReferenceClass(ClassName, Cs->hInstance); + Class = IntGetAndReferenceClass(ClassName, Cs->hInstance, FALSE); if(!Class) { ERR("Failed to find class %wZ\n", ClassName); @@ -2059,7 +2060,8 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, Class, ParentWindow, OwnerWindow, - acbiBuffer); + acbiBuffer, + NULL); if(!Window) { ERR("IntCreateWindow failed!\n"); @@ -2502,7 +2504,7 @@ NtUserCreateWindowEx( UserEnterExclusive(); /* Call the internal function */ - pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName, acbiBuffer); + pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName, acbiBuffer, NULL); if(!pwnd) { @@ -2540,12 +2542,15 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) TRACE("co_UserDestroyWindow \n"); - /* Check for owner thread */ - if ( (Window->head.pti->pEThread != PsGetCurrentThread()) || - Window->head.pti != PsGetCurrentThreadWin32Thread() ) + /* Check for owner thread */ + if ( Window->head.pti != PsGetCurrentThreadWin32Thread()) { - EngSetLastError(ERROR_ACCESS_DENIED); - return FALSE; + /* Check if we are destroying the desktop window */ + if (! ((Window->head.rpdesk->dwDTFlags & DF_DESTROYED) && Window == Window->head.rpdesk->pDeskInfo->spwnd)) + { + EngSetLastError(ERROR_ACCESS_DENIED); + return FALSE; + } } /* If window was created successfully and it is hooked */ diff --git a/reactos/win32ss/user/ntuser/window.h b/reactos/win32ss/user/ntuser/window.h index d6931646564..e9c10305342 100644 --- a/reactos/win32ss/user/ntuser/window.h +++ b/reactos/win32ss/user/ntuser/window.h @@ -47,7 +47,13 @@ VOID FASTCALL IntGetWindowBorderMeasures(PWND WindowObject, UINT *cx, UINT *cy); BOOL FASTCALL IntShowOwnedPopups( PWND owner, BOOL fShow ); LRESULT FASTCALL IntDefWindowProc( PWND Window, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Ansi); VOID FASTCALL IntNotifyWinEvent(DWORD, PWND, LONG, LONG, DWORD); -PWND FASTCALL co_UserCreateWindowEx(CREATESTRUCTW*, PUNICODE_STRING, PLARGE_STRING, PVOID); +PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, + PLARGE_STRING WindowName, + PCLS Class, + PWND ParentWindow, + PWND OwnerWindow, + PVOID acbiBuffer, + PDESKTOP pdeskCreated); BOOL FASTCALL IntEnableWindow(HWND,BOOL); BOOL FASTCALL IntIsWindowVisible(PWND); DWORD FASTCALL GetNCHitEx(PWND,POINT); diff --git a/reactos/win32ss/user/ntuser/winsta.c b/reactos/win32ss/user/ntuser/winsta.c index c9a81781520..64039cbfbce 100644 --- a/reactos/win32ss/user/ntuser/winsta.c +++ b/reactos/win32ss/user/ntuser/winsta.c @@ -229,10 +229,7 @@ co_IntInitializeDesktopGraphics(VOID) { TEXTMETRICW tmw; UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"DISPLAY"); - if (! IntCreatePrimarySurface()) - { - return FALSE; - } + ScreenDeviceContext = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE); if (NULL == ScreenDeviceContext) { @@ -241,6 +238,11 @@ co_IntInitializeDesktopGraphics(VOID) } GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_PUBLIC); + if (! IntCreatePrimarySurface()) + { + return FALSE; + } + /* Setup the cursor */ co_IntLoadDefaultCursors(); diff --git a/reactos/win32ss/user/user32/windows/cursoricon.c b/reactos/win32ss/user/user32/windows/cursoricon.c index 45d30f822a9..7270e821e98 100644 --- a/reactos/win32ss/user/user32/windows/cursoricon.c +++ b/reactos/win32ss/user/user32/windows/cursoricon.c @@ -2137,21 +2137,23 @@ User32SetupDefaultCursors(PVOID Arguments, ULONG ArgumentLength) { BOOL *DefaultCursor = (BOOL*)Arguments; - LRESULT Result = TRUE; + HCURSOR hCursor; if(*DefaultCursor) { /* set default cursor */ - SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW)); + hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW); + SetCursor(hCursor); } else { /* FIXME load system cursor scheme */ SetCursor(0); - SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW)); + hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW); + SetCursor(hCursor); } - return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS)); + return(ZwCallbackReturn(&hCursor, sizeof(HCURSOR), STATUS_SUCCESS)); } BOOL get_icon_size(HICON hIcon, SIZE *size) diff --git a/reactos/win32ss/user/win32csr/desktopbg.c b/reactos/win32ss/user/win32csr/desktopbg.c index 4edd7a3fb2c..4fef3937d4e 100644 --- a/reactos/win32ss/user/win32csr/desktopbg.c +++ b/reactos/win32ss/user/win32csr/desktopbg.c @@ -1,341 +1,27 @@ -/* - * win32ss/user/win32csr/desktopbg.c - * - * Desktop background window functions - * - * ReactOS Operating System - * - * Looks as a hax fix to a problem of not having a proper class window proc support - * which ReactOS has now. - * - * Notes on reason why this is here: - * http://www.reactos.org/archives/public/ros-kernel/2003-November/000538.html - * http://www.reactos.org/archives/public/ros-kernel/2003-November/000545.html - * http://www.reactos.org/archives/public/ros-kernel/2003-November/000586.html - * http://www.reactos.org/archives/public/ros-kernel/2003-November/000674.html - * Revision 6908 Move desktop window proc from WIN32K to CSRSS - * Bugs 42, 48 and 57. - * - * http://www.reactos.org/archives/public/ros-kernel/2003-December/001186.html - * - - Now this is used to start Desktops Threads with TEB support. - These first three are Application, Winlogon and ScreenSaver desktops. - - */ - #define NDEBUG #include "w32csr.h" #include -#define DESKTOP_WINDOW_ATOM 32769 - -#define PM_SHOW_DESKTOP 1 -#define PM_HIDE_DESKTOP 2 - -typedef struct tagDTBG_THREAD_DATA -{ - HDESK Desktop; - HANDLE Event; - NTSTATUS Status; -} DTBG_THREAD_DATA, *PDTBG_THREAD_DATA; - -typedef struct tagPRIVATE_NOTIFY_DESKTOP -{ - NMHDR hdr; - struct /* PM_SHOW_DESKTOP */ - { - int Width; - int Height; - } ShowDesktop; -} PRIVATE_NOTIFY_DESKTOP, *PPRIVATE_NOTIFY_DESKTOP; - -static BOOL BgInitialized = FALSE; -static HWND VisibleDesktopWindow = NULL; -#if 0 -static -LRESULT -CALLBACK -DtbgWindowProc(HWND Wnd, - UINT Msg, - WPARAM wParam, - LPARAM lParam) -{ - PAINTSTRUCT PS; - - switch (Msg) - { - case WM_ERASEBKGND: - PaintDesktop((HDC)wParam); - return 1; - - case WM_PAINT: - if (BeginPaint(Wnd, &PS)) - EndPaint(Wnd, &PS); - return 0; - - case WM_SETCURSOR: - return (LRESULT)SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW)); - - case WM_NCCREATE: - return (LRESULT)TRUE; - - case WM_CREATE: - NtUserSetWindowFNID(Wnd, FNID_DESKTOP); // Anti-ReactOS hack! - case WM_CLOSE: - return 0; - - case WM_DISPLAYCHANGE: - MoveWindow(Wnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE); - break; - - case WM_NOTIFY: - { - PPRIVATE_NOTIFY_DESKTOP nmh = (PPRIVATE_NOTIFY_DESKTOP)lParam; - - /* Use WM_NOTIFY for private messages since - * it can't be sent between processes! - */ - switch (nmh->hdr.code) - { - case PM_SHOW_DESKTOP: - { - LRESULT Result; - - Result = !SetWindowPos(Wnd, NULL, 0, 0, - nmh->ShowDesktop.Width, - nmh->ShowDesktop.Height, - SWP_NOACTIVATE | SWP_NOZORDER | - SWP_SHOWWINDOW); - - UpdateWindow(Wnd); - VisibleDesktopWindow = Wnd; - return Result; - } - - case PM_HIDE_DESKTOP: - { - LRESULT Result; - - Result = !SetWindowPos(Wnd, NULL, 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOZORDER | - SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW); - - UpdateWindow(Wnd); - VisibleDesktopWindow = NULL; - return Result; - } - - default: - DPRINT("Unknown notification code 0x%x sent to the desktop window!\n", - nmh->hdr.code); - return 0; - } - } - - default: - return DefWindowProcW(Wnd, Msg, wParam, lParam); - } - - return 0; -} - -static -BOOL -FASTCALL -DtbgInit(VOID) -{ - WNDCLASSEXW Class; - ATOM ClassAtom; - - /* - * Create the desktop window class - */ - Class.cbSize = sizeof(WNDCLASSEXW); - Class.style = 0; // Local Class - Class.lpfnWndProc = DtbgWindowProc; - Class.cbClsExtra = 0; - Class.cbWndExtra = 0; - Class.hInstance = (HINSTANCE)GetModuleHandleW(NULL); - Class.hIcon = NULL; - Class.hCursor = NULL; - Class.hbrBackground = GetSysColorBrush(COLOR_BACKGROUND); - Class.lpszMenuName = NULL; - Class.lpszClassName = (LPCWSTR)DESKTOP_WINDOW_ATOM; - ClassAtom = RegisterClassExW(&Class); - - if (ClassAtom == INVALID_ATOM) - { - DPRINT1("Unable to register desktop background class (error %d)\n", - GetLastError()); - - return FALSE; - } - - VisibleDesktopWindow = NULL; - - return TRUE; -} -#endif -static -DWORD -WINAPI -DtbgDesktopThread(PVOID Data) -{ - HWND BackgroundWnd; - MSG msg; - PDTBG_THREAD_DATA ThreadData = (PDTBG_THREAD_DATA)Data; - - DPRINT("DtbgDesktopThread\n"); - - if (!SetThreadDesktop(ThreadData->Desktop)) - { - DPRINT1("Failed to set thread desktop\n"); - ThreadData->Status = STATUS_UNSUCCESSFUL; - SetEvent(ThreadData->Event); - return 1; - } - - BackgroundWnd = CreateWindowW((LPCWSTR)DESKTOP_WINDOW_ATOM, - L"", - WS_POPUP | WS_CLIPCHILDREN, - GetSystemMetrics(SM_XVIRTUALSCREEN), - GetSystemMetrics(SM_YVIRTUALSCREEN), - GetSystemMetrics(SM_CXVIRTUALSCREEN), - GetSystemMetrics(SM_CYVIRTUALSCREEN), - NULL, NULL, - (HINSTANCE)GetModuleHandleW(L"user32.dll"), // Run in win32k/user32. - NULL); - - if (NULL == BackgroundWnd) - { - DPRINT1("Failed to create desktop background window\n"); - ThreadData->Status = STATUS_UNSUCCESSFUL; - SetEvent(ThreadData->Event); - return 1; - } - - DPRINT("BackgroundWnd 0x%p\n",BackgroundWnd); - - ThreadData->Status = STATUS_SUCCESS; - SetEvent(ThreadData->Event); - - while (GetMessageW(&msg, NULL, 0, 0)) - { - if (msg.message == WM_QUIT) - { - DPRINT1("DtbgDesktopThread WM_QUIT\n"); - } - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - - DPRINT1("DtbgDesktopThread Exit\n"); - return 1; -} - CSR_API(CsrCreateDesktop) { - DTBG_THREAD_DATA ThreadData; - HANDLE ThreadHandle; - - DPRINT("CsrCreateDesktop\n"); - - if (!BgInitialized) - { - BgInitialized = TRUE; - - // if (!DtbgInit()) - // return STATUS_UNSUCCESSFUL; - } - - /* - * The desktop handle we got from win32k is in - * the scope of CSRSS so we can just use it. - */ - ThreadData.Desktop = Request->Data.CreateDesktopRequest.DesktopHandle; - - ThreadData.Event = CreateEventW(NULL, FALSE, FALSE, NULL); - - if (NULL == ThreadData.Event) - { - DPRINT1("Failed to create event (error %d)\n", GetLastError()); - return STATUS_UNSUCCESSFUL; - } - - ThreadHandle = CreateThread(NULL, - 0, - DtbgDesktopThread, - (PVOID)&ThreadData, - 0, - NULL); - - if (NULL == ThreadHandle) - { - CloseHandle(ThreadData.Event); - DPRINT1("Failed to create desktop window thread.\n"); - return STATUS_UNSUCCESSFUL; - } - - CloseHandle(ThreadHandle); - - WaitForSingleObject(ThreadData.Event, INFINITE); - CloseHandle(ThreadData.Event); - - return ThreadData.Status; + return STATUS_SUCCESS; } CSR_API(CsrShowDesktop) { -#if 0 - PRIVATE_NOTIFY_DESKTOP nmh; - DPRINT("CsrShowDesktop\n"); - - nmh.hdr.hwndFrom = Request->Data.ShowDesktopRequest.DesktopWindow; - nmh.hdr.idFrom = 0; - nmh.hdr.code = PM_SHOW_DESKTOP; - - nmh.ShowDesktop.Width = (int)Request->Data.ShowDesktopRequest.Width; - nmh.ShowDesktop.Height = (int)Request->Data.ShowDesktopRequest.Height; - - if (SendMessageW(Request->Data.ShowDesktopRequest.DesktopWindow, - WM_NOTIFY, - (WPARAM)nmh.hdr.hwndFrom, - (LPARAM)&nmh)) - { - return STATUS_UNSUCCESSFUL; - } -#endif return STATUS_SUCCESS; } CSR_API(CsrHideDesktop) { -#if 0 - PRIVATE_NOTIFY_DESKTOP nmh; - DPRINT("CsrHideDesktop\n"); - - nmh.hdr.hwndFrom = Request->Data.ShowDesktopRequest.DesktopWindow; - nmh.hdr.idFrom = 0; - nmh.hdr.code = PM_HIDE_DESKTOP; - - if (SendMessageW(Request->Data.ShowDesktopRequest.DesktopWindow, - WM_NOTIFY, - (WPARAM)nmh.hdr.hwndFrom, - (LPARAM)&nmh)) - { - return STATUS_UNSUCCESSFUL; - } -#endif return STATUS_SUCCESS; } BOOL -FASTCALL -DtbgIsDesktopVisible(VOID) +FASTCALL DtbgIsDesktopVisible(VOID) { - VisibleDesktopWindow = GetDesktopWindow(); // DESKTOPWNDPROC + HWND VisibleDesktopWindow = GetDesktopWindow(); // DESKTOPWNDPROC if (VisibleDesktopWindow != NULL && !IsWindowVisible(VisibleDesktopWindow)) diff --git a/reactos/win32ss/user/win32csr/dllmain.c b/reactos/win32ss/user/win32csr/dllmain.c index ad93d92296e..ade36cb9e7b 100644 --- a/reactos/win32ss/user/win32csr/dllmain.c +++ b/reactos/win32ss/user/win32csr/dllmain.c @@ -331,6 +331,7 @@ Win32CsrInitialization(IN PCSR_SERVER_DLL ServerDll) HANDLE ServerThread; CLIENT_ID ClientId; NTSTATUS Status; + UINT i; Win32CsrApiHeap = RtlGetProcessHeap(); @@ -352,15 +353,18 @@ Win32CsrInitialization(IN PCSR_SERVER_DLL ServerDll) RtlInitializeCriticalSection(&Win32CsrDefineDosDeviceCritSec); InitializeListHead(&DosDeviceHistory); - /* Start Raw Input Threads */ - Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, 0, 0, 0, (PTHREAD_START_ROUTINE)CreateSystemThreads, (PVOID)0, &ServerThread, &ClientId); - if (NT_SUCCESS(Status)) + /* Start the Raw Input Thread and the Desktop Thread */ + for (i = 0; i < 2; ++i) { - NtResumeThread(ServerThread, NULL); - NtClose(ServerThread); + Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, 0, 0, 0, (PTHREAD_START_ROUTINE)CreateSystemThreads, (PVOID)i, &ServerThread, &ClientId); + if (NT_SUCCESS(Status)) + { + NtResumeThread(ServerThread, NULL); + NtClose(ServerThread); + } + else + DPRINT1("Cannot start Raw Input Thread!\n"); } - else - DPRINT1("Cannot start Raw Input Thread!\n"); return STATUS_SUCCESS; } From 5d8559da946dc261904ec2fad8886a94489b90f3 Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Sun, 28 Oct 2012 10:43:48 +0000 Subject: [PATCH 02/16] - Fix build I wonder how ninja managed to compile this locally svn path=/trunk/; revision=57633 --- reactos/win32ss/user/ntuser/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index 6735dfe7b3d..af76bc5a7da 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -2504,7 +2504,7 @@ NtUserCreateWindowEx( UserEnterExclusive(); /* Call the internal function */ - pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName, acbiBuffer, NULL); + pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName, acbiBuffer); if(!pwnd) { From c81f7558533c9f276c9669d8bc4816a6ae5fc2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 28 Oct 2012 12:32:31 +0000 Subject: [PATCH 03/16] [FREELDR] Really use the 'status' variable. svn path=/trunk/; revision=57636 --- reactos/boot/freeldr/freeldr/fs/fat.c | 37 +++++++++++++-------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/reactos/boot/freeldr/freeldr/fs/fat.c b/reactos/boot/freeldr/freeldr/fs/fat.c index e7ecf1ed7fb..79c3dd36380 100644 --- a/reactos/boot/freeldr/freeldr/fs/fat.c +++ b/reactos/boot/freeldr/freeldr/fs/fat.c @@ -906,16 +906,16 @@ BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster, ULONG* ClusterPoi UINT32 ThisFatEntOffset; ULONG SectorCount; PUCHAR ReadBuffer; - BOOLEAN status = TRUE;; + BOOLEAN status = TRUE; //TRACE("FatGetFatEntry() Retrieving FAT entry for cluster %d.\n", Cluster); - // We need a buffer for 2 secors - ReadBuffer = HeapAllocate(FrLdrTempHeap, 2 * Volume->BytesPerSector, 'xTAF'); - if (!ReadBuffer) - { - return FALSE; - } + // We need a buffer for 2 secors + ReadBuffer = HeapAllocate(FrLdrTempHeap, 2 * Volume->BytesPerSector, 'xTAF'); + if (!ReadBuffer) + { + return FALSE; + } switch(Volume->FatType) { @@ -929,7 +929,6 @@ BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster, ULONG* ClusterPoi TRACE("ThisFatSecNum: %d\n", ThisFatSecNum); TRACE("ThisFatEntOffset: %d\n", ThisFatEntOffset); - if (ThisFatEntOffset == (Volume->BytesPerSector - 1)) { SectorCount = 2; @@ -939,11 +938,11 @@ BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster, ULONG* ClusterPoi SectorCount = 1; } - if (!FatReadVolumeSectors(Volume, ThisFatSecNum, SectorCount, ReadBuffer)) - { - status = FALSE; - break; - } + if (!FatReadVolumeSectors(Volume, ThisFatSecNum, SectorCount, ReadBuffer)) + { + status = FALSE; + break; + } fat = *((USHORT *) (ReadBuffer + ThisFatEntOffset)); fat = SWAPW(fat); @@ -963,8 +962,8 @@ BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster, ULONG* ClusterPoi if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 1, ReadBuffer)) { - status = FALSE; - break; + status = FALSE; + break; } fat = *((USHORT *) (ReadBuffer + ThisFatEntOffset)); @@ -992,17 +991,17 @@ BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster, ULONG* ClusterPoi default: ERR("Unknown FAT type %d\n", Volume->FatType); - status = FALSE; - break; + status = FALSE; + break; } //TRACE("FAT entry is 0x%x.\n", fat); - HeapFree(FrLdrTempHeap, ReadBuffer, 'xTAF'); + HeapFree(FrLdrTempHeap, ReadBuffer, 'xTAF'); *ClusterPointer = fat; - return TRUE; + return status; } ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, ULONG StartCluster) From a769501f01a809e8abd4aa2f9ec0d696df6efc97 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 28 Oct 2012 13:53:39 +0000 Subject: [PATCH 04/16] [SAMSRV] Implement SamrRemoveMemberFromAlias and SamrRemoveMultipleMembersFromAlias. svn path=/trunk/; revision=57639 --- reactos/dll/win32/samsrv/samrpc.c | 148 ++++++++++++++++++++++++++++-- 1 file changed, 141 insertions(+), 7 deletions(-) diff --git a/reactos/dll/win32/samsrv/samrpc.c b/reactos/dll/win32/samsrv/samrpc.c index 826bdc7f7f2..fc885fd02b1 100644 --- a/reactos/dll/win32/samsrv/samrpc.c +++ b/reactos/dll/win32/samsrv/samrpc.c @@ -7,18 +7,18 @@ * PROGRAMMERS: Eric Kohl */ -/* INCLUDES ****************************************************************/ +/* INCLUDES ******************************************************************/ #include "samsrv.h" WINE_DEFAULT_DEBUG_CHANNEL(samsrv); -/* GLOBALS ********************************************************************/ +/* GLOBALS *******************************************************************/ static SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY}; -/* FUNCTIONS ***************************************************************/ +/* FUNCTIONS *****************************************************************/ VOID SampStartRpcServer(VOID) @@ -4187,10 +4187,126 @@ NTAPI SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle, IN PRPC_SID MemberId) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PSAM_DB_OBJECT AliasObject; + LPWSTR MemberIdString = NULL; + HANDLE MembersKeyHandle = NULL; + HANDLE MemberKeyHandle = NULL; + ULONG ulValueCount; + NTSTATUS Status; + + TRACE("SamrRemoveMemberFromAlias(%p %p)\n", + AliasHandle, MemberId); + + /* Validate the alias handle */ + Status = SampValidateDbObject(AliasHandle, + SamDbAliasObject, + ALIAS_REMOVE_MEMBER, + &AliasObject); + if (!NT_SUCCESS(Status)) + { + TRACE("failed with status 0x%08lx\n", Status); + return Status; + } + + ConvertSidToStringSidW(MemberId, &MemberIdString); + TRACE("Member SID: %S\n", MemberIdString); + + Status = SampRegOpenKey(AliasObject->MembersKeyHandle, + MemberIdString, + KEY_WRITE | KEY_QUERY_VALUE, + &MemberKeyHandle); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegOpenKey failed with status 0x%08lx\n", Status); + goto done; + } + + Status = SampRegDeleteValue(MemberKeyHandle, + AliasObject->Name); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegDeleteValue failed with status 0x%08lx\n", Status); + goto done; + } + + Status = SampRegQueryKeyInfo(MemberKeyHandle, + NULL, + &ulValueCount); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status); + goto done; + } + + if (ulValueCount == 0) + { + SampRegCloseKey(MemberKeyHandle); + MemberKeyHandle = NULL; + + Status = SampRegDeleteKey(AliasObject->MembersKeyHandle, + MemberIdString); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegDeleteKey failed with status 0x%08lx\n", Status); + goto done; + } + } + + Status = SampRegOpenKey(AliasObject->KeyHandle, + L"Members", + KEY_WRITE | KEY_QUERY_VALUE, + &MembersKeyHandle); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegOpenKey failed with status 0x%08lx\n", Status); + goto done; + } + + Status = SampRegDeleteValue(MembersKeyHandle, + MemberIdString); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegDeleteValue failed with status 0x%08lx\n", Status); + goto done; + } + + Status = SampRegQueryKeyInfo(MembersKeyHandle, + NULL, + &ulValueCount); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status); + goto done; + } + + if (ulValueCount == 0) + { + SampRegCloseKey(MembersKeyHandle); + MembersKeyHandle = NULL; + + Status = SampRegDeleteKey(AliasObject->KeyHandle, + L"Members"); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegDeleteKey failed with status 0x%08lx\n", Status); + goto done; + } + } + +done: + if (MemberKeyHandle != NULL) + SampRegCloseKey(MemberKeyHandle); + + if (MembersKeyHandle != NULL) + SampRegCloseKey(MembersKeyHandle); + + if (MemberIdString != NULL) + LocalFree(MemberIdString); + + return Status; } + /* Function 33 */ NTSTATUS NTAPI @@ -6338,10 +6454,28 @@ NTAPI SamrRemoveMultipleMembersFromAlias(IN SAMPR_HANDLE AliasHandle, IN PSAMPR_PSID_ARRAY MembersBuffer) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + ULONG i; + NTSTATUS Status = STATUS_SUCCESS; + + TRACE("SamrRemoveMultipleMembersFromAlias(%p %p)\n", + AliasHandle, MembersBuffer); + + for (i = 0; i < MembersBuffer->Count; i++) + { + Status = SamrRemoveMemberFromAlias(AliasHandle, + ((PSID *)MembersBuffer->Sids)[i]); + + if (Status == STATUS_MEMBER_IN_ALIAS) + Status = STATUS_SUCCESS; + + if (!NT_SUCCESS(Status)) + break; + } + + return Status; } + /* Function 54 */ NTSTATUS NTAPI From 2108e7256c184372e7447b4b99976b00d95d10ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Sun, 28 Oct 2012 14:37:40 +0000 Subject: [PATCH 05/16] [WIN32K] - Plug an icon leak. svn path=/trunk/; revision=57640 --- reactos/win32ss/user/ntuser/painting.c | 1 + 1 file changed, 1 insertion(+) diff --git a/reactos/win32ss/user/ntuser/painting.c b/reactos/win32ss/user/ntuser/painting.c index e7145fd0826..f85adff9b7c 100644 --- a/reactos/win32ss/user/ntuser/painting.c +++ b/reactos/win32ss/user/ntuser/painting.c @@ -2003,6 +2003,7 @@ BOOL UserDrawCaption( LONG x = Rect.left - cx/2 + 1 + (Rect.bottom - Rect.top)/2; // this is really what Window does LONG y = (Rect.top + Rect.bottom)/2 - cy/2; // center UserDrawIconEx(hDc, x, y, pIcon, cx, cy, 0, NULL, DI_NORMAL); + UserDereferenceObject(pIcon); } } From b6e5342bce3a82a2926eaffec6daf1b1930d2c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Sun, 28 Oct 2012 14:45:35 +0000 Subject: [PATCH 06/16] [WIN32K] - Properly handle deletion of cursor/Icon objects - Gracefully change object owner when process closes - Remove useless check in a macro svn path=/trunk/; revision=57641 --- reactos/win32ss/gdi/ntgdi/misc.h | 2 +- reactos/win32ss/user/ntuser/cursoricon.c | 81 +++++++++--------------- reactos/win32ss/user/ntuser/object.c | 32 ++++++++++ reactos/win32ss/user/ntuser/object.h | 1 + 4 files changed, 64 insertions(+), 52 deletions(-) diff --git a/reactos/win32ss/gdi/ntgdi/misc.h b/reactos/win32ss/gdi/ntgdi/misc.h index addd2591806..22297f05bf7 100644 --- a/reactos/win32ss/gdi/ntgdi/misc.h +++ b/reactos/win32ss/gdi/ntgdi/misc.h @@ -163,6 +163,6 @@ BOOL NTAPI W32kDosPathNameToNtPathName(PCWSTR, PUNICODE_STRING); #define LIST_FOR_EACH_SAFE(cursor, cursor2, list, type, field) \ for ((cursor) = CONTAINING_RECORD((list)->Flink, type, field), \ (cursor2) = CONTAINING_RECORD((cursor)->field.Flink, type, field); \ - &(cursor)->field != (list) && ((&((cursor)->field)) != NULL); \ + &(cursor)->field != (list); \ (cursor) = (cursor2), \ (cursor2) = CONTAINING_RECORD((cursor)->field.Flink, type, field)) diff --git a/reactos/win32ss/user/ntuser/cursoricon.c b/reactos/win32ss/user/ntuser/cursoricon.c index 593e6ae7874..7ba56db0700 100644 --- a/reactos/win32ss/user/ntuser/cursoricon.c +++ b/reactos/win32ss/user/ntuser/cursoricon.c @@ -234,55 +234,54 @@ IntCreateCurIconHandle() } BOOLEAN FASTCALL -IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOL ProcessCleanup) +IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi) { PSYSTEM_CURSORINFO CurInfo; HBITMAP bmpMask, bmpColor; - BOOLEAN Ret; + BOOLEAN Ret, bListEmpty, bFound = FALSE; PCURICON_PROCESS Current = NULL; - PPROCESSINFO W32Process = PsGetCurrentProcessWin32Process(); - - /* Private objects can only be destroyed by their own process */ - if (NULL == CurIcon->hModule) - { - ASSERT(CurIcon->ProcessList.Flink->Flink == &CurIcon->ProcessList); - Current = CONTAINING_RECORD(CurIcon->ProcessList.Flink, CURICON_PROCESS, ListEntry); - if (Current->Process != W32Process) - { - ERR("Trying to destroy private icon/cursor of another process\n"); - return FALSE; - } - } - else if (! ProcessCleanup) - { - TRACE("Trying to destroy shared icon/cursor\n"); - return FALSE; - } + + /* For handles created without any data (error handling) */ + if(IsListEmpty(&CurIcon->ProcessList)) + goto emptyList; /* Now find this process in the list of processes referencing this object and remove it from that list */ LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry) { - if (Current->Process == W32Process) + if (Current->Process == ppi) { - RemoveEntryList(&Current->ListEntry); + bFound = TRUE; + bListEmpty = RemoveEntryList(&Current->ListEntry); break; } } + + if(!bFound) + { + /* This object doesn't belong to this process */ + EngSetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } ExFreeToPagedLookasideList(pgProcessLookasideList, Current); /* If there are still processes referencing this object we can't destroy it yet */ - if (! IsListEmpty(&CurIcon->ProcessList)) + if (!bListEmpty) { + if(CurIcon->head.ppi == ppi) + { + /* Set the first process of the list as owner */ + Current = CONTAINING_RECORD(CurIcon->ProcessList.Flink, CURICON_PROCESS, ListEntry); + UserSetObjectOwner(CurIcon, otCursorIcon, Current->Process); + } + UserDereferenceObject(CurIcon); return TRUE; } - - if (! ProcessCleanup) - { - RemoveEntryList(&CurIcon->ListEntry); - } +emptyList: + /* Remove it from the list */ + RemoveEntryList(&CurIcon->ListEntry); CurInfo = IntGetSysCursorInfo(); @@ -320,33 +319,13 @@ VOID FASTCALL IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process) { PCURICON_OBJECT CurIcon, tmp; - PCURICON_PROCESS ProcessData; + /* Run through the list of icon objects */ LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry) { UserReferenceObject(CurIcon); - // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) - { - LIST_FOR_EACH(ProcessData, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry) - { - if (Win32Process == ProcessData->Process) - { - RemoveEntryList(&CurIcon->ListEntry); - IntDestroyCurIconObject(CurIcon, TRUE); - CurIcon = NULL; - break; - } - } - -// UserDereferenceObject(Object); - } - - if (CurIcon) - { - UserDereferenceObject(CurIcon); - } + IntDestroyCurIconObject(CurIcon, Win32Process); } - } @@ -649,7 +628,7 @@ NtUserDestroyCursor( RETURN(FALSE); } - ret = IntDestroyCurIconObject(CurIcon, FALSE); + ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process()); /* Note: IntDestroyCurIconObject will remove our reference for us! */ RETURN(ret); diff --git a/reactos/win32ss/user/ntuser/object.c b/reactos/win32ss/user/ntuser/object.c index 94242ef83fe..d7785754073 100644 --- a/reactos/win32ss/user/ntuser/object.c +++ b/reactos/win32ss/user/ntuser/object.c @@ -516,6 +516,38 @@ UserReferenceObjectByHandle(HANDLE handle, USER_OBJECT_TYPE type) return object; } +VOID +FASTCALL +UserSetObjectOwner(PVOID obj, USER_OBJECT_TYPE type, PVOID owner) +{ + PUSER_HANDLE_ENTRY entry = handle_to_entry(gHandleTable, ((PHEAD)obj)->h ); + PPROCESSINFO ppi, oldppi; + + /* This must be called with a valid object */ + ASSERT(entry); + + /* For now, only supported for CursorIcon object */ + switch(type) + { + case otCursorIcon: + ppi = (PPROCESSINFO)owner; + entry->pi = ppi; + oldppi = ((PPROCMARKHEAD)obj)->ppi; + ((PPROCMARKHEAD)obj)->ppi = ppi; + break; + default: + ASSERT(FALSE); + return; + } + + oldppi->UserHandleCount--; + ppi->UserHandleCount++; +#if DBG + oldppi->DbgHandleCount[type]--; + ppi->DbgHandleCount[type]++; +#endif +} + /* * NtUserValidateHandleSecure * diff --git a/reactos/win32ss/user/ntuser/object.h b/reactos/win32ss/user/ntuser/object.h index 976fd463af6..08ae96ebcb2 100644 --- a/reactos/win32ss/user/ntuser/object.h +++ b/reactos/win32ss/user/ntuser/object.h @@ -40,6 +40,7 @@ PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE, HANDLE, USER_OBJECT_TYPE); BOOL FASTCALL UserCreateHandleTable(VOID); BOOL FASTCALL UserObjectInDestroy(HANDLE); void DbgUserDumpHandleTable(); +VOID FASTCALL UserSetObjectOwner(PVOID obj, USER_OBJECT_TYPE type, PVOID owner); static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry) From 7aed406e5531586f6a097b8d67a2b289060e8f6d Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Sun, 28 Oct 2012 17:31:33 +0000 Subject: [PATCH 07/16] [win32k] - Plug some object leaks in callproc and clipboard code svn path=/trunk/; revision=57642 --- reactos/win32ss/user/ntuser/callproc.c | 3 +++ reactos/win32ss/user/ntuser/clipboard.c | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/reactos/win32ss/user/ntuser/callproc.c b/reactos/win32ss/user/ntuser/callproc.c index 3d0f2fc998c..815cee50d81 100644 --- a/reactos/win32ss/user/ntuser/callproc.c +++ b/reactos/win32ss/user/ntuser/callproc.c @@ -46,6 +46,9 @@ CreateCallProc(IN PDESKTOP Desktop, NewCallProc->spcpdNext = NULL; } + /* Release the extra reference (UserCreateObject added 2 references) */ + UserDereferenceObject(NewCallProc); + return NewCallProc; } diff --git a/reactos/win32ss/user/ntuser/clipboard.c b/reactos/win32ss/user/ntuser/clipboard.c index e238e54a6be..72bac911b0f 100644 --- a/reactos/win32ss/user/ntuser/clipboard.c +++ b/reactos/win32ss/user/ntuser/clipboard.c @@ -211,6 +211,9 @@ IntSynthesizeDib( /* Add the clipboard data */ IntAddFormatedData(pWinStaObj, CF_DIB, hMem, TRUE, TRUE); + /* Release the extra reference (UserCreateObject added 2 references) */ + UserDereferenceObject(pClipboardData); + cleanup: UserReleaseDC(NULL, hdc, FALSE); } @@ -302,6 +305,9 @@ IntAddSynthesizedFormats(PWINSTATION_OBJECT pWinStaObj) *((LCID*)pMemObj->Data) = NtCurrentTeb()->CurrentLocale; IntAddFormatedData(pWinStaObj, CF_LOCALE, hMem, TRUE, TRUE); } + + /* Release the extra reference (UserCreateObject added 2 references) */ + UserDereferenceObject(pMemObj); } /* Add CF_TEXT. Note: it is synthesized in user32.dll */ @@ -1099,6 +1105,9 @@ NtUserConvertMemHandle( } _SEH2_END; + /* Release the extra reference (UserCreateObject added 2 references) */ + UserDereferenceObject(pMemObj); + /* If we failed to copy data, remove handle */ if (!pMemObj) { From 3a6c8d107b3fdd2d68138631dc1441024973a96d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Mon, 29 Oct 2012 01:43:38 +0000 Subject: [PATCH 08/16] [WIN32SS/USER] - Begin a rewrite of our cursor/Icons implementation. The current one is too close to wine's. svn path=/trunk/; revision=57644 --- reactos/win32ss/CMakeLists.txt | 5 + reactos/win32ss/include/ntuser.h | 30 +- reactos/win32ss/user/ntuser/cursoricon.c | 364 +++++---- reactos/win32ss/user/ntuser/cursoricon.h | 13 +- reactos/win32ss/user/ntuser/msgqueue.c | 16 +- reactos/win32ss/user/user32/CMakeLists.txt | 8 +- reactos/win32ss/user/user32/misc/exticon.c | 24 - .../user/user32/windows/cursoricon_new.c | 756 ++++++++++++++++++ reactos/win32ss/w32ksvc.h | 4 + 9 files changed, 1026 insertions(+), 194 deletions(-) create mode 100644 reactos/win32ss/user/user32/windows/cursoricon_new.c diff --git a/reactos/win32ss/CMakeLists.txt b/reactos/win32ss/CMakeLists.txt index 0cbe6b16ff4..010e38886c4 100644 --- a/reactos/win32ss/CMakeLists.txt +++ b/reactos/win32ss/CMakeLists.txt @@ -1,5 +1,6 @@ set(USE_DIBLIB FALSE) +set(USE_NEW_CURSORICON FALSE) # Give WIN32 subsystem its own project. PROJECT(WIN32SS) @@ -10,6 +11,10 @@ if(USE_DIBLIB) add_subdirectory(gdi/diblib) endif() +if(USE_NEW_CURSORICON) + add_definitions(-DNEW_CURSORICON) +endif() + add_subdirectory(gdi/gdi32) add_subdirectory(reactx) add_subdirectory(user/user32) diff --git a/reactos/win32ss/include/ntuser.h b/reactos/win32ss/include/ntuser.h index 3a0e9630d87..b0e1a4e42fb 100644 --- a/reactos/win32ss/include/ntuser.h +++ b/reactos/win32ss/include/ntuser.h @@ -2739,14 +2739,24 @@ NtUserSetCursorContents( HANDLE Handle, PICONINFO IconInfo); -#if 0 // Correct type. +#ifdef NEW_CURSORICON BOOL NTAPI NtUserSetCursorIconData( - HCURSOR hCursor, - PUNICODE_STRING ModuleName, - PUNICODE_STRING ResourceName, - PCURSORDATA pCursorData); + _In_ HCURSOR hCursor, + _In_ HINSTANCE hinst, + _In_ HRSRC hrsrc, + _In_ PICONINFO pii); +#else +BOOL +NTAPI +NtUserSetCursorIconData( + HANDLE Handle, + PBOOL fIcon, + POINT *Hotspot, + HMODULE hModule, + HRSRC hRsrc, + HRSRC hGroupRsrc); #endif DWORD @@ -3361,16 +3371,6 @@ NtUserMonitorFromWindow( IN HWND hWnd, IN DWORD dwFlags); -BOOL -NTAPI -NtUserSetCursorIconData( - HANDLE Handle, - PBOOL fIcon, - POINT *Hotspot, - HMODULE hModule, - HRSRC hRsrc, - HRSRC hGroupRsrc); - typedef struct _SETSCROLLBARINFO { int nTrackPos; diff --git a/reactos/win32ss/user/ntuser/cursoricon.c b/reactos/win32ss/user/ntuser/cursoricon.c index 7ba56db0700..0c772a2155d 100644 --- a/reactos/win32ss/user/ntuser/cursoricon.c +++ b/reactos/win32ss/user/ntuser/cursoricon.c @@ -237,7 +237,7 @@ BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi) { PSYSTEM_CURSORINFO CurInfo; - HBITMAP bmpMask, bmpColor; + HBITMAP bmpMask, bmpColor, bmpAlpha; BOOLEAN Ret, bListEmpty, bFound = FALSE; PCURICON_PROCESS Current = NULL; @@ -291,21 +291,28 @@ emptyList: UserSetCursor(NULL, TRUE); } - bmpMask = CurIcon->IconInfo.hbmMask; - bmpColor = CurIcon->IconInfo.hbmColor; + bmpMask = CurIcon->aFrame[0].hbmMask; + bmpColor = CurIcon->aFrame[0].hbmColor; + bmpAlpha = CurIcon->aFrame[0].hbmAlpha; /* Delete bitmaps */ if (bmpMask) { GreSetObjectOwner(bmpMask, GDI_OBJ_HMGR_POWNED); GreDeleteObject(bmpMask); - CurIcon->IconInfo.hbmMask = NULL; + CurIcon->aFrame[0].hbmMask = NULL; } if (bmpColor) { GreSetObjectOwner(bmpColor, GDI_OBJ_HMGR_POWNED); GreDeleteObject(bmpColor); - CurIcon->IconInfo.hbmColor = NULL; + CurIcon->aFrame[0].hbmColor = NULL; + } + if (bmpAlpha) + { + GreSetObjectOwner(bmpAlpha, GDI_OBJ_HMGR_POWNED); + GreDeleteObject(bmpAlpha); + CurIcon->aFrame[0].hbmAlpha = NULL; } /* We were given a pointer, no need to keep the reference anylonger! */ @@ -361,18 +368,21 @@ NtUserGetIconInfo( { goto leave; } - - RtlCopyMemory(&ii, &CurIcon->IconInfo, sizeof(ICONINFO)); + + /* Fill data */ + ii.fIcon = CurIcon->bIcon; + ii.xHotspot = CurIcon->ptlHotspot.x; + ii.yHotspot = CurIcon->ptlHotspot.y; /* Copy bitmaps */ - ii.hbmMask = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmMask); - ii.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor); + ii.hbmMask = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmMask); + ii.hbmColor = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmColor); if (pbpp) { PSURFACE psurfBmp; - psurfBmp = SURFACE_ShareLockSurface(CurIcon->IconInfo.hbmColor); + psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor); if (psurfBmp) { colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat); @@ -799,35 +809,103 @@ NtUserSetCursorContents( goto done; } +#if 0 + /* Check if we get valid information */ + if(IconInfo.fIcon != CurInfo->bIcon) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + goto done; + } +#endif + /* Delete old bitmaps */ - if ((CurIcon->IconInfo.hbmColor) - && (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor)) - { - GreDeleteObject(CurIcon->IconInfo.hbmColor); - } - if ((CurIcon->IconInfo.hbmMask) - && CurIcon->IconInfo.hbmMask != IconInfo.hbmMask) - { - GreDeleteObject(CurIcon->IconInfo.hbmMask); - } + if (CurIcon->aFrame[0].hbmColor) + GreDeleteObject(CurIcon->aFrame[0].hbmColor); + if (CurIcon->aFrame[0].hbmMask) + GreDeleteObject(CurIcon->aFrame[0].hbmMask); + if(CurIcon->aFrame[0].hbmAlpha) + GreDeleteObject(CurIcon->aFrame[0].hbmAlpha); - /* Copy new IconInfo field */ - CurIcon->IconInfo = IconInfo; + /* Set fields */ + CurIcon->bIcon = IconInfo.fIcon; + CurIcon->ptlHotspot.x = IconInfo.xHotspot; + CurIcon->ptlHotspot.y = IconInfo.yHotspot; + CurIcon->aFrame[0].hbmMask = IconInfo.hbmMask; + CurIcon->aFrame[0].hbmColor = IconInfo.hbmColor; + CurIcon->aFrame[0].hbmAlpha = NULL; - if (CurIcon->IconInfo.hbmColor) + if (IconInfo.hbmColor) { - psurfBmp = SURFACE_ShareLockSurface(CurIcon->IconInfo.hbmColor); + BOOLEAN bAlpha = FALSE; + psurfBmp = SURFACE_ShareLockSurface(IconInfo.hbmColor); if (!psurfBmp) goto done; - CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; + + /* 32bpp bitmap is likely to have an alpha channel */ + if(psurfBmp->SurfObj.iBitmapFormat == BMF_32BPP) + { + PFN_DIB_GetPixel fn_GetPixel = DibFunctionsForBitmapFormat[BMF_32BPP].DIB_GetPixel; + INT i, j; + + fn_GetPixel = DibFunctionsForBitmapFormat[BMF_32BPP].DIB_GetPixel; + for (i = 0; i < psurfBmp->SurfObj.sizlBitmap.cx; i++) + { + for (j = 0; j < psurfBmp->SurfObj.sizlBitmap.cy; j++) + { + bAlpha = ((BYTE)(fn_GetPixel(&psurfBmp->SurfObj, i, j) >> 24)) != 0; + if (bAlpha) + break; + } + if (bAlpha) + break; + } + } + /* We're done with this one */ SURFACE_ShareUnlockSurface(psurfBmp); - GreSetObjectOwner(CurIcon->IconInfo.hbmColor, GDI_OBJ_HMGR_PUBLIC); + GreSetObjectOwner(IconInfo.hbmColor, GDI_OBJ_HMGR_PUBLIC); + + if(bAlpha) + { + UCHAR Alpha; + PUCHAR ptr; + INT i, j; + /* Copy the bitmap */ + CurIcon->aFrame[0].hbmAlpha = BITMAP_CopyBitmap(IconInfo.hbmColor); + if(!CurIcon->aFrame[0].hbmAlpha) + { + ERR("BITMAP_CopyBitmap failed!"); + goto done; + } + + psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmAlpha); + if(!psurfBmp) + { + ERR("SURFACE_LockSurface failed!\n"); + goto done; + } + + /* Premultiply with the alpha channel value */ + for (i = 0; i < psurfBmp->SurfObj.sizlBitmap.cy; i++) + { + ptr = (PBYTE)psurfBmp->SurfObj.pvScan0 + i*psurfBmp->SurfObj.lDelta; + for (j = 0; j < psurfBmp->SurfObj.sizlBitmap.cx; j++) + { + Alpha = ptr[3]; + ptr[0] = (ptr[0] * Alpha) / 0xff; + ptr[1] = (ptr[1] * Alpha) / 0xff; + ptr[2] = (ptr[2] * Alpha) / 0xff; + ptr += 4; + } + } + SURFACE_ShareUnlockSurface(psurfBmp); + GreSetObjectOwner(CurIcon->aFrame[0].hbmAlpha, GDI_OBJ_HMGR_PUBLIC); + } } else { - psurfBmp = SURFACE_ShareLockSurface(CurIcon->IconInfo.hbmMask); + psurfBmp = SURFACE_ShareLockSurface(IconInfo.hbmMask); if (!psurfBmp) goto done; @@ -836,12 +914,18 @@ NtUserSetCursorContents( SURFACE_ShareUnlockSurface(psurfBmp); } - GreSetObjectOwner(CurIcon->IconInfo.hbmMask, GDI_OBJ_HMGR_PUBLIC); + GreSetObjectOwner(IconInfo.hbmMask, GDI_OBJ_HMGR_PUBLIC); Ret = TRUE; done: + if(!Ret) + { + IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process()); + CurIcon = NULL; + } + if (CurIcon) { UserDereferenceObject(CurIcon); @@ -858,20 +942,21 @@ CLEANUP: /* * @implemented */ -#if 0 +#ifdef NEW_CURSORICON BOOL APIENTRY NtUserSetCursorIconData( - HANDLE Handle, - HMODULE hModule, - PUNICODE_STRING pstrResName, - PICONINFO pIconInfo) + _In_ HCURSOR Handle, + _In_ HINSTANCE hinst, + _In_ HRSRC hrsrc, + _In_ PICONINFO pIconInfo) { PCURICON_OBJECT CurIcon; PSURFACE psurfBmp; NTSTATUS Status = STATUS_SUCCESS; BOOL Ret = FALSE; DECLARE_RETURN(BOOL); + ICONINFO ii; TRACE("Enter NtUserSetCursorIconData\n"); UserEnterExclusive(); @@ -881,54 +966,96 @@ NtUserSetCursorIconData( RETURN(FALSE); } - CurIcon->hModule = hModule; - CurIcon->hRsrc = NULL; //hRsrc; - CurIcon->hGroupRsrc = NULL; //hGroupRsrc; + CurIcon->hModule = hinst; + CurIcon->hRsrc =hrsrc; _SEH2_TRY { ProbeForRead(pIconInfo, sizeof(ICONINFO), 1); - RtlCopyMemory(&CurIcon->IconInfo, pIconInfo, sizeof(ICONINFO)); - - CurIcon->IconInfo.hbmMask = BITMAP_CopyBitmap(pIconInfo->hbmMask); - CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(pIconInfo->hbmColor); - - if (CurIcon->IconInfo.hbmColor) - { - if ((psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor))) - { - CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; - CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; - SURFACE_UnlockSurface(psurfBmp); - GreSetObjectOwner(CurIcon->IconInfo.hbmMask, GDI_OBJ_HMGR_PUBLIC); - } - } - if (CurIcon->IconInfo.hbmMask) - { - if (CurIcon->IconInfo.hbmColor == NULL) - { - if ((psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask))) - { - CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; - CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; - SURFACE_UnlockSurface(psurfBmp); - } - } - GreSetObjectOwner(CurIcon->IconInfo.hbmMask, GDI_OBJ_HMGR_PUBLIC); - } + ii = *pIconInfo; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END - + if (!NT_SUCCESS(Status)) + { SetLastNtError(Status); - else - Ret = TRUE; + goto done; + } + + /* This is probably not what windows does, but consistency checks can't hurt */ + if(CurIcon->bIcon != ii.fIcon) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + CurIcon->ptlHotspot.x = ii.xHotspot; + CurIcon->ptlHotspot.y = ii.yHotspot; + + if(!ii.hbmMask) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + CurIcon->aFrame[0].hbmMask = BITMAP_CopyBitmap(ii.hbmMask); + if(!CurIcon->aFrame[0].hbmMask) + goto done; + if(ii.hbmColor) + { + CurIcon->aFrame[0].hbmColor = BITMAP_CopyBitmap(ii.hbmColor); + if(!CurIcon->aFrame[0].hbmColor) + goto done; + } + + if (CurIcon->aFrame[0].hbmColor) + { + if ((psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor))) + { + CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; + CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; + SURFACE_ShareUnlockSurface(psurfBmp); + GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); + } + else + goto done; + } + else + { + if ((psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmMask))) + { + CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; + CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy/2; + SURFACE_ShareUnlockSurface(psurfBmp); + } + else + goto done; + } + GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); + + Ret = TRUE; + +done: UserDereferenceObject(CurIcon); + if(!Ret) + { + if (CurIcon->aFrame[0].hbmMask) + { + GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_POWNED); + GreDeleteObject(CurIcon->aFrame[0].hbmMask); + CurIcon->aFrame[0].hbmMask = NULL; + } + if (CurIcon->aFrame[0].hbmColor) + { + GreSetObjectOwner(CurIcon->aFrame[0].hbmColor, GDI_OBJ_HMGR_POWNED); + GreDeleteObject(CurIcon->aFrame[0].hbmColor); + CurIcon->aFrame[0].hbmColor = NULL; + } + } RETURN(Ret); CLEANUP: @@ -949,7 +1076,6 @@ NtUserSetCursorIconData( { PCURICON_OBJECT CurIcon; NTSTATUS Status; - POINT SafeHotspot; BOOL Ret = FALSE; DECLARE_RETURN(BOOL); @@ -968,7 +1094,7 @@ NtUserSetCursorIconData( /* Copy fields */ if (fIcon) { - Status = MmCopyFromCaller(&CurIcon->IconInfo.fIcon, fIcon, sizeof(BOOL)); + Status = MmCopyFromCaller(&CurIcon->bIcon, fIcon, sizeof(BOOL)); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); @@ -983,16 +1109,12 @@ NtUserSetCursorIconData( if (Hotspot) { - Status = MmCopyFromCaller(&SafeHotspot, Hotspot, sizeof(POINT)); - if (NT_SUCCESS(Status)) + Status = MmCopyFromCaller(&CurIcon->ptlHotspot, Hotspot, sizeof(POINT)); + if (!NT_SUCCESS(Status)) { - CurIcon->IconInfo.xHotspot = SafeHotspot.x; - CurIcon->IconInfo.yHotspot = SafeHotspot.y; - - Ret = TRUE; - } - else SetLastNtError(Status); + goto done; + } } if (!fIcon && !Hotspot) @@ -1004,10 +1126,14 @@ done: if(Ret) { /* This icon is shared now */ - GreSetObjectOwner(CurIcon->IconInfo.hbmMask, GDI_OBJ_HMGR_PUBLIC); - if(CurIcon->IconInfo.hbmColor) + GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); + if(CurIcon->aFrame[0].hbmColor) { - GreSetObjectOwner(CurIcon->IconInfo.hbmColor, GDI_OBJ_HMGR_PUBLIC); + GreSetObjectOwner(CurIcon->aFrame[0].hbmColor, GDI_OBJ_HMGR_PUBLIC); + } + if(CurIcon->aFrame[0].hbmAlpha) + { + GreSetObjectOwner(CurIcon->aFrame[0].hbmAlpha, GDI_OBJ_HMGR_PUBLIC); } } UserDereferenceObject(CurIcon); @@ -1044,8 +1170,8 @@ UserDrawIconEx( PSURFACE psurfDest, psurfMask, psurfColor, psurfOffScreen; PDC pdc = NULL; BOOL Ret = FALSE; - HBITMAP hbmMask, hbmColor; - BOOL bOffScreen, bAlpha = FALSE; + HBITMAP hbmMask, hbmColor, hbmAlpha; + BOOL bOffScreen; RECTL rcDest, rcSrc; CLIPOBJ* pdcClipObj = NULL; EXLATEOBJ exlo; @@ -1057,8 +1183,9 @@ UserDrawIconEx( return FALSE; } - hbmMask = pIcon->IconInfo.hbmMask; - hbmColor = pIcon->IconInfo.hbmColor; + hbmMask = pIcon->aFrame[0].hbmMask; + hbmColor = pIcon->aFrame[0].hbmColor; + hbmAlpha = pIcon->aFrame[0].hbmAlpha; if (istepIfAniCur) ERR("NtUserDrawIconEx: istepIfAniCur is not supported!\n"); @@ -1091,35 +1218,11 @@ UserDrawIconEx( /* Set source rect */ RECTL_vSetRect(&rcSrc, 0, 0, pIcon->Size.cx, pIcon->Size.cy); - /* Check for alpha */ - if (psurfColor && - (psurfColor->SurfObj.iBitmapFormat == BMF_32BPP) && - (diFlags & DI_IMAGE)) - { - PFN_DIB_GetPixel fnSource_GetPixel = NULL; - INT i, j; - - /* In order to correctly display 32 bit icons Windows first scans the image, - because information about transparency is not stored in any image's headers */ - fnSource_GetPixel = DibFunctionsForBitmapFormat[BMF_32BPP].DIB_GetPixel; - for (i = 0; i < psurfColor->SurfObj.sizlBitmap.cx; i++) - { - for (j = 0; j < psurfColor->SurfObj.sizlBitmap.cy; j++) - { - bAlpha = ((BYTE)(fnSource_GetPixel(&psurfColor->SurfObj, i, j) >> 24) & 0xff); - if (bAlpha) - break; - } - if (bAlpha) - break; - } - } - /* Fix width parameter, if needed */ if (!cxWidth) { if(diFlags & DI_DEFAULTSIZE) - cxWidth = pIcon->IconInfo.fIcon ? + cxWidth = pIcon->bIcon ? UserGetSystemMetrics(SM_CXICON) : UserGetSystemMetrics(SM_CXCURSOR); else cxWidth = pIcon->Size.cx; @@ -1129,7 +1232,7 @@ UserDrawIconEx( if (!cyHeight) { if(diFlags & DI_DEFAULTSIZE) - cyHeight = pIcon->IconInfo.fIcon ? + cyHeight = pIcon->bIcon ? UserGetSystemMetrics(SM_CYICON) : UserGetSystemMetrics(SM_CYCURSOR); else cyHeight = pIcon->Size.cy; @@ -1238,42 +1341,16 @@ UserDrawIconEx( } /* Now do the rendering */ - if(bAlpha && (diFlags & DI_IMAGE)) + if(hbmAlpha && (diFlags & DI_IMAGE)) { BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } }; - BYTE Alpha; - INT i, j; PSURFACE psurf = NULL; - PBYTE ptr ; - HBITMAP hsurfCopy = NULL; - hsurfCopy = BITMAP_CopyBitmap(hbmColor); - if(!hsurfCopy) - { - ERR("BITMAP_CopyBitmap failed!"); - goto CleanupAlpha; - } - - psurf = SURFACE_ShareLockSurface(hsurfCopy); + psurf = SURFACE_ShareLockSurface(hbmAlpha); if(!psurf) { ERR("SURFACE_LockSurface failed!\n"); - goto CleanupAlpha; - } - - /* Premultiply with the alpha channel value */ - for (i = 0; i < psurf->SurfObj.sizlBitmap.cy; i++) - { - ptr = (PBYTE)psurf->SurfObj.pvScan0 + i*psurf->SurfObj.lDelta; - for (j = 0; j < psurf->SurfObj.sizlBitmap.cx; j++) - { - Alpha = ptr[3]; - ptr[0] = (ptr[0] * Alpha) / 0xff; - ptr[1] = (ptr[1] * Alpha) / 0xff; - ptr[2] = (ptr[2] * Alpha) / 0xff; - - ptr += 4; - } + goto NoAlpha; } /* Initialize color translation object */ @@ -1289,14 +1366,11 @@ UserDrawIconEx( &blendobj); EXLATEOBJ_vCleanup(&exlo); - - CleanupAlpha: - if(psurf) SURFACE_ShareUnlockSurface(psurf); - if(hsurfCopy) NtGdiDeleteObjectApp(hsurfCopy); - if(Ret) goto done; + SURFACE_ShareUnlockSurface(psurf); + if(Ret) goto done; ERR("NtGdiAlphaBlend failed!\n"); } - +NoAlpha: if (diFlags & DI_MASK) { DWORD rop4 = (diFlags & DI_IMAGE) ? ROP4_SRCAND : ROP4_SRCCOPY; diff --git a/reactos/win32ss/user/ntuser/cursoricon.h b/reactos/win32ss/user/ntuser/cursoricon.h index ca48c934f02..722daebe820 100644 --- a/reactos/win32ss/user/ntuser/cursoricon.h +++ b/reactos/win32ss/user/ntuser/cursoricon.h @@ -8,6 +8,13 @@ typedef struct tagCURICON_PROCESS PPROCESSINFO Process; } CURICON_PROCESS, *PCURICON_PROCESS; +typedef struct _CURICON_FRAME +{ + HBITMAP hbmMask; + HBITMAP hbmColor; + HBITMAP hbmAlpha; +} CURICON_FRAME, *PCURICON_FRAME; + typedef struct _CURICON_OBJECT { PROCMARKHEAD head; @@ -16,10 +23,14 @@ typedef struct _CURICON_OBJECT LIST_ENTRY ProcessList; HMODULE hModule; HRSRC hRsrc; +#ifndef NEW_CURSORICON HRSRC hGroupRsrc; +#endif SIZE Size; BYTE Shadow; - ICONINFO IconInfo; + BOOL bIcon; + POINTL ptlHotspot; + CURICON_FRAME aFrame[1]; } CURICON_OBJECT, *PCURICON_OBJECT; typedef struct _CURSORACCELERATION_INFO diff --git a/reactos/win32ss/user/ntuser/msgqueue.c b/reactos/win32ss/user/ntuser/msgqueue.c index 084f04ddfe7..38245a1ec82 100644 --- a/reactos/win32ss/user/ntuser/msgqueue.c +++ b/reactos/win32ss/user/ntuser/msgqueue.c @@ -146,10 +146,10 @@ UserSetCursor( { /* Call GDI to set the new screen cursor */ GreSetPointerShape(hdcScreen, - NewCursor->IconInfo.hbmMask, - NewCursor->IconInfo.hbmColor, - NewCursor->IconInfo.xHotspot, - NewCursor->IconInfo.yHotspot, + NewCursor->aFrame[0].hbmMask, + NewCursor->aFrame[0].hbmColor, + NewCursor->ptlHotspot.x, + NewCursor->ptlHotspot.y, gpsi->ptCursor.x, gpsi->ptCursor.y); } @@ -572,10 +572,10 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook { /* Call GDI to set the new screen cursor */ GreSetPointerShape(hdcScreen, - MessageQueue->CursorObject->IconInfo.hbmMask, - MessageQueue->CursorObject->IconInfo.hbmColor, - MessageQueue->CursorObject->IconInfo.xHotspot, - MessageQueue->CursorObject->IconInfo.yHotspot, + MessageQueue->CursorObject->aFrame[0].hbmMask, + MessageQueue->CursorObject->aFrame[0].hbmColor, + MessageQueue->CursorObject->ptlHotspot.x, + MessageQueue->CursorObject->ptlHotspot.y, gpsi->ptCursor.x, gpsi->ptCursor.y); } else diff --git a/reactos/win32ss/user/user32/CMakeLists.txt b/reactos/win32ss/user/user32/CMakeLists.txt index b67b30d33e7..8c5930d14a9 100644 --- a/reactos/win32ss/user/user32/CMakeLists.txt +++ b/reactos/win32ss/user/user32/CMakeLists.txt @@ -41,7 +41,7 @@ list(APPEND SOURCE windows/caret.c windows/class.c windows/clipboard.c - windows/cursoricon.c +# windows/cursoricon.c windows/dc.c windows/defwnd.c windows/dialog.c @@ -64,6 +64,12 @@ list(APPEND SOURCE user32.rc ${CMAKE_CURRENT_BINARY_DIR}/user32.def) +if(USE_NEW_CURSORICON) + list(APPEND SOURCE windows/cursoricon_new.c) +else() + list(APPEND SOURCE windows/cursoricon.c) +endif() + add_library(user32 SHARED ${SOURCE}) set_module_type(user32 win32dll UNICODE) diff --git a/reactos/win32ss/user/user32/misc/exticon.c b/reactos/win32ss/user/user32/misc/exticon.c index 00b3b3e87da..7455f22cd83 100644 --- a/reactos/win32ss/user/user32/misc/exticon.c +++ b/reactos/win32ss/user/user32/misc/exticon.c @@ -30,30 +30,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(icon); -#include "pshpack1.h" - -typedef struct -{ - BYTE bWidth; /* Width, in pixels, of the image */ - BYTE bHeight; /* Height, in pixels, of the image */ - BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */ - BYTE bReserved; /* Reserved ( must be 0) */ - WORD wPlanes; /* Color Planes */ - WORD wBitCount; /* Bits per pixel */ - DWORD dwBytesInRes; /* How many bytes in this resource? */ - DWORD dwImageOffset; /* Where in the file is this image? */ -} icoICONDIRENTRY, *LPicoICONDIRENTRY; - -typedef struct -{ - WORD idReserved; /* Reserved (must be 0) */ - WORD idType; /* Resource Type (RES_ICON or RES_CURSOR) */ - WORD idCount; /* How many images */ - icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */ -} icoICONDIR, *LPicoICONDIR; - -#include "poppack.h" - #if 0 static void dumpIcoDirEnty ( LPicoICONDIRENTRY entry ) { diff --git a/reactos/win32ss/user/user32/windows/cursoricon_new.c b/reactos/win32ss/user/user32/windows/cursoricon_new.c new file mode 100644 index 00000000000..d1276192ad6 --- /dev/null +++ b/reactos/win32ss/user/user32/windows/cursoricon_new.c @@ -0,0 +1,756 @@ +/* + * PROJECT: ReactOS user32.dll + * COPYRIGHT: GPL - See COPYING in the top level directory + * FILE: dll/win32/user32/windows/class.c + * PURPOSE: Window classes + * PROGRAMMER: Jérôme Gardou (jerome.gardou@reactos.org) + */ + +#include + +#include + +WINE_DEFAULT_DEBUG_CHANNEL(cursor); +//WINE_DECLARE_DEBUG_CHANNEL(icon); +//WINE_DECLARE_DEBUG_CHANNEL(resource); + +/************* USER32 INTERNAL FUNCTIONS **********/ + +/* This callback routine is called directly after switching to gui mode */ +NTSTATUS +WINAPI +User32SetupDefaultCursors(PVOID Arguments, + ULONG ArgumentLength) +{ + BOOL *DefaultCursor = (BOOL*)Arguments; + HCURSOR hCursor; + + if(*DefaultCursor) + { + /* set default cursor */ + hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW); + SetCursor(hCursor); + } + else + { + /* FIXME load system cursor scheme */ + SetCursor(0); + hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW); + SetCursor(hCursor); + } + + return(ZwCallbackReturn(&hCursor, sizeof(HCURSOR), STATUS_SUCCESS)); +} + +BOOL get_icon_size(HICON hIcon, SIZE *size) +{ + return NtUserGetIconSize(hIcon, 0, &size->cx, &size->cy); +} + +HCURSOR CursorIconToCursor(HICON hIcon, BOOL SemiTransparent) +{ + UNIMPLEMENTED; + return NULL; +} + +/************* IMPLEMENTATION HELPERS ******************/ + +static int get_dib_image_size( int width, int height, int depth ) +{ + return (((width * depth + 31) / 8) & ~3) * abs( height ); +} + +static BOOL is_dib_monochrome( const BITMAPINFO* info ) +{ + if (info->bmiHeader.biBitCount != 1) return FALSE; + + if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + const RGBTRIPLE *rgb = ((const BITMAPCOREINFO*)info)->bmciColors; + + /* Check if the first color is black */ + if ((rgb->rgbtRed == 0) && (rgb->rgbtGreen == 0) && (rgb->rgbtBlue == 0)) + { + rgb++; + + /* Check if the second color is white */ + return ((rgb->rgbtRed == 0xff) && (rgb->rgbtGreen == 0xff) + && (rgb->rgbtBlue == 0xff)); + } + else return FALSE; + } + else /* assume BITMAPINFOHEADER */ + { + const RGBQUAD *rgb = info->bmiColors; + + /* Check if the first color is black */ + if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) && + (rgb->rgbBlue == 0) && (rgb->rgbReserved == 0)) + { + rgb++; + + /* Check if the second color is white */ + return ((rgb->rgbRed == 0xff) && (rgb->rgbGreen == 0xff) + && (rgb->rgbBlue == 0xff) && (rgb->rgbReserved == 0)); + } + else return FALSE; + } +} + +static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse ) +{ + unsigned int colors, size, masks = 0; + + if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info; + colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0; + return sizeof(BITMAPCOREHEADER) + colors * + ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD)); + } + else /* assume BITMAPINFOHEADER */ + { + colors = info->bmiHeader.biClrUsed; + if (colors > 256) /* buffer overflow otherwise */ + colors = 256; + if (!colors && (info->bmiHeader.biBitCount <= 8)) + colors = 1 << info->bmiHeader.biBitCount; + if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3; + size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) ); + return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD)); + } +} + +/************* IMPLEMENTATION CORE ****************/ + +static BOOL CURSORICON_GetIconInfoFromBMI( + _Inout_ ICONINFO* pii, + _In_ const BITMAPINFO *pbmi, + _In_ int cxDesired, + _In_ int cyDesired +) +{ + UINT ubmiSize = bitmap_info_size(pbmi, DIB_RGB_COLORS); + BOOL monochrome = is_dib_monochrome(pbmi); + HDC hdc, hdcScreen; + BITMAPINFO* pbmiCopy; + HBITMAP hbmpOld = NULL; + BOOL bResult = FALSE; + const VOID *pvColor, *pvMask; + + /* Check for invalid data */ + if ( (pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER) && + pbmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) || + pbmi->bmiHeader.biCompression != BI_RGB ) + { + WARN("Invalid resource bitmap header.\n"); + return FALSE; + } + + /* Fix the hotspot coords */ + if(cxDesired != pbmi->bmiHeader.biWidth) + pii->xHotspot = (pii->xHotspot * cxDesired) / pbmi->bmiHeader.biWidth; + if(cxDesired != (pbmi->bmiHeader.biHeight/2)) + pii->yHotspot = (pii->yHotspot * cyDesired * 2) / pbmi->bmiHeader.biHeight; + + hdcScreen = CreateDCW(L"DISPLAY", NULL, NULL, NULL); + if(!hdcScreen) + return FALSE; + hdc = CreateCompatibleDC(hdcScreen); + if(!hdc) + { + DeleteDC(hdcScreen); + return FALSE; + } + + pbmiCopy = HeapAlloc(GetProcessHeap(), 0, max(ubmiSize, FIELD_OFFSET(BITMAPINFO, bmiColors[3]))); + if(!pbmiCopy) + goto done; + RtlCopyMemory(pbmiCopy, pbmi, ubmiSize); + pbmiCopy->bmiHeader.biHeight /= 2; + + pvColor = (const char*)pbmi + ubmiSize; + pvMask = (const char*)pvColor + + get_dib_image_size(pbmi->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight, pbmi->bmiHeader.biBitCount ); + + /* Set XOR bits */ + if(monochrome) + { + /* Create the 1bpp bitmap which will contain everything */ + pii->hbmColor = NULL; + pii->hbmMask = CreateCompatibleBitmap(hdc, cxDesired, cyDesired * 2); + if(!pii->hbmMask) + goto done; + hbmpOld = SelectObject(hdc, pii->hbmMask); + if(!hbmpOld) + goto done; + + if(!StretchDIBits(hdc, 0, cyDesired, cxDesired, cyDesired, + 0, 0, pbmiCopy->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight, + pvColor, pbmiCopy, DIB_RGB_COLORS, SRCCOPY)) + goto done; + } + else + { + /* Create the bitmap. It has to be compatible with the screen surface */ + pii->hbmColor = CreateCompatibleBitmap(hdcScreen, cxDesired, cyDesired); + if(!pii->hbmColor) + goto done; + /* Create the 1bpp mask bitmap */ + pii->hbmMask = CreateCompatibleBitmap(hdc, cxDesired, cyDesired); + if(!pii->hbmMask) + goto done; + hbmpOld = SelectObject(hdc, pii->hbmColor); + if(!hbmpOld) + goto done; + if(!StretchDIBits(hdc, 0, 0, cxDesired, cyDesired, + 0, 0, pbmiCopy->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight, + pvColor, pbmiCopy, DIB_RGB_COLORS, SRCCOPY)) + goto done; + + /* Now convert the info to monochrome for the mask bits */ + pbmiCopy->bmiHeader.biBitCount = 1; + /* Handle the CORE/INFO difference */ + if (pbmiCopy->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) + { + RGBQUAD *rgb = pbmiCopy->bmiColors; + + pbmiCopy->bmiHeader.biClrUsed = pbmiCopy->bmiHeader.biClrImportant = 2; + rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00; + rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff; + rgb[0].rgbReserved = rgb[1].rgbReserved = 0; + } + else + { + RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pbmiCopy) + 1); + + rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00; + rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff; + } + } + /* Set the mask bits */ + if(!SelectObject(hdc, pii->hbmMask)) + goto done; + bResult = StretchDIBits(hdc, 0, 0, cxDesired, cyDesired, + 0, 0, pbmiCopy->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight, + pvMask, pbmiCopy, DIB_RGB_COLORS, SRCCOPY) != 0; + +done: + DeleteDC(hdcScreen); + if(hbmpOld) SelectObject(hdc, hbmpOld); + DeleteDC(hdc); + if(pbmiCopy) HeapFree(GetProcessHeap(), 0, pbmiCopy); + /* Clean up in case of failure */ + if(!bResult) + { + if(pii->hbmMask) DeleteObject(pii->hbmMask); + if(pii->hbmColor) DeleteObject(pii->hbmColor); + } + return bResult; +} + +static +HANDLE +BITMAP_LoadImageW( + _In_opt_ HINSTANCE hinst, + _In_ LPCWSTR lpszName, + _In_ int cxDesired, + _In_ int cyDesired, + _In_ UINT fuLoad +) +{ + UNIMPLEMENTED; + return NULL; +} + +static +HANDLE +CURSORICON_LoadImageW( + _In_opt_ HINSTANCE hinst, + _In_ LPCWSTR lpszName, + _In_ int cxDesired, + _In_ int cyDesired, + _In_ UINT fuLoad, + _In_ BOOL bIcon +) +{ + HRSRC hrsrc, hrsrc2; + HANDLE handle, hCurIcon; + CURSORICONDIR* dir; + WORD wResId; + LPBYTE bits; + ICONINFO ii; + BOOL bStatus; + + if(fuLoad & LR_LOADFROMFILE) + { + UNIMPLEMENTED; + return NULL; + } + + /* Check if caller wants OEM icons */ + if(!hinst) + hinst = User32Instance; + + /* Find resource ID */ + hrsrc = FindResourceW( + hinst, + lpszName, + (LPWSTR)(bIcon ? RT_GROUP_ICON : RT_GROUP_CURSOR)); + + /* We let FindResource, LoadResource, etc. call SetLastError */ + if(!hrsrc) + return NULL; + + /* Fix width/height */ + if(fuLoad & LR_DEFAULTSIZE) + { + if(!cxDesired) cxDesired = GetSystemMetrics(bIcon ? SM_CXICON : SM_CXCURSOR); + if(!cyDesired) cyDesired = GetSystemMetrics(bIcon ? SM_CYICON : SM_CYCURSOR); + } + + /* If LR_SHARED is set, we must check for the cache */ + hCurIcon = NtUserFindExistingCursorIcon(hinst, hrsrc, cxDesired, cyDesired); + if(hCurIcon) + return hCurIcon; + + handle = LoadResource(hinst, hrsrc); + if(!handle) + return NULL; + + dir = LockResource(handle); + if(!dir) return NULL; + + /* For now, take the first entry */ + wResId = dir->idEntries[0].wResId; + FreeResource(handle); + + /* Get the relevant resource pointer */ + hrsrc2 = FindResourceW( + hinst, + MAKEINTRESOURCEW(wResId), + (LPWSTR)(bIcon ? RT_ICON : RT_CURSOR)); + if(!hrsrc2) + return NULL; + + handle = LoadResource(hinst, hrsrc2); + if(!handle) + return NULL; + + bits = LockResource(handle); + if(!bits) + { + FreeResource(handle); + return NULL; + } + + /* Get the hospot */ + if(bIcon) + { + ii.xHotspot = cxDesired/2; + ii.yHotspot = cyDesired/2; + } + else + { + SHORT* ptr = (SHORT*)bits; + ii.xHotspot = ptr[0]; + ii.yHotspot = ptr[1]; + bits += 2*sizeof(SHORT); + } + ii.fIcon = bIcon; + + /* Get the bitmaps */ + bStatus = CURSORICON_GetIconInfoFromBMI( + &ii, + (BITMAPINFO*)bits, + cxDesired, + cyDesired); + + FreeResource( handle ); + + if(!bStatus) + return NULL; + + /* Create the handle */ + hCurIcon = NtUserxCreateEmptyCurObject(bIcon ? 0 : 1); + if(!hCurIcon) + return NULL; + + /* Tell win32k */ + if(fuLoad & LR_SHARED) + bStatus = NtUserSetCursorIconData(hCurIcon, hinst, hrsrc, &ii); + else + bStatus = NtUserSetCursorIconData(hCurIcon, NULL, NULL, &ii); + + if(!bStatus) + { + NtUserDestroyCursor(hCurIcon, TRUE); + hCurIcon = NULL; + } + + DeleteObject(ii.hbmMask); + DeleteObject(ii.hbmColor); + + return hCurIcon; +} + +/************* PUBLIC FUNCTIONS *******************/ + +HANDLE WINAPI CopyImage( + _In_ HANDLE hImage, + _In_ UINT uType, + _In_ int cxDesired, + _In_ int cyDesired, + _In_ UINT fuFlags +) +{ + UNIMPLEMENTED; + return NULL; +} + +HICON WINAPI CopyIcon( + _In_ HICON hIcon +) +{ + UNIMPLEMENTED; + return NULL; +} + +BOOL WINAPI DrawIcon( + _In_ HDC hDC, + _In_ int X, + _In_ int Y, + _In_ HICON hIcon +) +{ + return DrawIconEx(hDC, X, Y, hIcon, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE); +} + +BOOL WINAPI DrawIconEx( + _In_ HDC hdc, + _In_ int xLeft, + _In_ int yTop, + _In_ HICON hIcon, + _In_ int cxWidth, + _In_ int cyWidth, + _In_ UINT istepIfAniCur, + _In_opt_ HBRUSH hbrFlickerFreeDraw, + _In_ UINT diFlags +) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI GetIconInfo( + _In_ HICON hIcon, + _Out_ PICONINFO piconinfo +) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI DestroyIcon( + _In_ HICON hIcon +) +{ + UNIMPLEMENTED; + return FALSE; +} + +HICON WINAPI LoadIconA( + _In_opt_ HINSTANCE hInstance, + _In_ LPCSTR lpIconName +) +{ + TRACE("%p, %s\n", hInstance, debugstr_a(lpIconName)); + + return LoadImageA(hInstance, + lpIconName, + IMAGE_ICON, + 0, + 0, + LR_SHARED | LR_DEFAULTSIZE ); +} + +HICON WINAPI LoadIconW( + _In_opt_ HINSTANCE hInstance, + _In_ LPCWSTR lpIconName +) +{ + TRACE("%p, %s\n", hInstance, debugstr_w(lpIconName)); + + return LoadImageW(hInstance, + lpIconName, + IMAGE_ICON, + 0, + 0, + LR_SHARED | LR_DEFAULTSIZE ); +} + +HCURSOR WINAPI LoadCursorA( + _In_opt_ HINSTANCE hInstance, + _In_ LPCSTR lpCursorName +) +{ + TRACE("%p, %s\n", hInstance, debugstr_a(lpCursorName)); + + return LoadImageA(hInstance, + lpCursorName, + IMAGE_CURSOR, + 0, + 0, + LR_SHARED | LR_DEFAULTSIZE ); +} + +HCURSOR WINAPI LoadCursorW( + _In_opt_ HINSTANCE hInstance, + _In_ LPCWSTR lpCursorName +) +{ + TRACE("%p, %s\n", hInstance, debugstr_w(lpCursorName)); + + return LoadImageW(hInstance, + lpCursorName, + IMAGE_CURSOR, + 0, + 0, + LR_SHARED | LR_DEFAULTSIZE ); +} + +HCURSOR WINAPI LoadCursorFromFileA( + _In_ LPCSTR lpFileName +) +{ + TRACE("%s\n", debugstr_a(lpFileName)); + + return LoadImageA(NULL, + lpFileName, + IMAGE_CURSOR, + 0, + 0, + LR_LOADFROMFILE | LR_DEFAULTSIZE ); +} + +HCURSOR WINAPI LoadCursorFromFileW( + _In_ LPCWSTR lpFileName +) +{ + TRACE("%s\n", debugstr_w(lpFileName)); + + return LoadImageW(NULL, + lpFileName, + IMAGE_CURSOR, + 0, + 0, + LR_LOADFROMFILE | LR_DEFAULTSIZE ); +} + +HBITMAP WINAPI LoadBitmapA( + _In_opt_ HINSTANCE hInstance, + _In_ LPCSTR lpBitmapName +) +{ + TRACE("%p, %s\n", hInstance, debugstr_a(lpBitmapName)); + + return LoadImageA(hInstance, + lpBitmapName, + IMAGE_BITMAP, + 0, + 0, + 0); +} + +HBITMAP WINAPI LoadBitmapW( + _In_opt_ HINSTANCE hInstance, + _In_ LPCWSTR lpBitmapName +) +{ + TRACE("%p, %s\n", hInstance, debugstr_w(lpBitmapName)); + + return LoadImageW(hInstance, + lpBitmapName, + IMAGE_BITMAP, + 0, + 0, + 0); +} + +HANDLE WINAPI LoadImageA( + _In_opt_ HINSTANCE hinst, + _In_ LPCSTR lpszName, + _In_ UINT uType, + _In_ int cxDesired, + _In_ int cyDesired, + _In_ UINT fuLoad +) +{ + HANDLE res; + LPWSTR u_name; + DWORD len; + + if (IS_INTRESOURCE(lpszName)) + return LoadImageW(hinst, (LPCWSTR)lpszName, uType, cxDesired, cyDesired, fuLoad); + + len = MultiByteToWideChar( CP_ACP, 0, lpszName, -1, NULL, 0 ); + u_name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, lpszName, -1, u_name, len ); + + res = LoadImageW(hinst, u_name, uType, cxDesired, cyDesired, fuLoad); + HeapFree(GetProcessHeap(), 0, u_name); + return res; +} + +HANDLE WINAPI LoadImageW( + _In_opt_ HINSTANCE hinst, + _In_ LPCWSTR lpszName, + _In_ UINT uType, + _In_ int cxDesired, + _In_ int cyDesired, + _In_ UINT fuLoad +) +{ + /* Redirect to each implementation */ + switch(uType) + { + case IMAGE_BITMAP: + return BITMAP_LoadImageW(hinst, lpszName, cxDesired, cyDesired, fuLoad); + case IMAGE_CURSOR: + case IMAGE_ICON: + return CURSORICON_LoadImageW(hinst, lpszName, cxDesired, cyDesired, fuLoad, uType == IMAGE_ICON); + default: + SetLastError(ERROR_INVALID_PARAMETER); + break; + } + return NULL; +} + +int WINAPI LookupIconIdFromDirectory( + _In_ PBYTE presbits, + _In_ BOOL fIcon +) +{ + UNIMPLEMENTED; + return 0; +} + +int WINAPI LookupIconIdFromDirectoryEx( + _In_ PBYTE presbits, + _In_ BOOL fIcon, + _In_ int cxDesired, + _In_ int cyDesired, + _In_ UINT Flags +) +{ + UNIMPLEMENTED; + return 0; +} + +HICON WINAPI CreateIcon( + _In_opt_ HINSTANCE hInstance, + _In_ int nWidth, + _In_ int nHeight, + _In_ BYTE cPlanes, + _In_ BYTE cBitsPixel, + _In_ const BYTE *lpbANDbits, + _In_ const BYTE *lpbXORbits +) +{ + UNIMPLEMENTED; + return NULL; +} + +HICON WINAPI CreateIconFromResource( + _In_ PBYTE presbits, + _In_ DWORD dwResSize, + _In_ BOOL fIcon, + _In_ DWORD dwVer +) +{ + return CreateIconFromResourceEx( presbits, dwResSize, fIcon, dwVer, 0,0,0); +} + +HICON WINAPI CreateIconFromResourceEx( + _In_ PBYTE pbIconBits, + _In_ DWORD cbIconBits, + _In_ BOOL fIcon, + _In_ DWORD dwVersion, + _In_ int cxDesired, + _In_ int cyDesired, + _In_ UINT uFlags +) +{ + UNIMPLEMENTED; + return NULL; +} + +HICON WINAPI CreateIconIndirect( + _In_ PICONINFO piconinfo +) +{ + UNIMPLEMENTED; + return NULL; +} + +HCURSOR WINAPI CreateCursor( + _In_opt_ HINSTANCE hInst, + _In_ int xHotSpot, + _In_ int yHotSpot, + _In_ int nWidth, + _In_ int nHeight, + _In_ const VOID *pvANDPlane, + _In_ const VOID *pvXORPlane +) +{ + UNIMPLEMENTED; + return NULL; +} + +BOOL WINAPI SetSystemCursor( + _In_ HCURSOR hcur, + _In_ DWORD id +) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI SetCursorPos( + _In_ int X, + _In_ int Y +) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI GetCursorPos( + _Out_ LPPOINT lpPoint +) +{ + UNIMPLEMENTED; + return FALSE; +} + +int WINAPI ShowCursor( + _In_ BOOL bShow +) +{ + UNIMPLEMENTED; + return -1; +} + +HCURSOR WINAPI GetCursor(void) +{ + UNIMPLEMENTED; + return NULL; +} + +BOOL WINAPI DestroyCursor( + _In_ HCURSOR hCursor +) +{ + UNIMPLEMENTED; + return FALSE; +} diff --git a/reactos/win32ss/w32ksvc.h b/reactos/win32ss/w32ksvc.h index ce06f569393..dd80587c696 100644 --- a/reactos/win32ss/w32ksvc.h +++ b/reactos/win32ss/w32ksvc.h @@ -517,7 +517,11 @@ SVC_(UserSetClipboardViewer, 1) SVC_(UserSetConsoleReserveKeys, 2) SVC_(UserSetCursor, 1) SVC_(UserSetCursorContents, 2) +#ifdef NEW_CURSORICON +SVC_(UserSetCursorIconData, 4) +#else SVC_(UserSetCursorIconData, 6) +#endif SVC_(UserSetDbgTag, 2) SVC_(UserSetFocus, 1) SVC_(UserSetImeHotKey, 5) From b7efe0bd86b6655412d6382dbc2b42fd62eb8141 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Mon, 29 Oct 2012 04:47:55 +0000 Subject: [PATCH 09/16] [Win32k] - Move away from thread pointer when using hooks. svn path=/trunk/; revision=57645 --- reactos/win32ss/include/ntuser.h | 1 - reactos/win32ss/user/ntuser/hook.c | 16 +++++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/reactos/win32ss/include/ntuser.h b/reactos/win32ss/include/ntuser.h index b0e1a4e42fb..7c6d5a40f98 100644 --- a/reactos/win32ss/include/ntuser.h +++ b/reactos/win32ss/include/ntuser.h @@ -200,7 +200,6 @@ typedef struct tagHOOK struct _DESKTOP *rpdesk; /* ReactOS */ LIST_ENTRY Chain; /* Hook chain entry */ - struct _ETHREAD* Thread; /* Thread owning the hook */ HOOKPROC Proc; /* Hook function */ BOOLEAN Ansi; /* Is it an Ansi hook? */ UNICODE_STRING ModuleName; /* Module name for global hooks */ diff --git a/reactos/win32ss/user/ntuser/hook.c b/reactos/win32ss/user/ntuser/hook.c index 31ebcbd486a..2c436918d68 100644 --- a/reactos/win32ss/user/ntuser/hook.c +++ b/reactos/win32ss/user/ntuser/hook.c @@ -250,8 +250,8 @@ co_IntCallLowLevelHook(PHOOK Hook, BOOL Block = FALSE; ULONG_PTR uResult = 0; - if (Hook->Thread) - pti = Hook->Thread->Tcb.Win32Thread; + if (Hook->ptiHooked) + pti = Hook->ptiHooked; else pti = Hook->head.pti; @@ -990,9 +990,9 @@ IntGetNextHook(PHOOK Hook) PLIST_ENTRY pLastHead, pElem; PTHREADINFO pti; - if (Hook->Thread) + if (Hook->ptiHooked) { - pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread); + pti = Hook->ptiHooked; pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; } else @@ -1035,9 +1035,9 @@ IntRemoveHook(PHOOK Hook) HookId = Hook->HookId; - if (Hook->Thread) // Local + if (Hook->ptiHooked) // Local { - pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread); + pti = Hook->ptiHooked; IntFreeHook( Hook); @@ -1496,8 +1496,6 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, ptiHook = Thread->Tcb.Win32Thread; - ObDereferenceObject(Thread); - if ( ptiHook->rpdesk != pti->rpdesk) // gptiCurrent->rpdesk) { ERR("Local hook wrong desktop HookId: %d\n",HookId); @@ -1577,7 +1575,6 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, } Hook->ihmod = (INT)Mod; // Module Index from atom table, Do this for now. - Hook->Thread = Thread; /* Set Thread, Null is Global. */ Hook->HookId = HookId; Hook->rpdesk = ptiHook->rpdesk; Hook->phkNext = NULL; /* Dont use as a chain! Use link lists for chaining. */ @@ -1684,6 +1681,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, CLEANUP: TRACE("Leave NtUserSetWindowsHookEx, ret=%i\n",_ret_); + if (Thread) ObDereferenceObject(Thread); UserLeave(); END_CLEANUP; } From 9aec2fb369344082333f58f9adb977c18994f19f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Mon, 29 Oct 2012 15:50:20 +0000 Subject: [PATCH 10/16] [WIN32K] - put changes for the new cursor/icons implementation in a separate file svn path=/trunk/; revision=57646 --- reactos/win32ss/CMakeLists.txt | 12 +- reactos/win32ss/user/ntuser/cursoricon.c | 366 ++-- reactos/win32ss/user/ntuser/cursoricon.h | 21 +- reactos/win32ss/user/ntuser/cursoricon_new.c | 1578 ++++++++++++++++++ reactos/win32ss/user/ntuser/msgqueue.c | 20 + 5 files changed, 1769 insertions(+), 228 deletions(-) create mode 100644 reactos/win32ss/user/ntuser/cursoricon_new.c diff --git a/reactos/win32ss/CMakeLists.txt b/reactos/win32ss/CMakeLists.txt index 010e38886c4..10704c1b9fe 100644 --- a/reactos/win32ss/CMakeLists.txt +++ b/reactos/win32ss/CMakeLists.txt @@ -11,10 +11,6 @@ if(USE_DIBLIB) add_subdirectory(gdi/diblib) endif() -if(USE_NEW_CURSORICON) - add_definitions(-DNEW_CURSORICON) -endif() - add_subdirectory(gdi/gdi32) add_subdirectory(reactx) add_subdirectory(user/user32) @@ -107,7 +103,6 @@ list(APPEND SOURCE user/ntuser/class.c user/ntuser/clipboard.c user/ntuser/csr.c - user/ntuser/cursoricon.c user/ntuser/defwnd.c user/ntuser/desktop.c user/ntuser/display.c @@ -194,6 +189,13 @@ else() ${GENDIB_FILES}) endif() +if(USE_NEW_CURSORICON) + add_definitions(-DNEW_CURSORICON) + list(APPEND SOURCE user/ntuser/cursoricon_new.c) +else() + list(APPEND SOURCE user/ntuser/cursoricon.c) +endif() + if(ARCH STREQUAL "i386") list(APPEND SOURCE gdi/dib/i386/dib24bpp_hline.s diff --git a/reactos/win32ss/user/ntuser/cursoricon.c b/reactos/win32ss/user/ntuser/cursoricon.c index 0c772a2155d..7ba56db0700 100644 --- a/reactos/win32ss/user/ntuser/cursoricon.c +++ b/reactos/win32ss/user/ntuser/cursoricon.c @@ -237,7 +237,7 @@ BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi) { PSYSTEM_CURSORINFO CurInfo; - HBITMAP bmpMask, bmpColor, bmpAlpha; + HBITMAP bmpMask, bmpColor; BOOLEAN Ret, bListEmpty, bFound = FALSE; PCURICON_PROCESS Current = NULL; @@ -291,28 +291,21 @@ emptyList: UserSetCursor(NULL, TRUE); } - bmpMask = CurIcon->aFrame[0].hbmMask; - bmpColor = CurIcon->aFrame[0].hbmColor; - bmpAlpha = CurIcon->aFrame[0].hbmAlpha; + bmpMask = CurIcon->IconInfo.hbmMask; + bmpColor = CurIcon->IconInfo.hbmColor; /* Delete bitmaps */ if (bmpMask) { GreSetObjectOwner(bmpMask, GDI_OBJ_HMGR_POWNED); GreDeleteObject(bmpMask); - CurIcon->aFrame[0].hbmMask = NULL; + CurIcon->IconInfo.hbmMask = NULL; } if (bmpColor) { GreSetObjectOwner(bmpColor, GDI_OBJ_HMGR_POWNED); GreDeleteObject(bmpColor); - CurIcon->aFrame[0].hbmColor = NULL; - } - if (bmpAlpha) - { - GreSetObjectOwner(bmpAlpha, GDI_OBJ_HMGR_POWNED); - GreDeleteObject(bmpAlpha); - CurIcon->aFrame[0].hbmAlpha = NULL; + CurIcon->IconInfo.hbmColor = NULL; } /* We were given a pointer, no need to keep the reference anylonger! */ @@ -368,21 +361,18 @@ NtUserGetIconInfo( { goto leave; } - - /* Fill data */ - ii.fIcon = CurIcon->bIcon; - ii.xHotspot = CurIcon->ptlHotspot.x; - ii.yHotspot = CurIcon->ptlHotspot.y; + + RtlCopyMemory(&ii, &CurIcon->IconInfo, sizeof(ICONINFO)); /* Copy bitmaps */ - ii.hbmMask = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmMask); - ii.hbmColor = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmColor); + ii.hbmMask = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmMask); + ii.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor); if (pbpp) { PSURFACE psurfBmp; - psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor); + psurfBmp = SURFACE_ShareLockSurface(CurIcon->IconInfo.hbmColor); if (psurfBmp) { colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat); @@ -809,103 +799,35 @@ NtUserSetCursorContents( goto done; } -#if 0 - /* Check if we get valid information */ - if(IconInfo.fIcon != CurInfo->bIcon) - { - EngSetLastError(ERROR_INVALID_PARAMETER); - goto done; - } -#endif - /* Delete old bitmaps */ - if (CurIcon->aFrame[0].hbmColor) - GreDeleteObject(CurIcon->aFrame[0].hbmColor); - if (CurIcon->aFrame[0].hbmMask) - GreDeleteObject(CurIcon->aFrame[0].hbmMask); - if(CurIcon->aFrame[0].hbmAlpha) - GreDeleteObject(CurIcon->aFrame[0].hbmAlpha); - - /* Set fields */ - CurIcon->bIcon = IconInfo.fIcon; - CurIcon->ptlHotspot.x = IconInfo.xHotspot; - CurIcon->ptlHotspot.y = IconInfo.yHotspot; - CurIcon->aFrame[0].hbmMask = IconInfo.hbmMask; - CurIcon->aFrame[0].hbmColor = IconInfo.hbmColor; - CurIcon->aFrame[0].hbmAlpha = NULL; - - if (IconInfo.hbmColor) + if ((CurIcon->IconInfo.hbmColor) + && (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor)) { - BOOLEAN bAlpha = FALSE; - psurfBmp = SURFACE_ShareLockSurface(IconInfo.hbmColor); + GreDeleteObject(CurIcon->IconInfo.hbmColor); + } + if ((CurIcon->IconInfo.hbmMask) + && CurIcon->IconInfo.hbmMask != IconInfo.hbmMask) + { + GreDeleteObject(CurIcon->IconInfo.hbmMask); + } + + /* Copy new IconInfo field */ + CurIcon->IconInfo = IconInfo; + + if (CurIcon->IconInfo.hbmColor) + { + psurfBmp = SURFACE_ShareLockSurface(CurIcon->IconInfo.hbmColor); if (!psurfBmp) goto done; + CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; - - /* 32bpp bitmap is likely to have an alpha channel */ - if(psurfBmp->SurfObj.iBitmapFormat == BMF_32BPP) - { - PFN_DIB_GetPixel fn_GetPixel = DibFunctionsForBitmapFormat[BMF_32BPP].DIB_GetPixel; - INT i, j; - - fn_GetPixel = DibFunctionsForBitmapFormat[BMF_32BPP].DIB_GetPixel; - for (i = 0; i < psurfBmp->SurfObj.sizlBitmap.cx; i++) - { - for (j = 0; j < psurfBmp->SurfObj.sizlBitmap.cy; j++) - { - bAlpha = ((BYTE)(fn_GetPixel(&psurfBmp->SurfObj, i, j) >> 24)) != 0; - if (bAlpha) - break; - } - if (bAlpha) - break; - } - } - /* We're done with this one */ SURFACE_ShareUnlockSurface(psurfBmp); - GreSetObjectOwner(IconInfo.hbmColor, GDI_OBJ_HMGR_PUBLIC); - - if(bAlpha) - { - UCHAR Alpha; - PUCHAR ptr; - INT i, j; - /* Copy the bitmap */ - CurIcon->aFrame[0].hbmAlpha = BITMAP_CopyBitmap(IconInfo.hbmColor); - if(!CurIcon->aFrame[0].hbmAlpha) - { - ERR("BITMAP_CopyBitmap failed!"); - goto done; - } - - psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmAlpha); - if(!psurfBmp) - { - ERR("SURFACE_LockSurface failed!\n"); - goto done; - } - - /* Premultiply with the alpha channel value */ - for (i = 0; i < psurfBmp->SurfObj.sizlBitmap.cy; i++) - { - ptr = (PBYTE)psurfBmp->SurfObj.pvScan0 + i*psurfBmp->SurfObj.lDelta; - for (j = 0; j < psurfBmp->SurfObj.sizlBitmap.cx; j++) - { - Alpha = ptr[3]; - ptr[0] = (ptr[0] * Alpha) / 0xff; - ptr[1] = (ptr[1] * Alpha) / 0xff; - ptr[2] = (ptr[2] * Alpha) / 0xff; - ptr += 4; - } - } - SURFACE_ShareUnlockSurface(psurfBmp); - GreSetObjectOwner(CurIcon->aFrame[0].hbmAlpha, GDI_OBJ_HMGR_PUBLIC); - } + GreSetObjectOwner(CurIcon->IconInfo.hbmColor, GDI_OBJ_HMGR_PUBLIC); } else { - psurfBmp = SURFACE_ShareLockSurface(IconInfo.hbmMask); + psurfBmp = SURFACE_ShareLockSurface(CurIcon->IconInfo.hbmMask); if (!psurfBmp) goto done; @@ -914,18 +836,12 @@ NtUserSetCursorContents( SURFACE_ShareUnlockSurface(psurfBmp); } - GreSetObjectOwner(IconInfo.hbmMask, GDI_OBJ_HMGR_PUBLIC); + GreSetObjectOwner(CurIcon->IconInfo.hbmMask, GDI_OBJ_HMGR_PUBLIC); Ret = TRUE; done: - if(!Ret) - { - IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process()); - CurIcon = NULL; - } - if (CurIcon) { UserDereferenceObject(CurIcon); @@ -942,21 +858,20 @@ CLEANUP: /* * @implemented */ -#ifdef NEW_CURSORICON +#if 0 BOOL APIENTRY NtUserSetCursorIconData( - _In_ HCURSOR Handle, - _In_ HINSTANCE hinst, - _In_ HRSRC hrsrc, - _In_ PICONINFO pIconInfo) + HANDLE Handle, + HMODULE hModule, + PUNICODE_STRING pstrResName, + PICONINFO pIconInfo) { PCURICON_OBJECT CurIcon; PSURFACE psurfBmp; NTSTATUS Status = STATUS_SUCCESS; BOOL Ret = FALSE; DECLARE_RETURN(BOOL); - ICONINFO ii; TRACE("Enter NtUserSetCursorIconData\n"); UserEnterExclusive(); @@ -966,96 +881,54 @@ NtUserSetCursorIconData( RETURN(FALSE); } - CurIcon->hModule = hinst; - CurIcon->hRsrc =hrsrc; + CurIcon->hModule = hModule; + CurIcon->hRsrc = NULL; //hRsrc; + CurIcon->hGroupRsrc = NULL; //hGroupRsrc; _SEH2_TRY { ProbeForRead(pIconInfo, sizeof(ICONINFO), 1); - ii = *pIconInfo; + RtlCopyMemory(&CurIcon->IconInfo, pIconInfo, sizeof(ICONINFO)); + + CurIcon->IconInfo.hbmMask = BITMAP_CopyBitmap(pIconInfo->hbmMask); + CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(pIconInfo->hbmColor); + + if (CurIcon->IconInfo.hbmColor) + { + if ((psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor))) + { + CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; + CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; + SURFACE_UnlockSurface(psurfBmp); + GreSetObjectOwner(CurIcon->IconInfo.hbmMask, GDI_OBJ_HMGR_PUBLIC); + } + } + if (CurIcon->IconInfo.hbmMask) + { + if (CurIcon->IconInfo.hbmColor == NULL) + { + if ((psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask))) + { + CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; + CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; + SURFACE_UnlockSurface(psurfBmp); + } + } + GreSetObjectOwner(CurIcon->IconInfo.hbmMask, GDI_OBJ_HMGR_PUBLIC); + } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END - + if (!NT_SUCCESS(Status)) - { SetLastNtError(Status); - goto done; - } - - /* This is probably not what windows does, but consistency checks can't hurt */ - if(CurIcon->bIcon != ii.fIcon) - { - EngSetLastError(ERROR_INVALID_PARAMETER); - goto done; - } - CurIcon->ptlHotspot.x = ii.xHotspot; - CurIcon->ptlHotspot.y = ii.yHotspot; - - if(!ii.hbmMask) - { - EngSetLastError(ERROR_INVALID_PARAMETER); - goto done; - } - - CurIcon->aFrame[0].hbmMask = BITMAP_CopyBitmap(ii.hbmMask); - if(!CurIcon->aFrame[0].hbmMask) - goto done; - - if(ii.hbmColor) - { - CurIcon->aFrame[0].hbmColor = BITMAP_CopyBitmap(ii.hbmColor); - if(!CurIcon->aFrame[0].hbmColor) - goto done; - } - - if (CurIcon->aFrame[0].hbmColor) - { - if ((psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor))) - { - CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; - CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; - SURFACE_ShareUnlockSurface(psurfBmp); - GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); - } - else - goto done; - } else - { - if ((psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmMask))) - { - CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; - CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy/2; - SURFACE_ShareUnlockSurface(psurfBmp); - } - else - goto done; - } - GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); - - Ret = TRUE; + Ret = TRUE; -done: UserDereferenceObject(CurIcon); - if(!Ret) - { - if (CurIcon->aFrame[0].hbmMask) - { - GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_POWNED); - GreDeleteObject(CurIcon->aFrame[0].hbmMask); - CurIcon->aFrame[0].hbmMask = NULL; - } - if (CurIcon->aFrame[0].hbmColor) - { - GreSetObjectOwner(CurIcon->aFrame[0].hbmColor, GDI_OBJ_HMGR_POWNED); - GreDeleteObject(CurIcon->aFrame[0].hbmColor); - CurIcon->aFrame[0].hbmColor = NULL; - } - } RETURN(Ret); CLEANUP: @@ -1076,6 +949,7 @@ NtUserSetCursorIconData( { PCURICON_OBJECT CurIcon; NTSTATUS Status; + POINT SafeHotspot; BOOL Ret = FALSE; DECLARE_RETURN(BOOL); @@ -1094,7 +968,7 @@ NtUserSetCursorIconData( /* Copy fields */ if (fIcon) { - Status = MmCopyFromCaller(&CurIcon->bIcon, fIcon, sizeof(BOOL)); + Status = MmCopyFromCaller(&CurIcon->IconInfo.fIcon, fIcon, sizeof(BOOL)); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); @@ -1109,12 +983,16 @@ NtUserSetCursorIconData( if (Hotspot) { - Status = MmCopyFromCaller(&CurIcon->ptlHotspot, Hotspot, sizeof(POINT)); - if (!NT_SUCCESS(Status)) + Status = MmCopyFromCaller(&SafeHotspot, Hotspot, sizeof(POINT)); + if (NT_SUCCESS(Status)) { - SetLastNtError(Status); - goto done; + CurIcon->IconInfo.xHotspot = SafeHotspot.x; + CurIcon->IconInfo.yHotspot = SafeHotspot.y; + + Ret = TRUE; } + else + SetLastNtError(Status); } if (!fIcon && !Hotspot) @@ -1126,14 +1004,10 @@ done: if(Ret) { /* This icon is shared now */ - GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); - if(CurIcon->aFrame[0].hbmColor) + GreSetObjectOwner(CurIcon->IconInfo.hbmMask, GDI_OBJ_HMGR_PUBLIC); + if(CurIcon->IconInfo.hbmColor) { - GreSetObjectOwner(CurIcon->aFrame[0].hbmColor, GDI_OBJ_HMGR_PUBLIC); - } - if(CurIcon->aFrame[0].hbmAlpha) - { - GreSetObjectOwner(CurIcon->aFrame[0].hbmAlpha, GDI_OBJ_HMGR_PUBLIC); + GreSetObjectOwner(CurIcon->IconInfo.hbmColor, GDI_OBJ_HMGR_PUBLIC); } } UserDereferenceObject(CurIcon); @@ -1170,8 +1044,8 @@ UserDrawIconEx( PSURFACE psurfDest, psurfMask, psurfColor, psurfOffScreen; PDC pdc = NULL; BOOL Ret = FALSE; - HBITMAP hbmMask, hbmColor, hbmAlpha; - BOOL bOffScreen; + HBITMAP hbmMask, hbmColor; + BOOL bOffScreen, bAlpha = FALSE; RECTL rcDest, rcSrc; CLIPOBJ* pdcClipObj = NULL; EXLATEOBJ exlo; @@ -1183,9 +1057,8 @@ UserDrawIconEx( return FALSE; } - hbmMask = pIcon->aFrame[0].hbmMask; - hbmColor = pIcon->aFrame[0].hbmColor; - hbmAlpha = pIcon->aFrame[0].hbmAlpha; + hbmMask = pIcon->IconInfo.hbmMask; + hbmColor = pIcon->IconInfo.hbmColor; if (istepIfAniCur) ERR("NtUserDrawIconEx: istepIfAniCur is not supported!\n"); @@ -1218,11 +1091,35 @@ UserDrawIconEx( /* Set source rect */ RECTL_vSetRect(&rcSrc, 0, 0, pIcon->Size.cx, pIcon->Size.cy); + /* Check for alpha */ + if (psurfColor && + (psurfColor->SurfObj.iBitmapFormat == BMF_32BPP) && + (diFlags & DI_IMAGE)) + { + PFN_DIB_GetPixel fnSource_GetPixel = NULL; + INT i, j; + + /* In order to correctly display 32 bit icons Windows first scans the image, + because information about transparency is not stored in any image's headers */ + fnSource_GetPixel = DibFunctionsForBitmapFormat[BMF_32BPP].DIB_GetPixel; + for (i = 0; i < psurfColor->SurfObj.sizlBitmap.cx; i++) + { + for (j = 0; j < psurfColor->SurfObj.sizlBitmap.cy; j++) + { + bAlpha = ((BYTE)(fnSource_GetPixel(&psurfColor->SurfObj, i, j) >> 24) & 0xff); + if (bAlpha) + break; + } + if (bAlpha) + break; + } + } + /* Fix width parameter, if needed */ if (!cxWidth) { if(diFlags & DI_DEFAULTSIZE) - cxWidth = pIcon->bIcon ? + cxWidth = pIcon->IconInfo.fIcon ? UserGetSystemMetrics(SM_CXICON) : UserGetSystemMetrics(SM_CXCURSOR); else cxWidth = pIcon->Size.cx; @@ -1232,7 +1129,7 @@ UserDrawIconEx( if (!cyHeight) { if(diFlags & DI_DEFAULTSIZE) - cyHeight = pIcon->bIcon ? + cyHeight = pIcon->IconInfo.fIcon ? UserGetSystemMetrics(SM_CYICON) : UserGetSystemMetrics(SM_CYCURSOR); else cyHeight = pIcon->Size.cy; @@ -1341,16 +1238,42 @@ UserDrawIconEx( } /* Now do the rendering */ - if(hbmAlpha && (diFlags & DI_IMAGE)) + if(bAlpha && (diFlags & DI_IMAGE)) { BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } }; + BYTE Alpha; + INT i, j; PSURFACE psurf = NULL; + PBYTE ptr ; + HBITMAP hsurfCopy = NULL; - psurf = SURFACE_ShareLockSurface(hbmAlpha); + hsurfCopy = BITMAP_CopyBitmap(hbmColor); + if(!hsurfCopy) + { + ERR("BITMAP_CopyBitmap failed!"); + goto CleanupAlpha; + } + + psurf = SURFACE_ShareLockSurface(hsurfCopy); if(!psurf) { ERR("SURFACE_LockSurface failed!\n"); - goto NoAlpha; + goto CleanupAlpha; + } + + /* Premultiply with the alpha channel value */ + for (i = 0; i < psurf->SurfObj.sizlBitmap.cy; i++) + { + ptr = (PBYTE)psurf->SurfObj.pvScan0 + i*psurf->SurfObj.lDelta; + for (j = 0; j < psurf->SurfObj.sizlBitmap.cx; j++) + { + Alpha = ptr[3]; + ptr[0] = (ptr[0] * Alpha) / 0xff; + ptr[1] = (ptr[1] * Alpha) / 0xff; + ptr[2] = (ptr[2] * Alpha) / 0xff; + + ptr += 4; + } } /* Initialize color translation object */ @@ -1366,11 +1289,14 @@ UserDrawIconEx( &blendobj); EXLATEOBJ_vCleanup(&exlo); - SURFACE_ShareUnlockSurface(psurf); - if(Ret) goto done; + + CleanupAlpha: + if(psurf) SURFACE_ShareUnlockSurface(psurf); + if(hsurfCopy) NtGdiDeleteObjectApp(hsurfCopy); + if(Ret) goto done; ERR("NtGdiAlphaBlend failed!\n"); } -NoAlpha: + if (diFlags & DI_MASK) { DWORD rop4 = (diFlags & DI_IMAGE) ? ROP4_SRCAND : ROP4_SRCCOPY; diff --git a/reactos/win32ss/user/ntuser/cursoricon.h b/reactos/win32ss/user/ntuser/cursoricon.h index 722daebe820..3bf5e19c4be 100644 --- a/reactos/win32ss/user/ntuser/cursoricon.h +++ b/reactos/win32ss/user/ntuser/cursoricon.h @@ -8,6 +8,7 @@ typedef struct tagCURICON_PROCESS PPROCESSINFO Process; } CURICON_PROCESS, *PCURICON_PROCESS; +#ifdef NEW_CURSORICON typedef struct _CURICON_FRAME { HBITMAP hbmMask; @@ -23,9 +24,6 @@ typedef struct _CURICON_OBJECT LIST_ENTRY ProcessList; HMODULE hModule; HRSRC hRsrc; -#ifndef NEW_CURSORICON - HRSRC hGroupRsrc; -#endif SIZE Size; BYTE Shadow; BOOL bIcon; @@ -33,6 +31,23 @@ typedef struct _CURICON_OBJECT CURICON_FRAME aFrame[1]; } CURICON_OBJECT, *PCURICON_OBJECT; +#else + +typedef struct _CURICON_OBJECT +{ + PROCMARKHEAD head; + LIST_ENTRY ListEntry; + HANDLE Self; + LIST_ENTRY ProcessList; + HMODULE hModule; + HRSRC hRsrc; + HRSRC hGroupRsrc; + SIZE Size; + BYTE Shadow; + ICONINFO IconInfo; +} CURICON_OBJECT, *PCURICON_OBJECT; +#endif + typedef struct _CURSORACCELERATION_INFO { UINT FirstThreshold; diff --git a/reactos/win32ss/user/ntuser/cursoricon_new.c b/reactos/win32ss/user/ntuser/cursoricon_new.c new file mode 100644 index 00000000000..0c772a2155d --- /dev/null +++ b/reactos/win32ss/user/ntuser/cursoricon_new.c @@ -0,0 +1,1578 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Win32k subsystem + * PURPOSE: Cursor and icon functions + * FILE: subsystems/win32/win32k/ntuser/cursoricon.c + * PROGRAMER: ReactOS Team + */ +/* + * We handle two types of cursors/icons: + * - Private + * Loaded without LR_SHARED flag + * Private to a process + * Can be deleted by calling NtDestroyCursorIcon() + * CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc set to NULL + * - Shared + * Loaded with LR_SHARED flag + * Possibly shared by multiple processes + * Immune to NtDestroyCursorIcon() + * CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc are valid + * There's a M:N relationship between processes and (shared) cursor/icons. + * A process can have multiple cursor/icons and a cursor/icon can be used + * by multiple processes. To keep track of this we keep a list of all + * cursor/icons (CurIconList) and per cursor/icon we keep a list of + * CURICON_PROCESS structs starting at CurIcon->ProcessList. + */ + +#include +DBG_DEFAULT_CHANNEL(UserIcon); + +static PPAGED_LOOKASIDE_LIST pgProcessLookasideList; +static LIST_ENTRY gCurIconList; + +SYSTEM_CURSORINFO gSysCursorInfo; + +BOOL +InitCursorImpl() +{ + pgProcessLookasideList = ExAllocatePool(NonPagedPool, sizeof(PAGED_LOOKASIDE_LIST)); + if(!pgProcessLookasideList) + return FALSE; + + ExInitializePagedLookasideList(pgProcessLookasideList, + NULL, + NULL, + 0, + sizeof(CURICON_PROCESS), + TAG_DIB, + 128); + InitializeListHead(&gCurIconList); + + gSysCursorInfo.Enabled = FALSE; + gSysCursorInfo.ButtonsDown = 0; + gSysCursorInfo.bClipped = FALSE; + gSysCursorInfo.LastBtnDown = 0; + gSysCursorInfo.CurrentCursorObject = NULL; + gSysCursorInfo.ShowingCursor = -1; + gSysCursorInfo.ClickLockActive = FALSE; + gSysCursorInfo.ClickLockTime = 0; + + return TRUE; +} + +PSYSTEM_CURSORINFO +IntGetSysCursorInfo() +{ + return &gSysCursorInfo; +} + +/* This function creates a reference for the object! */ +PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon) +{ + PCURICON_OBJECT CurIcon; + + if (!hCurIcon) + { + EngSetLastError(ERROR_INVALID_CURSOR_HANDLE); + return NULL; + } + + CurIcon = (PCURICON_OBJECT)UserReferenceObjectByHandle(hCurIcon, otCursorIcon); + if (!CurIcon) + { + /* We never set ERROR_INVALID_ICON_HANDLE. lets hope noone ever checks for it */ + EngSetLastError(ERROR_INVALID_CURSOR_HANDLE); + return NULL; + } + + ASSERT(CurIcon->head.cLockObj >= 1); + return CurIcon; +} + +BOOL UserSetCursorPos( INT x, INT y, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook) +{ + PWND DesktopWindow; + PSYSTEM_CURSORINFO CurInfo; + MSG Msg; + RECTL rcClip; + POINT pt; + + if(!(DesktopWindow = UserGetDesktopWindow())) + { + return FALSE; + } + + CurInfo = IntGetSysCursorInfo(); + + /* Clip cursor position */ + if (!CurInfo->bClipped) + rcClip = DesktopWindow->rcClient; + else + rcClip = CurInfo->rcClip; + + if(x >= rcClip.right) x = rcClip.right - 1; + if(x < rcClip.left) x = rcClip.left; + if(y >= rcClip.bottom) y = rcClip.bottom - 1; + if(y < rcClip.top) y = rcClip.top; + + pt.x = x; + pt.y = y; + + /* 1. Generate a mouse move message, this sets the htEx and Track Window too. */ + Msg.message = WM_MOUSEMOVE; + Msg.wParam = UserGetMouseButtonsState(); + Msg.lParam = MAKELPARAM(x, y); + Msg.pt = pt; + co_MsqInsertMouseMessage(&Msg, flags, dwExtraInfo, Hook); + + /* 2. Store the new cursor position */ + gpsi->ptCursor = pt; + + return TRUE; +} + +/* + * We have to register that this object is in use by the current + * process. The only way to do that seems to be to walk the list + * of cursor/icon objects starting at W32Process->CursorIconListHead. + * If the object is already present in the list, we don't have to do + * anything, if it's not present we add it and inc the ProcessCount + * in the object. Having to walk the list kind of sucks, but that's + * life... + */ +static BOOLEAN FASTCALL +ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon) +{ + PPROCESSINFO Win32Process; + PCURICON_PROCESS Current; + + Win32Process = PsGetCurrentProcessWin32Process(); + + LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry) + { + if (Current->Process == Win32Process) + { + /* Already registered for this process */ + return TRUE; + } + } + + /* Not registered yet */ + Current = ExAllocateFromPagedLookasideList(pgProcessLookasideList); + if (NULL == Current) + { + return FALSE; + } + InsertHeadList(&CurIcon->ProcessList, &Current->ListEntry); + Current->Process = Win32Process; + + return TRUE; +} + +PCURICON_OBJECT FASTCALL +IntFindExistingCurIconObject(HMODULE hModule, + HRSRC hRsrc, LONG cx, LONG cy) +{ + PCURICON_OBJECT CurIcon; + + LIST_FOR_EACH(CurIcon, &gCurIconList, CURICON_OBJECT, ListEntry) + { + + // if (NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) // <- huh???? +// UserReferenceObject( CurIcon); +// { + if ((CurIcon->hModule == hModule) && (CurIcon->hRsrc == hRsrc)) + { + if (cx && ((cx != CurIcon->Size.cx) || (cy != CurIcon->Size.cy))) + { +// UserDereferenceObject(CurIcon); + continue; + } + if (! ReferenceCurIconByProcess(CurIcon)) + { + return NULL; + } + + return CurIcon; + } +// } +// UserDereferenceObject(CurIcon); + + } + + return NULL; +} + +PCURICON_OBJECT +IntCreateCurIconHandle() +{ + PCURICON_OBJECT CurIcon; + HANDLE hCurIcon; + + CurIcon = UserCreateObject(gHandleTable, NULL, NULL, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT)); + + if (!CurIcon) + { + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + CurIcon->Self = hCurIcon; + InitializeListHead(&CurIcon->ProcessList); + + if (! ReferenceCurIconByProcess(CurIcon)) + { + ERR("Failed to add process\n"); + UserDeleteObject(hCurIcon, otCursorIcon); + UserDereferenceObject(CurIcon); + return NULL; + } + + InsertHeadList(&gCurIconList, &CurIcon->ListEntry); + + return CurIcon; +} + +BOOLEAN FASTCALL +IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi) +{ + PSYSTEM_CURSORINFO CurInfo; + HBITMAP bmpMask, bmpColor, bmpAlpha; + BOOLEAN Ret, bListEmpty, bFound = FALSE; + PCURICON_PROCESS Current = NULL; + + /* For handles created without any data (error handling) */ + if(IsListEmpty(&CurIcon->ProcessList)) + goto emptyList; + + /* Now find this process in the list of processes referencing this object and + remove it from that list */ + LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry) + { + if (Current->Process == ppi) + { + bFound = TRUE; + bListEmpty = RemoveEntryList(&Current->ListEntry); + break; + } + } + + if(!bFound) + { + /* This object doesn't belong to this process */ + EngSetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + ExFreeToPagedLookasideList(pgProcessLookasideList, Current); + + /* If there are still processes referencing this object we can't destroy it yet */ + if (!bListEmpty) + { + if(CurIcon->head.ppi == ppi) + { + /* Set the first process of the list as owner */ + Current = CONTAINING_RECORD(CurIcon->ProcessList.Flink, CURICON_PROCESS, ListEntry); + UserSetObjectOwner(CurIcon, otCursorIcon, Current->Process); + } + UserDereferenceObject(CurIcon); + return TRUE; + } + +emptyList: + /* Remove it from the list */ + RemoveEntryList(&CurIcon->ListEntry); + + CurInfo = IntGetSysCursorInfo(); + + if (CurInfo->CurrentCursorObject == CurIcon) + { + /* Hide the cursor if we're destroying the current cursor */ + UserSetCursor(NULL, TRUE); + } + + bmpMask = CurIcon->aFrame[0].hbmMask; + bmpColor = CurIcon->aFrame[0].hbmColor; + bmpAlpha = CurIcon->aFrame[0].hbmAlpha; + + /* Delete bitmaps */ + if (bmpMask) + { + GreSetObjectOwner(bmpMask, GDI_OBJ_HMGR_POWNED); + GreDeleteObject(bmpMask); + CurIcon->aFrame[0].hbmMask = NULL; + } + if (bmpColor) + { + GreSetObjectOwner(bmpColor, GDI_OBJ_HMGR_POWNED); + GreDeleteObject(bmpColor); + CurIcon->aFrame[0].hbmColor = NULL; + } + if (bmpAlpha) + { + GreSetObjectOwner(bmpAlpha, GDI_OBJ_HMGR_POWNED); + GreDeleteObject(bmpAlpha); + CurIcon->aFrame[0].hbmAlpha = NULL; + } + + /* We were given a pointer, no need to keep the reference anylonger! */ + UserDereferenceObject(CurIcon); + Ret = UserDeleteObject(CurIcon->Self, otCursorIcon); + + return Ret; +} + +VOID FASTCALL +IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process) +{ + PCURICON_OBJECT CurIcon, tmp; + + /* Run through the list of icon objects */ + LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry) + { + UserReferenceObject(CurIcon); + IntDestroyCurIconObject(CurIcon, Win32Process); + } +} + + +/* + * @implemented + */ +BOOL +APIENTRY +NtUserGetIconInfo( + HANDLE hCurIcon, + PICONINFO IconInfo, + PUNICODE_STRING lpInstName, // Optional + PUNICODE_STRING lpResName, // Optional + LPDWORD pbpp, // Optional + BOOL bInternal) +{ + ICONINFO ii; + PCURICON_OBJECT CurIcon; + NTSTATUS Status = STATUS_SUCCESS; + BOOL Ret = FALSE; + DWORD colorBpp = 0; + + TRACE("Enter NtUserGetIconInfo\n"); + UserEnterExclusive(); + + if (!IconInfo) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + goto leave; + } + + if (!(CurIcon = UserGetCurIconObject(hCurIcon))) + { + goto leave; + } + + /* Fill data */ + ii.fIcon = CurIcon->bIcon; + ii.xHotspot = CurIcon->ptlHotspot.x; + ii.yHotspot = CurIcon->ptlHotspot.y; + + /* Copy bitmaps */ + ii.hbmMask = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmMask); + ii.hbmColor = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmColor); + + if (pbpp) + { + PSURFACE psurfBmp; + + psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor); + if (psurfBmp) + { + colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat); + SURFACE_ShareUnlockSurface(psurfBmp); + } + } + + /* Copy fields */ + _SEH2_TRY + { + ProbeForWrite(IconInfo, sizeof(ICONINFO), 1); + RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO)); + + if (pbpp) + { + ProbeForWrite(pbpp, sizeof(DWORD), 1); + *pbpp = colorBpp; + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END + + if (NT_SUCCESS(Status)) + Ret = TRUE; + else + SetLastNtError(Status); + + UserDereferenceObject(CurIcon); + +leave: + TRACE("Leave NtUserGetIconInfo, ret=%i\n", Ret); + UserLeave(); + + return Ret; +} + + +/* + * @implemented + */ +BOOL +APIENTRY +NtUserGetIconSize( + HANDLE hCurIcon, + UINT istepIfAniCur, + PLONG plcx, // &size.cx + PLONG plcy) // &size.cy +{ + PCURICON_OBJECT CurIcon; + NTSTATUS Status = STATUS_SUCCESS; + BOOL bRet = FALSE; + + TRACE("Enter NtUserGetIconSize\n"); + UserEnterExclusive(); + + if (!(CurIcon = UserGetCurIconObject(hCurIcon))) + { + goto cleanup; + } + + _SEH2_TRY + { + ProbeForWrite(plcx, sizeof(LONG), 1); + RtlCopyMemory(plcx, &CurIcon->Size.cx, sizeof(LONG)); + ProbeForWrite(plcy, sizeof(LONG), 1); + RtlCopyMemory(plcy, &CurIcon->Size.cy, sizeof(LONG)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END + + if (NT_SUCCESS(Status)) + bRet = TRUE; + else + SetLastNtError(Status); // Maybe not, test this + + UserDereferenceObject(CurIcon); + +cleanup: + TRACE("Leave NtUserGetIconSize, ret=%i\n", bRet); + UserLeave(); + return bRet; +} + + +/* + * @implemented + */ +BOOL +APIENTRY +NtUserGetCursorInfo( + PCURSORINFO pci) +{ + CURSORINFO SafeCi; + PSYSTEM_CURSORINFO CurInfo; + NTSTATUS Status = STATUS_SUCCESS; + PCURICON_OBJECT CurIcon; + BOOL Ret = FALSE; + DECLARE_RETURN(BOOL); + + TRACE("Enter NtUserGetCursorInfo\n"); + UserEnterExclusive(); + + CurInfo = IntGetSysCursorInfo(); + CurIcon = (PCURICON_OBJECT)CurInfo->CurrentCursorObject; + + SafeCi.cbSize = sizeof(CURSORINFO); + SafeCi.flags = ((CurIcon && CurInfo->ShowingCursor >= 0) ? CURSOR_SHOWING : 0); + SafeCi.hCursor = (CurIcon ? (HCURSOR)CurIcon->Self : (HCURSOR)0); + + SafeCi.ptScreenPos = gpsi->ptCursor; + + _SEH2_TRY + { + if (pci->cbSize == sizeof(CURSORINFO)) + { + ProbeForWrite(pci, sizeof(CURSORINFO), 1); + RtlCopyMemory(pci, &SafeCi, sizeof(CURSORINFO)); + Ret = TRUE; + } + else + { + EngSetLastError(ERROR_INVALID_PARAMETER); + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + } + + RETURN(Ret); + +CLEANUP: + TRACE("Leave NtUserGetCursorInfo, ret=%i\n",_ret_); + UserLeave(); + END_CLEANUP; +} + +BOOL +APIENTRY +UserClipCursor( + RECTL *prcl) +{ + /* FIXME: Check if process has WINSTA_WRITEATTRIBUTES */ + PSYSTEM_CURSORINFO CurInfo; + PWND DesktopWindow = NULL; + + CurInfo = IntGetSysCursorInfo(); + + DesktopWindow = UserGetDesktopWindow(); + + if (prcl != NULL && DesktopWindow != NULL) + { + if (prcl->right < prcl->left || prcl->bottom < prcl->top) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + CurInfo->bClipped = TRUE; + + /* Set nw cliping region. Note: we can't use RECTL_bIntersectRect because + it sets rect to 0 0 0 0 when it's empty. For more info see monitor winetest */ + CurInfo->rcClip.left = max(prcl->left, DesktopWindow->rcWindow.left); + CurInfo->rcClip.right = min(prcl->right, DesktopWindow->rcWindow.right); + if (CurInfo->rcClip.right < CurInfo->rcClip.left) + CurInfo->rcClip.right = CurInfo->rcClip.left; + + CurInfo->rcClip.top = max(prcl->top, DesktopWindow->rcWindow.top); + CurInfo->rcClip.bottom = min(prcl->bottom, DesktopWindow->rcWindow.bottom); + if (CurInfo->rcClip.bottom < CurInfo->rcClip.top) + CurInfo->rcClip.bottom = CurInfo->rcClip.top; + + /* Make sure cursor is in clipping region */ + UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y, 0, 0, FALSE); + } + else + { + CurInfo->bClipped = FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +APIENTRY +NtUserClipCursor( + RECTL *prcl) +{ + RECTL rclLocal; + BOOL bResult; + + if (prcl) + { + _SEH2_TRY + { + /* Probe and copy rect */ + ProbeForRead(prcl, sizeof(RECTL), 1); + rclLocal = *prcl; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + _SEH2_YIELD(return FALSE;) + } + _SEH2_END + + prcl = &rclLocal; + } + + UserEnterExclusive(); + + /* Call the internal function */ + bResult = UserClipCursor(prcl); + + UserLeave(); + + return bResult; +} + + +/* + * @implemented + */ +BOOL +APIENTRY +NtUserDestroyCursor( + HANDLE hCurIcon, + DWORD Unknown) +{ + PCURICON_OBJECT CurIcon; + BOOL ret; + DECLARE_RETURN(BOOL); + + TRACE("Enter NtUserDestroyCursorIcon\n"); + UserEnterExclusive(); + + if (!(CurIcon = UserGetCurIconObject(hCurIcon))) + { + RETURN(FALSE); + } + + ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process()); + /* Note: IntDestroyCurIconObject will remove our reference for us! */ + + RETURN(ret); + +CLEANUP: + TRACE("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_); + UserLeave(); + END_CLEANUP; +} + + +/* + * @implemented + */ +HICON +APIENTRY +NtUserFindExistingCursorIcon( + HMODULE hModule, + HRSRC hRsrc, + LONG cx, + LONG cy) +{ + PCURICON_OBJECT CurIcon; + HANDLE Ret = (HANDLE)0; + DECLARE_RETURN(HICON); + + TRACE("Enter NtUserFindExistingCursorIcon\n"); + UserEnterExclusive(); + + CurIcon = IntFindExistingCurIconObject(hModule, hRsrc, cx, cy); + if (CurIcon) + { + Ret = CurIcon->Self; + +// IntReleaseCurIconObject(CurIcon); // FIXME: Is this correct? Does IntFindExistingCurIconObject add a ref? + RETURN(Ret); + } + + EngSetLastError(ERROR_INVALID_CURSOR_HANDLE); + RETURN((HANDLE)0); + +CLEANUP: + TRACE("Leave NtUserFindExistingCursorIcon, ret=%p\n",_ret_); + UserLeave(); + END_CLEANUP; +} + + +/* + * @implemented + */ +BOOL +APIENTRY +NtUserGetClipCursor( + RECTL *lpRect) +{ + /* FIXME: Check if process has WINSTA_READATTRIBUTES */ + PSYSTEM_CURSORINFO CurInfo; + RECTL Rect; + NTSTATUS Status; + DECLARE_RETURN(BOOL); + + TRACE("Enter NtUserGetClipCursor\n"); + UserEnterExclusive(); + + if (!lpRect) + RETURN(FALSE); + + CurInfo = IntGetSysCursorInfo(); + if (CurInfo->bClipped) + { + Rect = CurInfo->rcClip; + } + else + { + Rect.left = 0; + Rect.top = 0; + Rect.right = UserGetSystemMetrics(SM_CXSCREEN); + Rect.bottom = UserGetSystemMetrics(SM_CYSCREEN); + } + + Status = MmCopyToCaller(lpRect, &Rect, sizeof(RECT)); + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + RETURN(FALSE); + } + + RETURN(TRUE); + +CLEANUP: + TRACE("Leave NtUserGetClipCursor, ret=%i\n",_ret_); + UserLeave(); + END_CLEANUP; +} + + +/* + * @implemented + */ +HCURSOR +APIENTRY +NtUserSetCursor( + HCURSOR hCursor) +{ + PCURICON_OBJECT pcurOld, pcurNew; + HCURSOR hOldCursor = NULL; + + TRACE("Enter NtUserSetCursor\n"); + UserEnterExclusive(); + + if (hCursor) + { + pcurNew = UserGetCurIconObject(hCursor); + if (!pcurNew) + { + EngSetLastError(ERROR_INVALID_CURSOR_HANDLE); + goto leave; + } + } + else + { + pcurNew = NULL; + } + + pcurOld = UserSetCursor(pcurNew, FALSE); + if (pcurOld) + { + hOldCursor = (HCURSOR)pcurOld->Self; + UserDereferenceObject(pcurOld); + } + +leave: + UserLeave(); + return hOldCursor; +} + + +/* + * @implemented + */ +BOOL +APIENTRY +NtUserSetCursorContents( + HANDLE hCurIcon, + PICONINFO UnsafeIconInfo) +{ + PCURICON_OBJECT CurIcon; + ICONINFO IconInfo; + PSURFACE psurfBmp; + NTSTATUS Status; + BOOL Ret = FALSE; + DECLARE_RETURN(BOOL); + + TRACE("Enter NtUserSetCursorContents\n"); + UserEnterExclusive(); + + if (!(CurIcon = UserGetCurIconObject(hCurIcon))) + { + RETURN(FALSE); + } + + /* Copy fields */ + Status = MmCopyFromCaller(&IconInfo, UnsafeIconInfo, sizeof(ICONINFO)); + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + goto done; + } + +#if 0 + /* Check if we get valid information */ + if(IconInfo.fIcon != CurInfo->bIcon) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + goto done; + } +#endif + + /* Delete old bitmaps */ + if (CurIcon->aFrame[0].hbmColor) + GreDeleteObject(CurIcon->aFrame[0].hbmColor); + if (CurIcon->aFrame[0].hbmMask) + GreDeleteObject(CurIcon->aFrame[0].hbmMask); + if(CurIcon->aFrame[0].hbmAlpha) + GreDeleteObject(CurIcon->aFrame[0].hbmAlpha); + + /* Set fields */ + CurIcon->bIcon = IconInfo.fIcon; + CurIcon->ptlHotspot.x = IconInfo.xHotspot; + CurIcon->ptlHotspot.y = IconInfo.yHotspot; + CurIcon->aFrame[0].hbmMask = IconInfo.hbmMask; + CurIcon->aFrame[0].hbmColor = IconInfo.hbmColor; + CurIcon->aFrame[0].hbmAlpha = NULL; + + if (IconInfo.hbmColor) + { + BOOLEAN bAlpha = FALSE; + psurfBmp = SURFACE_ShareLockSurface(IconInfo.hbmColor); + if (!psurfBmp) + goto done; + CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; + CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; + + /* 32bpp bitmap is likely to have an alpha channel */ + if(psurfBmp->SurfObj.iBitmapFormat == BMF_32BPP) + { + PFN_DIB_GetPixel fn_GetPixel = DibFunctionsForBitmapFormat[BMF_32BPP].DIB_GetPixel; + INT i, j; + + fn_GetPixel = DibFunctionsForBitmapFormat[BMF_32BPP].DIB_GetPixel; + for (i = 0; i < psurfBmp->SurfObj.sizlBitmap.cx; i++) + { + for (j = 0; j < psurfBmp->SurfObj.sizlBitmap.cy; j++) + { + bAlpha = ((BYTE)(fn_GetPixel(&psurfBmp->SurfObj, i, j) >> 24)) != 0; + if (bAlpha) + break; + } + if (bAlpha) + break; + } + } + /* We're done with this one */ + SURFACE_ShareUnlockSurface(psurfBmp); + GreSetObjectOwner(IconInfo.hbmColor, GDI_OBJ_HMGR_PUBLIC); + + if(bAlpha) + { + UCHAR Alpha; + PUCHAR ptr; + INT i, j; + /* Copy the bitmap */ + CurIcon->aFrame[0].hbmAlpha = BITMAP_CopyBitmap(IconInfo.hbmColor); + if(!CurIcon->aFrame[0].hbmAlpha) + { + ERR("BITMAP_CopyBitmap failed!"); + goto done; + } + + psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmAlpha); + if(!psurfBmp) + { + ERR("SURFACE_LockSurface failed!\n"); + goto done; + } + + /* Premultiply with the alpha channel value */ + for (i = 0; i < psurfBmp->SurfObj.sizlBitmap.cy; i++) + { + ptr = (PBYTE)psurfBmp->SurfObj.pvScan0 + i*psurfBmp->SurfObj.lDelta; + for (j = 0; j < psurfBmp->SurfObj.sizlBitmap.cx; j++) + { + Alpha = ptr[3]; + ptr[0] = (ptr[0] * Alpha) / 0xff; + ptr[1] = (ptr[1] * Alpha) / 0xff; + ptr[2] = (ptr[2] * Alpha) / 0xff; + ptr += 4; + } + } + SURFACE_ShareUnlockSurface(psurfBmp); + GreSetObjectOwner(CurIcon->aFrame[0].hbmAlpha, GDI_OBJ_HMGR_PUBLIC); + } + } + else + { + psurfBmp = SURFACE_ShareLockSurface(IconInfo.hbmMask); + if (!psurfBmp) + goto done; + + CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; + CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy / 2; + + SURFACE_ShareUnlockSurface(psurfBmp); + } + GreSetObjectOwner(IconInfo.hbmMask, GDI_OBJ_HMGR_PUBLIC); + + Ret = TRUE; + +done: + + if(!Ret) + { + IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process()); + CurIcon = NULL; + } + + if (CurIcon) + { + UserDereferenceObject(CurIcon); + } + RETURN(Ret); + +CLEANUP: + TRACE("Leave NtUserSetCursorContents, ret=%i\n",_ret_); + UserLeave(); + END_CLEANUP; +} + + +/* + * @implemented + */ +#ifdef NEW_CURSORICON +BOOL +APIENTRY +NtUserSetCursorIconData( + _In_ HCURSOR Handle, + _In_ HINSTANCE hinst, + _In_ HRSRC hrsrc, + _In_ PICONINFO pIconInfo) +{ + PCURICON_OBJECT CurIcon; + PSURFACE psurfBmp; + NTSTATUS Status = STATUS_SUCCESS; + BOOL Ret = FALSE; + DECLARE_RETURN(BOOL); + ICONINFO ii; + + TRACE("Enter NtUserSetCursorIconData\n"); + UserEnterExclusive(); + + if (!(CurIcon = UserGetCurIconObject(Handle))) + { + RETURN(FALSE); + } + + CurIcon->hModule = hinst; + CurIcon->hRsrc =hrsrc; + + _SEH2_TRY + { + ProbeForRead(pIconInfo, sizeof(ICONINFO), 1); + ii = *pIconInfo; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END + + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + goto done; + } + + /* This is probably not what windows does, but consistency checks can't hurt */ + if(CurIcon->bIcon != ii.fIcon) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + CurIcon->ptlHotspot.x = ii.xHotspot; + CurIcon->ptlHotspot.y = ii.yHotspot; + + if(!ii.hbmMask) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + CurIcon->aFrame[0].hbmMask = BITMAP_CopyBitmap(ii.hbmMask); + if(!CurIcon->aFrame[0].hbmMask) + goto done; + + if(ii.hbmColor) + { + CurIcon->aFrame[0].hbmColor = BITMAP_CopyBitmap(ii.hbmColor); + if(!CurIcon->aFrame[0].hbmColor) + goto done; + } + + if (CurIcon->aFrame[0].hbmColor) + { + if ((psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor))) + { + CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; + CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; + SURFACE_ShareUnlockSurface(psurfBmp); + GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); + } + else + goto done; + } + else + { + if ((psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmMask))) + { + CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; + CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy/2; + SURFACE_ShareUnlockSurface(psurfBmp); + } + else + goto done; + } + GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); + + Ret = TRUE; + +done: + UserDereferenceObject(CurIcon); + if(!Ret) + { + if (CurIcon->aFrame[0].hbmMask) + { + GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_POWNED); + GreDeleteObject(CurIcon->aFrame[0].hbmMask); + CurIcon->aFrame[0].hbmMask = NULL; + } + if (CurIcon->aFrame[0].hbmColor) + { + GreSetObjectOwner(CurIcon->aFrame[0].hbmColor, GDI_OBJ_HMGR_POWNED); + GreDeleteObject(CurIcon->aFrame[0].hbmColor); + CurIcon->aFrame[0].hbmColor = NULL; + } + } + RETURN(Ret); + +CLEANUP: + TRACE("Leave NtUserSetCursorIconData, ret=%i\n",_ret_); + UserLeave(); + END_CLEANUP; +} +#else +BOOL +APIENTRY +NtUserSetCursorIconData( + HANDLE hCurIcon, + PBOOL fIcon, + POINT *Hotspot, + HMODULE hModule, + HRSRC hRsrc, + HRSRC hGroupRsrc) +{ + PCURICON_OBJECT CurIcon; + NTSTATUS Status; + BOOL Ret = FALSE; + DECLARE_RETURN(BOOL); + + TRACE("Enter NtUserSetCursorIconData\n"); + UserEnterExclusive(); + + if (!(CurIcon = UserGetCurIconObject(hCurIcon))) + { + RETURN(FALSE); + } + + CurIcon->hModule = hModule; + CurIcon->hRsrc = hRsrc; + CurIcon->hGroupRsrc = hGroupRsrc; + + /* Copy fields */ + if (fIcon) + { + Status = MmCopyFromCaller(&CurIcon->bIcon, fIcon, sizeof(BOOL)); + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + goto done; + } + } + else + { + if (!Hotspot) + Ret = TRUE; + } + + if (Hotspot) + { + Status = MmCopyFromCaller(&CurIcon->ptlHotspot, Hotspot, sizeof(POINT)); + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + goto done; + } + } + + if (!fIcon && !Hotspot) + { + Ret = TRUE; + } + +done: + if(Ret) + { + /* This icon is shared now */ + GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); + if(CurIcon->aFrame[0].hbmColor) + { + GreSetObjectOwner(CurIcon->aFrame[0].hbmColor, GDI_OBJ_HMGR_PUBLIC); + } + if(CurIcon->aFrame[0].hbmAlpha) + { + GreSetObjectOwner(CurIcon->aFrame[0].hbmAlpha, GDI_OBJ_HMGR_PUBLIC); + } + } + UserDereferenceObject(CurIcon); + RETURN(Ret); + + +CLEANUP: + TRACE("Leave NtUserSetCursorIconData, ret=%i\n",_ret_); + UserLeave(); + END_CLEANUP; +} +#endif + +/* Mostly inspired from wine code. + * We use low level functions because: + * - at this point, the icon bitmap could have a different bit depth than the DC, + * making it thus impossible to use NtCreateCompatibleDC and selecting the bitmap. + * This happens after a mode setting change. + * - it avoids massive GDI objects locking when only the destination surface needs it. + * - It makes (small) performance gains. + */ +BOOL +UserDrawIconEx( + HDC hDc, + INT xLeft, + INT yTop, + PCURICON_OBJECT pIcon, + INT cxWidth, + INT cyHeight, + UINT istepIfAniCur, + HBRUSH hbrFlickerFreeDraw, + UINT diFlags) +{ + PSURFACE psurfDest, psurfMask, psurfColor, psurfOffScreen; + PDC pdc = NULL; + BOOL Ret = FALSE; + HBITMAP hbmMask, hbmColor, hbmAlpha; + BOOL bOffScreen; + RECTL rcDest, rcSrc; + CLIPOBJ* pdcClipObj = NULL; + EXLATEOBJ exlo; + + /* Stupid case */ + if((diFlags & DI_NORMAL) == 0) + { + ERR("DrawIconEx called without mask or color bitmap to draw.\n"); + return FALSE; + } + + hbmMask = pIcon->aFrame[0].hbmMask; + hbmColor = pIcon->aFrame[0].hbmColor; + hbmAlpha = pIcon->aFrame[0].hbmAlpha; + + if (istepIfAniCur) + ERR("NtUserDrawIconEx: istepIfAniCur is not supported!\n"); + + /* + * Get our objects. + * Shared locks are enough, we are only reading those bitmaps + */ + psurfMask = SURFACE_ShareLockSurface(hbmMask); + if(psurfMask == NULL) + { + ERR("Unable to lock the mask surface.\n"); + return FALSE; + } + + /* Color bitmap is not mandatory */ + if(hbmColor == NULL) + { + /* But then the mask bitmap must have the information in it's bottom half */ + ASSERT(psurfMask->SurfObj.sizlBitmap.cy == 2*pIcon->Size.cy); + psurfColor = NULL; + } + else if ((psurfColor = SURFACE_ShareLockSurface(hbmColor)) == NULL) + { + ERR("Unable to lock the color bitmap.\n"); + SURFACE_ShareUnlockSurface(psurfMask); + return FALSE; + } + + /* Set source rect */ + RECTL_vSetRect(&rcSrc, 0, 0, pIcon->Size.cx, pIcon->Size.cy); + + /* Fix width parameter, if needed */ + if (!cxWidth) + { + if(diFlags & DI_DEFAULTSIZE) + cxWidth = pIcon->bIcon ? + UserGetSystemMetrics(SM_CXICON) : UserGetSystemMetrics(SM_CXCURSOR); + else + cxWidth = pIcon->Size.cx; + } + + /* Fix height parameter, if needed */ + if (!cyHeight) + { + if(diFlags & DI_DEFAULTSIZE) + cyHeight = pIcon->bIcon ? + UserGetSystemMetrics(SM_CYICON) : UserGetSystemMetrics(SM_CYCURSOR); + else + cyHeight = pIcon->Size.cy; + } + + /* Should we render off-screen? */ + bOffScreen = hbrFlickerFreeDraw && (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH); + + if (bOffScreen) + { + /* Yes: Allocate and paint the offscreen surface */ + EBRUSHOBJ eboFill; + PBRUSH pbrush = BRUSH_ShareLockBrush(hbrFlickerFreeDraw); + + TRACE("Performing off-screen rendering.\n"); + + if(!pbrush) + { + ERR("Failed to get brush object.\n"); + SURFACE_ShareUnlockSurface(psurfMask); + if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); + return FALSE; + } + + psurfOffScreen = SURFACE_AllocSurface(STYPE_BITMAP, + cxWidth, cyHeight, psurfColor->SurfObj.iBitmapFormat, + 0, 0, NULL); + if(!psurfOffScreen) + { + ERR("Failed to allocate the off-screen surface.\n"); + SURFACE_ShareUnlockSurface(psurfMask); + if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); + BRUSH_ShareUnlockBrush(pbrush); + return FALSE; + } + + /* Paint the brush */ + EBRUSHOBJ_vInit(&eboFill, pbrush, psurfOffScreen, 0x00FFFFFF, 0, NULL); + RECTL_vSetRect(&rcDest, 0, 0, cxWidth, cyHeight); + + Ret = IntEngBitBlt(&psurfOffScreen->SurfObj, + NULL, + NULL, + NULL, + NULL, + &rcDest, + NULL, + NULL, + &eboFill.BrushObject, + &pbrush->ptOrigin, + ROP4_PATCOPY); + + /* Clean up everything */ + EBRUSHOBJ_vCleanup(&eboFill); + BRUSH_ShareUnlockBrush(pbrush); + + if(!Ret) + { + ERR("Failed to paint the off-screen surface.\n"); + SURFACE_ShareUnlockSurface(psurfMask); + if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); + GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject); + return FALSE; + } + + /* We now have our destination surface */ + psurfDest = psurfOffScreen; + } + else + { + /* We directly draw to the DC */ + TRACE("Performing on screen rendering.\n"); + + psurfOffScreen = NULL; + pdc = DC_LockDc(hDc); + if(!pdc) + { + ERR("Could not lock the destination DC.\n"); + SURFACE_ShareUnlockSurface(psurfMask); + if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); + return FALSE; + } + /* Calculate destination rectangle */ + RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); + IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); + RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); + + /* Prepare the underlying surface */ + DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest); + + /* Get the clip object */ + pdcClipObj = pdc->rosdc.CombinedClip; + + /* We now have our destination surface and rectangle */ + psurfDest = pdc->dclevel.pSurface; + + if(psurfDest == NULL) + { + /* Empty DC */ + DC_vFinishBlit(pdc, NULL); + DC_UnlockDc(pdc); + SURFACE_ShareUnlockSurface(psurfMask); + if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); + return FALSE; + } + } + + /* Now do the rendering */ + if(hbmAlpha && (diFlags & DI_IMAGE)) + { + BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } }; + PSURFACE psurf = NULL; + + psurf = SURFACE_ShareLockSurface(hbmAlpha); + if(!psurf) + { + ERR("SURFACE_LockSurface failed!\n"); + goto NoAlpha; + } + + /* Initialize color translation object */ + EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xFFFFFFFF, 0xFFFFFFFF, 0); + + /* Now do it */ + Ret = IntEngAlphaBlend(&psurfDest->SurfObj, + &psurf->SurfObj, + pdcClipObj, + &exlo.xlo, + &rcDest, + &rcSrc, + &blendobj); + + EXLATEOBJ_vCleanup(&exlo); + SURFACE_ShareUnlockSurface(psurf); + if(Ret) goto done; + ERR("NtGdiAlphaBlend failed!\n"); + } +NoAlpha: + if (diFlags & DI_MASK) + { + DWORD rop4 = (diFlags & DI_IMAGE) ? ROP4_SRCAND : ROP4_SRCCOPY; + + EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0); + + Ret = IntEngStretchBlt(&psurfDest->SurfObj, + &psurfMask->SurfObj, + NULL, + pdcClipObj, + &exlo.xlo, + NULL, + &rcDest, + &rcSrc, + NULL, + NULL, + NULL, + rop4); + + EXLATEOBJ_vCleanup(&exlo); + + if(!Ret) + { + ERR("Failed to mask the bitmap data.\n"); + goto Cleanup; + } + } + + if(diFlags & DI_IMAGE) + { + if (psurfColor) + { + DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY ; + + EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0); + + Ret = IntEngStretchBlt(&psurfDest->SurfObj, + &psurfColor->SurfObj, + NULL, + pdcClipObj, + &exlo.xlo, + NULL, + &rcDest, + &rcSrc, + NULL, + NULL, + NULL, + rop4); + + EXLATEOBJ_vCleanup(&exlo); + + if(!Ret) + { + ERR("Failed to render the icon bitmap.\n"); + goto Cleanup; + } + } + else + { + /* Mask bitmap holds the information in its bottom half */ + DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY; + RECTL_vOffsetRect(&rcSrc, 0, pIcon->Size.cy); + + EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0); + + Ret = IntEngStretchBlt(&psurfDest->SurfObj, + &psurfMask->SurfObj, + NULL, + pdcClipObj, + &exlo.xlo, + NULL, + &rcDest, + &rcSrc, + NULL, + NULL, + NULL, + rop4); + + EXLATEOBJ_vCleanup(&exlo); + + if(!Ret) + { + ERR("Failed to render the icon bitmap.\n"); + goto Cleanup; + } + } + } + +done: + /* We're done. Was it a double buffered draw ? */ + if(bOffScreen) + { + /* Yes. Draw it back to our DC */ + POINTL ptSrc = {0, 0}; + pdc = DC_LockDc(hDc); + if(!pdc) + { + ERR("Could not lock the destination DC.\n"); + return FALSE; + } + /* Calculate destination rectangle */ + RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); + IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); + RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); + + /* Prepare the underlying surface */ + DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest); + + /* Get the clip object */ + pdcClipObj = pdc->rosdc.CombinedClip; + + /* We now have our destination surface and rectangle */ + psurfDest = pdc->dclevel.pSurface; + if(!psurfDest) + { + /* So, you did all of this for an empty DC. */ + DC_UnlockDc(pdc); + goto Cleanup2; + } + + /* Color translation */ + EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0); + + /* Blt it! */ + Ret = IntEngBitBlt(&psurfDest->SurfObj, + &psurfOffScreen->SurfObj, + NULL, + pdcClipObj, + &exlo.xlo, + &rcDest, + &ptSrc, + NULL, + NULL, + NULL, + ROP4_SRCCOPY); + + EXLATEOBJ_vCleanup(&exlo); + } +Cleanup: + if(pdc) + { + DC_vFinishBlit(pdc, NULL); + DC_UnlockDc(pdc); + } + +Cleanup2: + /* Delete off screen rendering surface */ + if(psurfOffScreen) + GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject); + + /* Unlock other surfaces */ + SURFACE_ShareUnlockSurface(psurfMask); + if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); + + return Ret; +} + +/* + * @implemented + */ +BOOL +APIENTRY +NtUserDrawIconEx( + HDC hdc, + int xLeft, + int yTop, + HICON hIcon, + int cxWidth, + int cyHeight, + UINT istepIfAniCur, + HBRUSH hbrFlickerFreeDraw, + UINT diFlags, + BOOL bMetaHDC, // When TRUE, GDI functions need to be handled in User32! + PVOID pDIXData) +{ + PCURICON_OBJECT pIcon; + BOOL Ret; + + TRACE("Enter NtUserDrawIconEx\n"); + UserEnterExclusive(); + + if (!(pIcon = UserGetCurIconObject(hIcon))) + { + ERR("UserGetCurIconObject() failed!\n"); + UserLeave(); + return FALSE; + } + + Ret = UserDrawIconEx(hdc, + xLeft, + yTop, + pIcon, + cxWidth, + cyHeight, + istepIfAniCur, + hbrFlickerFreeDraw, + diFlags); + + UserDereferenceObject(pIcon); + + UserLeave(); + return Ret; +} + +/* EOF */ diff --git a/reactos/win32ss/user/ntuser/msgqueue.c b/reactos/win32ss/user/ntuser/msgqueue.c index 38245a1ec82..0ae86125932 100644 --- a/reactos/win32ss/user/ntuser/msgqueue.c +++ b/reactos/win32ss/user/ntuser/msgqueue.c @@ -145,6 +145,7 @@ UserSetCursor( if (NewCursor) { /* Call GDI to set the new screen cursor */ +#ifdef NEW_CURSORICON GreSetPointerShape(hdcScreen, NewCursor->aFrame[0].hbmMask, NewCursor->aFrame[0].hbmColor, @@ -152,6 +153,15 @@ UserSetCursor( NewCursor->ptlHotspot.y, gpsi->ptCursor.x, gpsi->ptCursor.y); +#else + GreSetPointerShape(hdcScreen, + NewCursor->IconInfo.hbmMask, + NewCursor->IconInfo.hbmColor, + NewCursor->IconInfo.xHotspot, + NewCursor->IconInfo.yHotspot, + gpsi->ptCursor.x, + gpsi->ptCursor.y); +#endif } else /* Note: OldCursor != NewCursor so we have to hide cursor */ { @@ -571,6 +581,7 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook if(CurInfo->CurrentCursorObject != MessageQueue->CursorObject) { /* Call GDI to set the new screen cursor */ +#ifdef NEW_CURSORICON GreSetPointerShape(hdcScreen, MessageQueue->CursorObject->aFrame[0].hbmMask, MessageQueue->CursorObject->aFrame[0].hbmColor, @@ -578,6 +589,15 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook MessageQueue->CursorObject->ptlHotspot.y, gpsi->ptCursor.x, gpsi->ptCursor.y); +#else + GreSetPointerShape(hdcScreen, + MessageQueue->CursorObject->IconInfo.hbmMask, + MessageQueue->CursorObject->IconInfo.hbmColor, + MessageQueue->CursorObject->IconInfo.xHotspot, + MessageQueue->CursorObject->IconInfo.yHotspot, + gpsi->ptCursor.x, + gpsi->ptCursor.y); +#endif } else GreMovePointer(hdcScreen, Msg->pt.x, Msg->pt.y); } From a74a3edcc74ddaa4fc3f8fb2734d907b7d877c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Mon, 29 Oct 2012 16:12:49 +0000 Subject: [PATCH 11/16] [USER32_APITESTS] - Add some test for DestroyCursor/DestroyIcon svn path=/trunk/; revision=57647 --- rostests/apitests/user32/CMakeLists.txt | 1 + rostests/apitests/user32/DestroyCursorIcon.c | 49 ++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 rostests/apitests/user32/DestroyCursorIcon.c diff --git a/rostests/apitests/user32/CMakeLists.txt b/rostests/apitests/user32/CMakeLists.txt index 4613c22b638..0a1d7491569 100644 --- a/rostests/apitests/user32/CMakeLists.txt +++ b/rostests/apitests/user32/CMakeLists.txt @@ -3,6 +3,7 @@ list(APPEND SOURCE AttachThreadInput.c helper.c DeferWindowPos.c + DestroyCursorIcon.c desktop.c GetIconInfo.c GetKeyState.c diff --git a/rostests/apitests/user32/DestroyCursorIcon.c b/rostests/apitests/user32/DestroyCursorIcon.c new file mode 100644 index 00000000000..3761c979000 --- /dev/null +++ b/rostests/apitests/user32/DestroyCursorIcon.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include "resource.h" + +START_TEST(DestroyCursorIcon) +{ + HICON hicon; + HCURSOR hcursor; + ICONINFO iconinfo; + + ZeroMemory(&iconinfo, sizeof(iconinfo)); + + iconinfo.hbmMask = CreateBitmap(8, 16, 1, 1, NULL); + ok(iconinfo.hbmMask != NULL, "\n"); + + /* + * Test if DestroyCursor can destroy an icon, and vice-versa . + * It can. + */ + iconinfo.fIcon = TRUE; + hicon = CreateIconIndirect(&iconinfo); + ok(hicon != 0, "should not fail\n"); + ok(DestroyCursor(hicon), "\n"); + ok(!DestroyIcon(hicon), "\n"); + + iconinfo.fIcon = FALSE; + hcursor = CreateIconIndirect(&iconinfo); + ok(hcursor != 0, "should not fail\n"); + ok(DestroyIcon(hcursor), "\n"); + ok(!DestroyCursor(hcursor), "\n"); + + /* Clean up */ + DeleteObject(iconinfo.hbmMask); + + /* Now check its behaviour regarding Shared icons/cursors */ + hcursor = LoadCursor(GetModuleHandle(NULL), "TESTCURSOR"); + ok(hcursor != 0, "\n"); + + /* MSDN says we shouldn't do that, but it still succeeds */ + ok(DestroyCursor(hcursor), "\n"); + + /* In fact, it's still there */ + ok(GetIconInfo(hcursor, &iconinfo), "\n"); + + /* clean up */ + DeleteObject(iconinfo.hbmMask); + DeleteObject(iconinfo.hbmColor); +} \ No newline at end of file From f40fbb64a63bbf7ea43a1129f02b0b3cafa5f822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Mon, 29 Oct 2012 16:14:54 +0000 Subject: [PATCH 12/16] [USER32_APITEST] - More thorough test for what really happens after the "destruction" of a shared cursor. svn path=/trunk/; revision=57648 --- rostests/apitests/user32/DestroyCursorIcon.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rostests/apitests/user32/DestroyCursorIcon.c b/rostests/apitests/user32/DestroyCursorIcon.c index 3761c979000..38b2fef99e5 100644 --- a/rostests/apitests/user32/DestroyCursorIcon.c +++ b/rostests/apitests/user32/DestroyCursorIcon.c @@ -41,7 +41,11 @@ START_TEST(DestroyCursorIcon) ok(DestroyCursor(hcursor), "\n"); /* In fact, it's still there */ + ZeroMemory(&iconinfo, sizeof(iconinfo)); ok(GetIconInfo(hcursor, &iconinfo), "\n"); + ok(iconinfo.hbmMask != NULL, "\n"); + ok(iconinfo.hbmColor != NULL, "\n"); + ok(!iconinfo.fIcon, "\n"); /* clean up */ DeleteObject(iconinfo.hbmMask); From 1c8f7b026b228282d4d5f5ee47a8c2b3f4fdc499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 30 Oct 2012 01:39:28 +0000 Subject: [PATCH 13/16] [USER32_APITEST] - Commit forgotten file svn path=/trunk/; revision=57649 --- rostests/apitests/user32/testlist.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rostests/apitests/user32/testlist.c b/rostests/apitests/user32/testlist.c index 6857b95b874..0c8737fc3a4 100644 --- a/rostests/apitests/user32/testlist.c +++ b/rostests/apitests/user32/testlist.c @@ -7,6 +7,7 @@ extern void func_AttachThreadInput(void); extern void func_DeferWindowPos(void); +extern void func_DestroyCursorIcon(void); extern void func_desktop(void); extern void func_GetIconInfo(void); extern void func_GetKeyState(void); @@ -28,6 +29,7 @@ const struct test winetest_testlist[] = { "AttachThreadInput", func_AttachThreadInput }, { "desktop", func_desktop }, { "DeferWindowPos", func_DeferWindowPos }, + { "DestroyCursorIcon", func_DestroyCursorIcon }, { "GetIconInfo", func_GetIconInfo }, { "GetKeyState", func_GetKeyState }, { "GetPeekMessage", func_GetPeekMessage }, From 95411ee85ddddd01ef0c1b901046d15409d186af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 30 Oct 2012 02:05:52 +0000 Subject: [PATCH 14/16] [W32K_APITEST] - Better test for NtUserGetIconInfo svn path=/trunk/; revision=57650 --- .../w32knapi/ntuser/NtUserGetIconInfo.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/rostests/apitests/w32knapi/ntuser/NtUserGetIconInfo.c b/rostests/apitests/w32knapi/ntuser/NtUserGetIconInfo.c index 2b4fd81a7f5..3e20fea5615 100644 --- a/rostests/apitests/w32knapi/ntuser/NtUserGetIconInfo.c +++ b/rostests/apitests/w32knapi/ntuser/NtUserGetIconInfo.c @@ -109,7 +109,9 @@ Test_NtUserGetIconInfo(PTESTINFO pti) TEST(hIcon != NULL); - RtlInitUnicodeString(&hInstStr, NULL); + hInstStr.Buffer = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); + hInstStr.MaximumLength = MAX_PATH; + hInstStr.Length = 0; RtlInitUnicodeString(&ResourceStr, NULL); TEST(NtUserGetIconInfo(hIcon, @@ -119,15 +121,16 @@ Test_NtUserGetIconInfo(PTESTINFO pti) &bpp, FALSE) == TRUE); - TESTX(hInstStr.Buffer == NULL, "hInstStr.buffer : %p\n", hInstStr.Buffer); - TEST(hInstStr.Length == 0); - TEST(hInstStr.MaximumLength == 0); + TEST(hInstStr.Length != 0); + hInstStr.Buffer[hInstStr.Length] = 0; + printf("%s,%i: hInstStr.buffer : %S\n", __FUNCTION__, __LINE__, hInstStr.Buffer); TEST((LPCTSTR)ResourceStr.Buffer == MAKEINTRESOURCE(293)); TEST(ResourceStr.Length == 0); TEST(ResourceStr.MaximumLength == 0); TEST(bpp == 32); - RtlInitUnicodeString(&hInstStr, NULL); + ZeroMemory(hInstStr.Buffer, MAX_PATH*sizeof(WCHAR)); + hInstStr.Length = 0; RtlInitUnicodeString(&ResourceStr, NULL); TEST(NtUserGetIconInfo(hIcon, @@ -137,9 +140,9 @@ Test_NtUserGetIconInfo(PTESTINFO pti) &bpp, TRUE) == TRUE); - TESTX(hInstStr.Buffer == NULL, "hInstStr.buffer : %p\n", hInstStr.Buffer); - TEST(hInstStr.Length == 0); - TEST(hInstStr.MaximumLength == 0); + TEST(hInstStr.Length != 0); + hInstStr.Buffer[hInstStr.Length] = 0; + printf("%s,%i: hInstStr.buffer : %S\n", __FUNCTION__, __LINE__, hInstStr.Buffer); TEST((LPCTSTR)ResourceStr.Buffer == MAKEINTRESOURCE(293)); TEST(bpp == 32); From 864bf93f953c2ea660b82391b8ec15337fb7bfd0 Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Tue, 30 Oct 2012 13:29:11 +0000 Subject: [PATCH 15/16] [user32_apitest] - Add a test for LR_SHARED flag for LoadImage svn path=/trunk/; revision=57651 --- rostests/apitests/user32/CMakeLists.txt | 1 + rostests/apitests/user32/LoadImage.c | 38 +++++++++++++++++++++++++ rostests/apitests/user32/testlist.c | 2 ++ 3 files changed, 41 insertions(+) create mode 100644 rostests/apitests/user32/LoadImage.c diff --git a/rostests/apitests/user32/CMakeLists.txt b/rostests/apitests/user32/CMakeLists.txt index 0a1d7491569..8bb6e912b45 100644 --- a/rostests/apitests/user32/CMakeLists.txt +++ b/rostests/apitests/user32/CMakeLists.txt @@ -10,6 +10,7 @@ list(APPEND SOURCE GetPeekMessage.c GetSystemMetrics.c InitializeLpkHooks.c + LoadImage.c RealGetWindowClass.c ScrollDC.c ScrollWindowEx.c diff --git a/rostests/apitests/user32/LoadImage.c b/rostests/apitests/user32/LoadImage.c new file mode 100644 index 00000000000..ef6b8de5c7f --- /dev/null +++ b/rostests/apitests/user32/LoadImage.c @@ -0,0 +1,38 @@ + +#include +#include +#include +#include "resource.h" + +START_TEST(LoadImage) +{ + char path[MAX_PATH]; + PROCESS_INFORMATION pi; + STARTUPINFO si; + HANDLE handle; + + char **test_argv; + int argc = winetest_get_mainargs( &test_argv ); + + /* Now check its behaviour regarding Shared icons/cursors */ + handle = LoadImageW( GetModuleHandle(NULL), L"TESTCURSOR", IMAGE_CURSOR, 0, 0, LR_SHARED | LR_DEFAULTSIZE ); + ok(handle != 0, "\n"); + + if (argc >= 3) + { + HANDLE arg; + + sscanf (test_argv[2], "%lu", (ULONG_PTR*) &arg); + + ok(handle != arg, "Got same handles\n"); + + return; + } + + /* Start child process */ + sprintf( path, "%s LoadImage %lu", test_argv[0], (ULONG_PTR)handle ); + memset( &si, 0, sizeof(si) ); + si.cb = sizeof(si); + CreateProcessA( NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ); + WaitForSingleObject (pi.hProcess, INFINITE); +} \ No newline at end of file diff --git a/rostests/apitests/user32/testlist.c b/rostests/apitests/user32/testlist.c index 0c8737fc3a4..9e86083bcc7 100644 --- a/rostests/apitests/user32/testlist.c +++ b/rostests/apitests/user32/testlist.c @@ -14,6 +14,7 @@ extern void func_GetKeyState(void); extern void func_GetPeekMessage(void); extern void func_GetSystemMetrics(void); extern void func_InitializeLpkHooks(void); +extern void func_LoadImage(void); extern void func_RealGetWindowClass(void); extern void func_ScrollDC(void); extern void func_ScrollWindowEx(void); @@ -35,6 +36,7 @@ const struct test winetest_testlist[] = { "GetPeekMessage", func_GetPeekMessage }, { "GetSystemMetrics", func_GetSystemMetrics }, { "InitializeLpkHooks", func_InitializeLpkHooks }, + { "LoadImage", func_LoadImage }, { "RealGetWindowClass", func_RealGetWindowClass }, { "ScrollDC", func_ScrollDC }, { "ScrollWindowEx", func_ScrollWindowEx }, From ccb9c49a46ee81b10bb294be39f34ffdc169f068 Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Tue, 30 Oct 2012 16:50:11 +0000 Subject: [PATCH 16/16] [win32k] - Fix the remaining tests that failed in user32:winstation svn path=/trunk/; revision=57652 --- reactos/win32ss/user/ntuser/winsta.c | 41 ++++++++++++----------- reactos/win32ss/user/user32/misc/object.c | 18 +++++----- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/reactos/win32ss/user/ntuser/winsta.c b/reactos/win32ss/user/ntuser/winsta.c index 64039cbfbce..13adc556057 100644 --- a/reactos/win32ss/user/ntuser/winsta.c +++ b/reactos/win32ss/user/ntuser/winsta.c @@ -526,7 +526,7 @@ NtUserCloseWindowStation( if (hWinSta == UserGetProcessWindowStation()) { - ERR("Attempted to close process window station"); + ERR("Attempted to close process window station\n"); return FALSE; } @@ -612,19 +612,13 @@ NtUserGetObjectInformation( /* try windowstation */ TRACE("Trying to open window station 0x%x\n", hObject); - Status = IntValidateWindowStationHandle( + Status = ObReferenceObjectByHandle( hObject, - UserMode, 0, - &WinStaObject); - - - if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_TYPE_MISMATCH) - { - TRACE("Failed: 0x%x\n", Status); - SetLastNtError(Status); - return FALSE; - } + ExWindowStationObjectType, + UserMode, + (PVOID*)&WinStaObject, + NULL); if (Status == STATUS_OBJECT_TYPE_MISMATCH) { @@ -635,13 +629,15 @@ NtUserGetObjectInformation( UserMode, 0, &DesktopObject); - if (!NT_SUCCESS(Status)) - { - TRACE("Failed: 0x%x\n", Status); - SetLastNtError(Status); - return FALSE; - } } + + if (!NT_SUCCESS(Status)) + { + ERR("Failed: 0x%x\n", Status); + SetLastNtError(Status); + return FALSE; + } + TRACE("WinSta or Desktop opened!!\n"); /* get data */ @@ -713,8 +709,13 @@ NtUserGetObjectInformation( if (DesktopObject != NULL) ObDereferenceObject(DesktopObject); - SetLastNtError(Status); - return NT_SUCCESS(Status); + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return FALSE; + } + + return TRUE; } /* diff --git a/reactos/win32ss/user/user32/misc/object.c b/reactos/win32ss/user/user32/misc/object.c index 5c97e0a521c..a40eef27c83 100644 --- a/reactos/win32ss/user/user32/misc/object.c +++ b/reactos/win32ss/user/user32/misc/object.c @@ -48,7 +48,8 @@ GetUserObjectInformationA( LPDWORD lpnLengthNeeded) { LPWSTR buffer; - BOOL ret = TRUE; + BOOL ret = FALSE; + DWORD LengthNeeded; TRACE("GetUserObjectInformationA(%x %d %x %d %x)\n", hObj, nIndex, pvInfo, nLength, lpnLengthNeeded); @@ -65,17 +66,16 @@ GetUserObjectInformationA( } /* get unicode string */ - if (!GetUserObjectInformationW(hObj, nIndex, buffer, nLength*2, lpnLengthNeeded)) - ret = FALSE; - *lpnLengthNeeded /= 2; - - if (ret) + if (GetUserObjectInformationW(hObj, nIndex, buffer, nLength*2, lpnLengthNeeded)) { /* convert string */ - if (WideCharToMultiByte(CP_THREAD_ACP, 0, buffer, -1, - pvInfo, nLength, NULL, NULL) == 0) + LengthNeeded = WideCharToMultiByte(CP_THREAD_ACP, 0, buffer, -1, + pvInfo, nLength, NULL, NULL); + + if (LengthNeeded != 0) { - ret = FALSE; + *lpnLengthNeeded = LengthNeeded; + ret = TRUE; } }