diff --git a/win32ss/include/callback.h b/win32ss/include/callback.h index 9fdf265ba59..69e4e1f5c92 100644 --- a/win32ss/include/callback.h +++ b/win32ss/include/callback.h @@ -62,6 +62,15 @@ typedef struct _HOOKPROC_CALLBACK_ARGUMENTS WCHAR ModuleName[512]; } HOOKPROC_CALLBACK_ARGUMENTS, *PHOOKPROC_CALLBACK_ARGUMENTS; +typedef struct _LOADIMAGE_CALLBACK_ARGUMENTS +{ + UINT ImageType; + int cxDesired; + int cyDesired; + UINT fuFlags; + WCHAR ImageName[MAX_PATH]; +} LOADIMAGE_CALLBACK_ARGUMENTS, *PLOADIMAGE_CALLBACK_ARGUMENTS; + typedef struct _HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS { CREATESTRUCTW Cs; /* lpszName and lpszClass replaced by offsets */ @@ -128,6 +137,26 @@ typedef struct _GET_CHARSET_INFO CHARSETINFO Cs; } GET_CHARSET_INFO, *PGET_CHARSET_INFO; +typedef struct _LOADCURSORS_CALLBACK_ARGUMENTS +{ + HCURSOR hCursorArrow; + HCURSOR hCursorIbeam; + HCURSOR hCursorWait; + HCURSOR hCursorCross; + HCURSOR hCursorUp; + HCURSOR hCursorIcon; + HCURSOR hCursorSize; + HCURSOR hCursorSizeNwse; + HCURSOR hCursorSizeNesw; + HCURSOR hCursorSizeWe; + HCURSOR hCursorSizeNs; + HCURSOR hCursorSizeAll; + HCURSOR hCursorNo; + HCURSOR hCursorHand; + HCURSOR hCursorAppStarting; + HCURSOR hCursorHelp; +} LOADCURSORS_CALLBACK_ARGUMENTS, *PLOADCURSORS_CALLBACK_ARGUMENTS; + typedef struct _SETWNDICONS_CALLBACK_ARGUMENTS { HICON hIconSample; @@ -185,6 +214,8 @@ typedef struct _IMMLOADLAYOUT_CALLBACK_OUTPUT IMEINFOEX iiex; } IMMLOADLAYOUT_CALLBACK_OUTPUT, *PIMMLOADLAYOUT_CALLBACK_OUTPUT; +NTSTATUS WINAPI +User32CallLoadImageFromKernel(PVOID Arguments, ULONG ArgumentLength); NTSTATUS WINAPI User32CallCopyImageFromKernel(PVOID Arguments, ULONG ArgumentLength); NTSTATUS WINAPI diff --git a/win32ss/include/u32cb.h b/win32ss/include/u32cb.h index 168df49f7dc..3f4233de4fe 100644 --- a/win32ss/include/u32cb.h +++ b/win32ss/include/u32cb.h @@ -16,13 +16,14 @@ DEFINE_USER32_CALLBACK(USER32_CALLBACK_LOADMENU, 6, User32CallLoa DEFINE_USER32_CALLBACK(USER32_CALLBACK_CLIENTTHREADSTARTUP, 7, User32CallClientThreadSetupFromKernel) DEFINE_USER32_CALLBACK(USER32_CALLBACK_CLIENTLOADLIBRARY, 8, User32CallClientLoadLibraryFromKernel) DEFINE_USER32_CALLBACK(USER32_CALLBACK_GETCHARSETINFO, 9, User32CallGetCharsetInfo) -DEFINE_USER32_CALLBACK(USER32_CALLBACK_COPYIMAGE, 10, User32CallCopyImageFromKernel) -DEFINE_USER32_CALLBACK(USER32_CALLBACK_SETWNDICONS, 11, User32CallSetWndIconsFromKernel) -DEFINE_USER32_CALLBACK(USER32_CALLBACK_DELIVERUSERAPC, 12, User32DeliverUserAPC) -DEFINE_USER32_CALLBACK(USER32_CALLBACK_DDEPOST, 13, User32CallDDEPostFromKernel) -DEFINE_USER32_CALLBACK(USER32_CALLBACK_DDEGET, 14, User32CallDDEGetFromKernel) -DEFINE_USER32_CALLBACK(USER32_CALLBACK_SETOBM, 15, User32CallOBMFromKernel) -DEFINE_USER32_CALLBACK(USER32_CALLBACK_LPK, 16, User32CallLPKFromKernel) -DEFINE_USER32_CALLBACK(USER32_CALLBACK_UMPD, 17, User32CallUMPDFromKernel) -DEFINE_USER32_CALLBACK(USER32_CALLBACK_IMMPROCESSKEY, 18, User32CallImmProcessKeyFromKernel) -DEFINE_USER32_CALLBACK(USER32_CALLBACK_IMMLOADLAYOUT, 19, User32CallImmLoadLayoutFromKernel) +DEFINE_USER32_CALLBACK(USER32_CALLBACK_LOADIMAGE, 10, User32CallLoadImageFromKernel) +DEFINE_USER32_CALLBACK(USER32_CALLBACK_COPYIMAGE, 11, User32CallCopyImageFromKernel) +DEFINE_USER32_CALLBACK(USER32_CALLBACK_SETWNDICONS, 12, User32CallSetWndIconsFromKernel) +DEFINE_USER32_CALLBACK(USER32_CALLBACK_DELIVERUSERAPC, 13, User32DeliverUserAPC) +DEFINE_USER32_CALLBACK(USER32_CALLBACK_DDEPOST, 14, User32CallDDEPostFromKernel) +DEFINE_USER32_CALLBACK(USER32_CALLBACK_DDEGET, 15, User32CallDDEGetFromKernel) +DEFINE_USER32_CALLBACK(USER32_CALLBACK_SETOBM, 16, User32CallOBMFromKernel) +DEFINE_USER32_CALLBACK(USER32_CALLBACK_LPK, 17, User32CallLPKFromKernel) +DEFINE_USER32_CALLBACK(USER32_CALLBACK_UMPD, 18, User32CallUMPDFromKernel) +DEFINE_USER32_CALLBACK(USER32_CALLBACK_IMMPROCESSKEY, 19, User32CallImmProcessKeyFromKernel) +DEFINE_USER32_CALLBACK(USER32_CALLBACK_IMMLOADLAYOUT, 20, User32CallImmLoadLayoutFromKernel) diff --git a/win32ss/user/ntuser/callback.c b/win32ss/user/ntuser/callback.c index 801e8e971db..0fa9b1e23a6 100644 --- a/win32ss/user/ntuser/callback.c +++ b/win32ss/user/ntuser/callback.c @@ -465,27 +465,33 @@ co_IntLoadSysMenuTemplate(VOID) return (HMENU)Result; } -extern HCURSOR gDesktopCursor; - BOOL APIENTRY co_IntLoadDefaultCursors(VOID) { NTSTATUS Status; - PVOID ResultPointer; - ULONG ResultLength; - BOOL DefaultCursor = TRUE; + PVOID Argument, ResultPointer; + ULONG ArgumentLength, ResultLength; + PLOADCURSORS_CALLBACK_ARGUMENTS Common; /* Do not allow the desktop thread to do callback to user mode */ ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); ResultPointer = NULL; - ResultLength = sizeof(HCURSOR); + ResultLength = ArgumentLength = sizeof(LOADCURSORS_CALLBACK_ARGUMENTS); + + Argument = IntCbAllocateMemory(ArgumentLength); + if (!Argument) + { + ERR("Load Default Cursors callback failed: out of memory\n"); + return FALSE; + } + Common = (PLOADCURSORS_CALLBACK_ARGUMENTS)Argument; UserLeaveCo(); Status = KeUserModeCallback(USER32_CALLBACK_LOADDEFAULTCURSORS, - &DefaultCursor, - sizeof(BOOL), + Argument, + ArgumentLength, &ResultPointer, &ResultLength); @@ -493,11 +499,31 @@ co_IntLoadDefaultCursors(VOID) if (!NT_SUCCESS(Status)) { + ERR("Load Default Cursors callback failed!\n"); + IntCbFreeMemory(Argument); return FALSE; } - /* HACK: The desktop class doen't have a proper cursor yet, so set it here */ - gDesktopCursor = *((HCURSOR*)ResultPointer); + RtlMoveMemory(Common, ResultPointer, ArgumentLength); + + IntLoadSystemCursors(Common->hCursorArrow, OCR_NORMAL); + IntLoadSystemCursors(Common->hCursorIbeam, OCR_IBEAM); + IntLoadSystemCursors(Common->hCursorWait, OCR_WAIT); + IntLoadSystemCursors(Common->hCursorCross, OCR_CROSS); + IntLoadSystemCursors(Common->hCursorUp, OCR_UP); + IntLoadSystemCursors(Common->hCursorIcon, OCR_ICON); + IntLoadSystemCursors(Common->hCursorSize, OCR_SIZE); + IntLoadSystemCursors(Common->hCursorSizeAll, OCR_SIZEALL); + IntLoadSystemCursors(Common->hCursorSizeNwse, OCR_SIZENWSE); + IntLoadSystemCursors(Common->hCursorSizeNesw, OCR_SIZENESW); + IntLoadSystemCursors(Common->hCursorSizeWe, OCR_SIZEWE); + IntLoadSystemCursors(Common->hCursorSizeNs, OCR_SIZENS); + IntLoadSystemCursors(Common->hCursorNo, OCR_NO); + IntLoadSystemCursors(Common->hCursorHand, OCR_HAND); + IntLoadSystemCursors(Common->hCursorAppStarting, OCR_APPSTARTING); + IntLoadSystemCursors(Common->hCursorHelp, OCR_HELP); + + IntCbFreeMemory(Argument); return TRUE; } @@ -981,6 +1007,61 @@ co_IntClientThreadSetup(VOID) return Status; } +HANDLE FASTCALL +co_IntLoadImage(LPCWSTR name, UINT type, INT desiredx, INT desiredy, UINT flags) +{ + HANDLE Handle; + NTSTATUS Status; + ULONG ArgumentLength, ResultLength; + PVOID Argument, ResultPointer; + PLOADIMAGE_CALLBACK_ARGUMENTS Common; + + ArgumentLength = ResultLength = 0; + Argument = ResultPointer = NULL; + + ArgumentLength = sizeof(LOADIMAGE_CALLBACK_ARGUMENTS); + + Argument = IntCbAllocateMemory(ArgumentLength); + if (!Argument) + { + ERR("LoadImage callback failed: out of memory\n"); + return 0; + } + Common = (PLOADIMAGE_CALLBACK_ARGUMENTS) Argument; + + RtlStringCchCopyW(Common->ImageName, wcslen(name) + 1, name); + + Common->ImageType = type; + Common->cxDesired = desiredx; + Common->cyDesired = desiredy; + Common->fuFlags = flags; + + UserLeaveCo(); + + Status = KeUserModeCallback(USER32_CALLBACK_LOADIMAGE, + Argument, + ArgumentLength, + &ResultPointer, + &ResultLength); + + + UserEnterCo(); + + if (NT_SUCCESS(Status)) + { + Handle = *(HANDLE*)ResultPointer; + } + else + { + ERR("LoadImage callback failed\n"); + Handle = NULL; + } + + IntCbFreeMemory(Argument); + + return Handle; +} + HANDLE FASTCALL co_IntCopyImage(HANDLE hnd, UINT type, INT desiredx, INT desiredy, UINT flags) { @@ -1138,13 +1219,13 @@ co_IntSetWndIcons(VOID) gpsi->hIconSmWindows = Common->hIconSmWindows; gpsi->hIconWindows = Common->hIconWindows; - IntLoadSystenIcons(Common->hIconSample, OIC_SAMPLE); - IntLoadSystenIcons(Common->hIconHand, OIC_HAND); - IntLoadSystenIcons(Common->hIconQuestion, OIC_QUES); - IntLoadSystenIcons(Common->hIconBang, OIC_BANG); - IntLoadSystenIcons(Common->hIconNote, OIC_NOTE); - IntLoadSystenIcons(gpsi->hIconWindows, OIC_WINLOGO); - IntLoadSystenIcons(gpsi->hIconSmWindows, OIC_WINLOGO+1); + IntLoadSystemIcons(Common->hIconSample, OIC_SAMPLE); + IntLoadSystemIcons(Common->hIconHand, OIC_HAND); + IntLoadSystemIcons(Common->hIconQuestion, OIC_QUES); + IntLoadSystemIcons(Common->hIconBang, OIC_BANG); + IntLoadSystemIcons(Common->hIconNote, OIC_NOTE); + IntLoadSystemIcons(gpsi->hIconWindows, OIC_WINLOGO); + IntLoadSystemIcons(gpsi->hIconSmWindows, OIC_WINLOGO+1); ERR("hIconSmWindows %p hIconWindows %p \n",gpsi->hIconSmWindows,gpsi->hIconWindows); diff --git a/win32ss/user/ntuser/callback.h b/win32ss/user/ntuser/callback.h index dde7152a952..ba66fe9d5aa 100644 --- a/win32ss/user/ntuser/callback.h +++ b/win32ss/user/ntuser/callback.h @@ -70,6 +70,7 @@ BOOL APIENTRY co_IntGetCharsetInfo(LCID Locale, PCHARSETINFO pCs); +HANDLE FASTCALL co_IntLoadImage(LPCWSTR,UINT,INT,INT,UINT); HANDLE FASTCALL co_IntCopyImage(HANDLE,UINT,INT,INT,UINT); BOOL FASTCALL co_IntSetWndIcons(VOID); diff --git a/win32ss/user/ntuser/cursoricon.c b/win32ss/user/ntuser/cursoricon.c index f0fdbac223e..3fa5799d238 100644 --- a/win32ss/user/ntuser/cursoricon.c +++ b/win32ss/user/ntuser/cursoricon.c @@ -82,9 +82,17 @@ IntInsertCursorIntoList( { PPROCESSINFO ppi = pcur->head.ppi; PCURICON_OBJECT *ppcurHead; + + // This is hacked around to support this while at the initial system start up. + // Avoids leakages of cursor handles when using a custom *.ani cursor themes. + if (pcur->head.ppi == NULL) return; + NT_ASSERT((pcur->CURSORF_flags & (CURSORF_GLOBAL|CURSORF_LRSHARED)) != 0); NT_ASSERT((pcur->CURSORF_flags & CURSORF_LINKED) == 0); + /* Don't cache *.ani */ + if (pcur->CURSORF_flags & CURSORF_ACON) return; + /* Get the right list head */ ppcurHead = (pcur->CURSORF_flags & CURSORF_GLOBAL) ? &gcurFirst : &ppi->pCursorCache; @@ -107,10 +115,16 @@ IntRemoveCursorFromList( NT_ASSERT((pcur->CURSORF_flags & (CURSORF_GLOBAL|CURSORF_LRSHARED)) != 0); NT_ASSERT((pcur->CURSORF_flags & CURSORF_LINKED) != 0); + /* Don't cache *.ani */ + if (pcur->CURSORF_flags & CURSORF_ACON) return; + /* Get the right list head */ ppcurHead = (pcur->CURSORF_flags & CURSORF_GLOBAL) ? &gcurFirst : &ppi->pCursorCache; + // This is hacked around to support this while at the initial system start up. + if (pcur->head.ppi == NULL) return; + /* Loop all cursors in the cache */ for (ppcur = ppcurHead; (*ppcur) != NULL; @@ -134,7 +148,49 @@ IntRemoveCursorFromList( } VOID -IntLoadSystenIcons(HICON hcur, DWORD id) +IntLoadSystemCursors(HCURSOR hcur, DWORD id) +{ + PCURICON_OBJECT pcur; + int i; + PPROCESSINFO ppi; + + if (hcur) + { + pcur = UserGetCurIconObject(hcur); + if (!pcur) + { + EngSetLastError(ERROR_INVALID_CURSOR_HANDLE); + return; + } + + ppi = PsGetCurrentProcessWin32Process(); + + if (!(ppi->W32PF_flags & W32PF_CREATEDWINORDC)) + return; + + for (i = 0 ; i < 16; i++) + { + if (gasyscur[i].type == id) + { + gasyscur[i].handle = pcur; + pcur->CURSORF_flags |= CURSORF_GLOBAL; + pcur->CURSORF_flags &= ~CURSORF_LINKED; + + // + // The active switch between LR shared and Global public. + // This is hacked around to support this while at the initial system start up. + // + pcur->head.ppi = NULL; + + IntInsertCursorIntoList(pcur); + return; + } + } + } +} + +VOID +IntLoadSystemIcons(HICON hcur, DWORD id) { PCURICON_OBJECT pcur; int i; @@ -374,7 +430,8 @@ FreeCurIconObject( UserDereferenceObject(AniCurIcon->aspcur[i]); NT_VERIFY(IntDestroyCurIconObject(AniCurIcon->aspcur[i]) == TRUE); } - ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR); + if (AniCurIcon->aspcur) + ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR); } if (CurIcon->CURSORF_flags & CURSORF_LRSHARED) @@ -852,6 +909,47 @@ leave: return ret; } +PCURICON_OBJECT +UserFindExistingCursorIcon( + _In_ PCURICON_OBJECT CurIcon, + _In_ RTL_ATOM atomModName, + _In_ PUNICODE_STRING pustrRsrc, + _In_ FINDEXISTINGCURICONPARAM* param) +{ + for (; CurIcon; CurIcon = CurIcon->pcurNext) + { + /* Icon/cursor */ + if (param->bIcon != is_icon(CurIcon)) + { + continue; + } + /* See if module names match */ + if (atomModName == CurIcon->atomModName) + { + /* They do. Now see if this is the same resource */ + if (IS_INTRESOURCE(CurIcon->strName.Buffer) != IS_INTRESOURCE(pustrRsrc->Buffer)) + { + /* One is an INT resource and the other is not -> no match */ + continue; + } + + if (IS_INTRESOURCE(CurIcon->strName.Buffer)) + { + if (CurIcon->strName.Buffer == pustrRsrc->Buffer) + { + /* INT resources match */ + return CurIcon; + } + } + else if (RtlEqualUnicodeString(pustrRsrc, &CurIcon->strName, TRUE)) + { + /* Resource name strings match */ + return CurIcon; + } + } + } + return NULL; +} /* * @implemented @@ -900,82 +998,9 @@ NtUserFindExistingCursorIcon( } UserEnterShared(); - CurIcon = pProcInfo->pCursorCache; - while (CurIcon) - { - /* Icon/cursor */ - if (paramSafe.bIcon != is_icon(CurIcon)) - { - CurIcon = CurIcon->pcurNext; - continue; - } - /* See if module names match */ - if (atomModName == CurIcon->atomModName) - { - /* They do. Now see if this is the same resource */ - if (IS_INTRESOURCE(CurIcon->strName.Buffer) != IS_INTRESOURCE(ustrRsrcSafe.Buffer)) - { - /* One is an INT resource and the other is not -> no match */ - CurIcon = CurIcon->pcurNext; - continue; - } - - if (IS_INTRESOURCE(CurIcon->strName.Buffer)) - { - if (CurIcon->strName.Buffer == ustrRsrcSafe.Buffer) - { - /* INT resources match */ - break; - } - } - else if (RtlCompareUnicodeString(&ustrRsrcSafe, &CurIcon->strName, TRUE) == 0) - { - /* Resource name strings match */ - break; - } - } - CurIcon = CurIcon->pcurNext; - } - - /* Now search Global Cursors or Icons. */ - if (CurIcon == NULL) - { - CurIcon = gcurFirst; - while (CurIcon) - { - /* Icon/cursor */ - if (paramSafe.bIcon != is_icon(CurIcon)) - { - CurIcon = CurIcon->pcurNext; - continue; - } - /* See if module names match */ - if (atomModName == CurIcon->atomModName) - { - /* They do. Now see if this is the same resource */ - if (IS_INTRESOURCE(CurIcon->strName.Buffer) != IS_INTRESOURCE(ustrRsrcSafe.Buffer)) - { - /* One is an INT resource and the other is not -> no match */ - CurIcon = CurIcon->pcurNext; - continue; - } - if (IS_INTRESOURCE(CurIcon->strName.Buffer)) - { - if (CurIcon->strName.Buffer == ustrRsrcSafe.Buffer) - { - /* INT resources match */ - break; - } - } - else if (RtlCompareUnicodeString(&ustrRsrcSafe, &CurIcon->strName, TRUE) == 0) - { - /* Resource name strings match */ - break; - } - } - CurIcon = CurIcon->pcurNext; - } - } + CurIcon = UserFindExistingCursorIcon(pProcInfo->pCursorCache, atomModName, &ustrRsrcSafe, ¶mSafe); + if (!CurIcon) + CurIcon = UserFindExistingCursorIcon(gcurFirst, atomModName, &ustrRsrcSafe, ¶mSafe); if (CurIcon) Ret = UserHMGetHandle(CurIcon); UserLeave(); @@ -2202,9 +2227,8 @@ NtUserSetSystemCursor( HCURSOR hcur, DWORD id) { - PCURICON_OBJECT pcur, pcurOrig = NULL; + PCURICON_OBJECT pcur; int i; - PPROCESSINFO ppi; BOOL Ret = FALSE; UserEnterExclusive(); @@ -2222,31 +2246,34 @@ NtUserSetSystemCursor( goto Exit; } - ppi = PsGetCurrentProcessWin32Process(); - - for (i = 0 ; i < 16; i++) + for (i = 0; i < 16; i++) { if (gasyscur[i].type == id) { - pcurOrig = gasyscur[i].handle; + /* Check if cursor is already set */ + if (pcur == gasyscur[i].handle) + { + ERR("Cursor %p is already set\n", pcur); + Ret = TRUE; + break; + } - if (pcurOrig) break; + /* Copy the new cursor */ + gasyscur[i].handle = pcur; - if (ppi->W32PF_flags & W32PF_CREATEDWINORDC) - { - gasyscur[i].handle = pcur; - pcur->CURSORF_flags |= CURSORF_GLOBAL; - pcur->head.ppi = NULL; - IntInsertCursorIntoList(pcur); - Ret = TRUE; - } - break; + /* Set the new cursor */ + if (IntGetSysCursorInfo()->CurrentCursorObject == pcur) + { + ERR("Applying the new cursor %p...\n", pcur); + IntSystemSetCursor(pcur); + } + + /* Mark it as a global cursor */ + pcur->CURSORF_flags |= CURSORF_GLOBAL; + Ret = TRUE; + break; } } - if (pcurOrig) - { - FIXME("Need to copy cursor data or do something! pcurOrig %p new pcur %p\n",pcurOrig,pcur); - } } Exit: UserLeave(); diff --git a/win32ss/user/ntuser/cursoricon.h b/win32ss/user/ntuser/cursoricon.h index 01e276f5ec9..d70c9c044b2 100644 --- a/win32ss/user/ntuser/cursoricon.h +++ b/win32ss/user/ntuser/cursoricon.h @@ -129,7 +129,8 @@ extern SYSTEMCURICO gasyscur[]; #define SYSTEMCUR(func) (gasyscur[ROCR_ ## func].handle) #define SYSTEMICO(func) (gasysico[ROIC_ ## func].handle) -VOID IntLoadSystenIcons(HICON,DWORD); +VOID IntLoadSystemCursors(HCURSOR,DWORD); +VOID IntLoadSystemIcons(HICON,DWORD); BOOL InitCursorImpl(VOID); HANDLE IntCreateCurIconHandle(BOOLEAN Anim); diff --git a/win32ss/user/ntuser/defwnd.c b/win32ss/user/ntuser/defwnd.c index 368105afc42..a3a4772a982 100644 --- a/win32ss/user/ntuser/defwnd.c +++ b/win32ss/user/ntuser/defwnd.c @@ -356,6 +356,15 @@ DefWndHandleSetCursor(PWND pWnd, WPARAM wParam, LPARAM lParam) IntSystemSetCursor(SYSTEMCUR(SIZENESW)); return TRUE; } + case HTHELP: + { + if (pWnd->style & WS_MAXIMIZE) + { + break; + } + IntSystemSetCursor(SYSTEMCUR(HELP)); + return TRUE; + } } IntSystemSetCursor(SYSTEMCUR(ARROW)); return FALSE; diff --git a/win32ss/user/ntuser/desktop.c b/win32ss/user/ntuser/desktop.c index 645717a7b1f..88836ffcd90 100644 --- a/win32ss/user/ntuser/desktop.c +++ b/win32ss/user/ntuser/desktop.c @@ -52,7 +52,6 @@ DWORD gdwWinlogonSectionSize = 128; PDESKTOP gpdeskInputDesktop = NULL; HDC ScreenDeviceContext = NULL; PTHREADINFO gptiDesktopThread = NULL; -HCURSOR gDesktopCursor = NULL; PKEVENT gpDesktopThreadStartedEvent = NULL; /* OBJECT CALLBACKS **********************************************************/ @@ -1457,7 +1456,7 @@ DesktopWindowProc(PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lRe { PAINTSTRUCT Ps; ULONG Value; - //ERR("DesktopWindowProc\n"); + TRACE("DesktopWindowProc\n"); *lResult = 0; @@ -1502,25 +1501,6 @@ DesktopWindowProc(PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lRe 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; - } - - pcurNew->CURSORF_flags |= CURSORF_CURRENT; - pcurOld = UserSetCursor(pcurNew, FALSE); - if (pcurOld) - { - pcurOld->CURSORF_flags &= ~CURSORF_CURRENT; - UserDereferenceObject(pcurOld); - } - return TRUE; - } - case WM_WINDOWPOSCHANGING: { PWINDOWPOS pWindowPos = (PWINDOWPOS)lParam; @@ -1531,6 +1511,7 @@ DesktopWindowProc(PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lRe } break; } + default: TRACE("DWP calling IDWP Msg %d\n",Msg); //*lResult = IntDefWindowProc(Wnd, Msg, wParam, lParam, FALSE); diff --git a/win32ss/user/ntuser/msgqueue.c b/win32ss/user/ntuser/msgqueue.c index 3a8b60704ff..1959a34abf6 100644 --- a/win32ss/user/ntuser/msgqueue.c +++ b/win32ss/user/ntuser/msgqueue.c @@ -17,7 +17,8 @@ static PPAGED_LOOKASIDE_LIST pgMessageLookasideList; static PPAGED_LOOKASIDE_LIST pgSendMsgLookasideList; INT PostMsgCount = 0; INT SendMsgCount = 0; -PUSER_MESSAGE_QUEUE gpqCursor; +PUSER_MESSAGE_QUEUE gpqCursor = NULL; +PACON gAniCursor = NULL; ULONG_PTR gdwMouseMoveExtraInfo = 0; DWORD gdwMouseMoveTimeStamp = 0; LIST_ENTRY usmList; @@ -132,29 +133,41 @@ UserSetCursor( return NULL; } - if (NewCursor) + /* Change the cursor only when it isn't changed yet */ + if (NewCursor != IntGetSysCursorInfo()->CurrentCursorObject) { - /* Call GDI to set the new screen cursor */ - PCURICON_OBJECT CursorFrame = NewCursor; - if(NewCursor->CURSORF_flags & CURSORF_ACON) + if (NewCursor) { - FIXME("Should animate the cursor, using only the first frame now.\n"); - CursorFrame = ((PACON)NewCursor)->aspcur[0]; + PCURICON_OBJECT CursorFrame = NewCursor; + if (NewCursor->CURSORF_flags & CURSORF_ACON) + { + gAniCursor = (PACON)NewCursor; + IntSetTimer(pWnd, ID_EVENT_SYSTIMER_ANIMATECURSOR, ((PACON)NewCursor)->ajifRate[((PACON)NewCursor)->iicur] * 100 / 6, SystemTimerProc, TMRF_SYSTEM); + CursorFrame = ((PACON)NewCursor)->aspcur[((PACON)NewCursor)->aicur[((PACON)NewCursor)->iicur]]; + } + + /* Kill the timer if the cursor is not *.ani anymore */ + if (!(CursorFrame->CURSORF_flags & CURSORF_ACONFRAME)) + IntKillTimer(pWnd, ID_EVENT_SYSTIMER_ANIMATECURSOR, TRUE); + + /* Call GDI to set the new screen cursor */ + GreSetPointerShape(hdcScreen, + CursorFrame->hbmAlpha ? NULL : CursorFrame->hbmMask, + CursorFrame->hbmAlpha ? CursorFrame->hbmAlpha : CursorFrame->hbmColor, + CursorFrame->xHotspot, + CursorFrame->yHotspot, + gpsi->ptCursor.x, + gpsi->ptCursor.y, + NewCursor->CURSORF_flags & CURSORF_ACON ? + (SPS_ANIMATEUPDATE | (CursorFrame->hbmAlpha ? SPS_ALPHA : 0)) : + (CursorFrame->hbmAlpha ? SPS_ALPHA : 0)); + } + else /* Note: OldCursor != NewCursor so we have to hide cursor */ + { + /* Remove the cursor */ + GreMovePointer(hdcScreen, -1, -1); + TRACE("Removing pointer!\n"); } - GreSetPointerShape(hdcScreen, - CursorFrame->hbmAlpha ? NULL : NewCursor->hbmMask, - CursorFrame->hbmAlpha ? NewCursor->hbmAlpha : NewCursor->hbmColor, - CursorFrame->xHotspot, - CursorFrame->yHotspot, - gpsi->ptCursor.x, - gpsi->ptCursor.y, - CursorFrame->hbmAlpha ? SPS_ALPHA : 0); - } - else /* Note: OldCursor != NewCursor so we have to hide cursor */ - { - /* Remove the cursor */ - GreMovePointer(hdcScreen, -1, -1); - TRACE("Removing pointer!\n"); } IntGetSysCursorInfo()->CurrentCursorObject = NewCursor; } @@ -680,7 +693,8 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook MessageQueue->CursorObject->yHotspot, gpsi->ptCursor.x, gpsi->ptCursor.y, - MessageQueue->CursorObject->hbmAlpha ? SPS_ALPHA : 0); + MessageQueue->CursorObject->CURSORF_flags & CURSORF_ACON ? + SPS_ANIMATEUPDATE : (MessageQueue->CursorObject->hbmAlpha ? SPS_ALPHA : 0)); } else GreMovePointer(hdcScreen, Msg->pt.x, Msg->pt.y); diff --git a/win32ss/user/ntuser/nonclient.c b/win32ss/user/ntuser/nonclient.c index f3a0cdb8492..c0d8801a8f6 100644 --- a/win32ss/user/ntuser/nonclient.c +++ b/win32ss/user/ntuser/nonclient.c @@ -2128,6 +2128,13 @@ GetNCHitEx(PWND pWnd, POINT pt) rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE); if (pt.x > rcWindow.right) return HTMINBUTTON; } + + /* Check help button */ + if (ExStyle & WS_EX_CONTEXTHELP && !(ExStyle & WS_EX_TOOLWINDOW)) + { + rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE); + if (pt.x > rcWindow.right) return HTHELP; + } } return HTCAPTION; } diff --git a/win32ss/user/ntuser/sysparams.c b/win32ss/user/ntuser/sysparams.c index 95bfbe7ca78..ff15eecc84b 100644 --- a/win32ss/user/ntuser/sysparams.c +++ b/win32ss/user/ntuser/sysparams.c @@ -58,6 +58,23 @@ static const WCHAR* VAL_HOVERWIDTH = L"MouseHoverWidth"; static const WCHAR* VAL_HOVERHEIGHT = L"MouseHoverHeight"; static const WCHAR* VAL_SENSITIVITY = L"MouseSensitivity"; +static const WCHAR* KEY_CURSORS = L"Control Panel\\Cursors"; +static const WCHAR* VAL_APPSTARTING = L"AppStarting"; +static const WCHAR* VAL_ARROW = L"Arrow"; +static const WCHAR* VAL_CROSS = L"Crosshair"; +static const WCHAR* VAL_HAND = L"Hand"; +static const WCHAR* VAL_HELP = L"Help"; +static const WCHAR* VAL_IBEAM = L"IBeam"; +static const WCHAR* VAL_NO = L"No"; +//static const WCHAR* VAL_NWPEN = L"NWPen"; +static const WCHAR* VAL_SIZEALL = L"SizeAll"; +static const WCHAR* VAL_SIZENESW = L"SizeNESW"; +static const WCHAR* VAL_SIZENS = L"SizeNS"; +static const WCHAR* VAL_SIZENWSE = L"SizeNWSE"; +static const WCHAR* VAL_SIZEWE = L"SizeWE"; +static const WCHAR* VAL_UPARROW = L"UpArrow"; +static const WCHAR* VAL_WAIT = L"Wait"; + static const WCHAR* KEY_DESKTOP = L"Control Panel\\Desktop"; static const WCHAR* VAL_SCRTO = L"ScreenSaveTimeOut"; static const WCHAR* VAL_SCRNSV = L"SCRNSAVE.EXE"; @@ -130,6 +147,13 @@ SpiLoadInt(PCWSTR pwszKey, PCWSTR pwszValue, INT iValue) return _wtoi(awcBuffer); } +static +BOOL +SpiLoadString(PCWSTR pwszKey, PCWSTR pwszValue, LPWSTR pwszBuffer, ULONG cbSize) +{ + return RegReadUserSetting(pwszKey, pwszValue, REG_EXPAND_SZ, pwszBuffer, cbSize); +} + static DWORD SpiLoadUserPrefMask(DWORD dValue) @@ -163,6 +187,60 @@ SpiLoadMouse(PCWSTR pwszValue, INT iValue) return SpiLoadInt(KEY_MOUSE, pwszValue, iValue); } +static +BOOL +SpiLoadCursor(PCWSTR pwszValue, LPWSTR pwszBuffer, ULONG cbSize) +{ + return SpiLoadString(KEY_CURSORS, pwszValue, pwszBuffer, cbSize); +} + +static +VOID +SpiReloadSystemCursor(PCWSTR pwszValue, DWORD dwId) +{ + WCHAR wchCursorPath[MAX_PATH]; + HANDLE hCursor; + ULONG cbSize; + + cbSize = sizeof(wchCursorPath); + if (!SpiLoadCursor(pwszValue, wchCursorPath, cbSize)) + { + ERR("Failed to get cursor path from registry for %ls\n", pwszValue); + return; + } + hCursor = co_IntLoadImage(wchCursorPath, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE); + if (!hCursor) + { + ERR("Failed to load cursor %ls\n", wchCursorPath); + return; + } + if (!NtUserSetSystemCursor(hCursor, dwId)) + { + ERR("NtUserSetSystemCursor failed with error %d\n", EngGetLastError()); + return; + } +} + +static +VOID +SpiReloadAllSystemCursors(VOID) +{ + SpiReloadSystemCursor(VAL_ARROW, OCR_NORMAL); + SpiReloadSystemCursor(VAL_IBEAM, OCR_IBEAM); + SpiReloadSystemCursor(VAL_WAIT, OCR_WAIT); + SpiReloadSystemCursor(VAL_CROSS, OCR_CROSS); + SpiReloadSystemCursor(VAL_UPARROW, OCR_UP); + SpiReloadSystemCursor(VAL_SIZENWSE, OCR_SIZENWSE); + SpiReloadSystemCursor(VAL_SIZENESW, OCR_SIZENESW); + SpiReloadSystemCursor(VAL_SIZEWE, OCR_SIZEWE); + SpiReloadSystemCursor(VAL_SIZENS, OCR_SIZENS); + SpiReloadSystemCursor(VAL_SIZEALL, OCR_SIZEALL); + SpiReloadSystemCursor(VAL_NO, OCR_NO); + SpiReloadSystemCursor(VAL_HAND, OCR_HAND); + SpiReloadSystemCursor(VAL_APPSTARTING, OCR_APPSTARTING); + SpiReloadSystemCursor(VAL_HELP, OCR_HELP); +} + static INT SpiLoadMetric(PCWSTR pwszValue, INT iValue) @@ -348,6 +426,9 @@ SpiUpdatePerUserSystemParameters(VOID) /* Update SystemMetrics */ InitMetrics(); + /* Load system cursors from registry */ + SpiReloadAllSystemCursors(); + if (gbSpiInitialized && gpsi) { if (gspv.bKbdPref) gpsi->dwSRVIFlags |= SRVINFO_KBDPREF; @@ -1446,7 +1527,7 @@ SpiGetSet(UINT uiAction, UINT uiParam, PVOID pvParam, FLONG fl) return SpiSetBool(&gspv.bPwrOffActive, uiParam, KEY_DESKTOP, L"PowerOffActive", fl); case SPI_SETCURSORS: - ERR("SPI_SETCURSORS is unimplemented\n"); + SpiReloadAllSystemCursors(); break; case SPI_SETICONS: diff --git a/win32ss/user/ntuser/timer.c b/win32ss/user/ntuser/timer.c index 051cf07cc1e..db28742d644 100644 --- a/win32ss/user/ntuser/timer.c +++ b/win32ss/user/ntuser/timer.c @@ -28,6 +28,8 @@ static RTL_BITMAP WindowLessTimersBitMap; static PVOID WindowLessTimersBitMapBuffer; static ULONG HintIndex = HINTINDEX_BEGIN_VALUE; +extern PACON gAniCursor; + ERESOURCE TimerLock; #define IntLockWindowlessTimerBitmap() \ @@ -362,6 +364,23 @@ SystemTimerProc(HWND hwnd, } return; + case ID_EVENT_SYSTIMER_ANIMATECURSOR: + { + PACON pacon = gAniCursor; + PCURICON_OBJECT pcurFrame; + if (!pacon || !pacon->aspcur || !pacon->aicur || pacon->iicur < 0 || + !(pacon->CURSORF_flags & CURSORF_ACON)) + break; + pcurFrame = pacon->aspcur[pacon->aicur[pacon->iicur]]; + if (!pcurFrame || !(pcurFrame->CURSORF_flags & CURSORF_ACONFRAME)) + break; + IntSystemSetCursor(pcurFrame); + pacon->iicur += 1; + if (pacon->iicur >= pacon->cicur) + pacon->iicur = 0; + } + return; + default: ERR("System Timer Proc invalid id %u!\n", idEvent); break; diff --git a/win32ss/user/ntuser/timer.h b/win32ss/user/ntuser/timer.h index 8ca2fe8ebd0..7fed6d31287 100644 --- a/win32ss/user/ntuser/timer.h +++ b/win32ss/user/ntuser/timer.h @@ -25,6 +25,7 @@ typedef struct _TIMER #define TMRF_TIFROMWND 0x0040 #define ID_EVENT_SYSTIMER_MOUSEHOVER ID_TME_TIMER +#define ID_EVENT_SYSTIMER_ANIMATECURSOR (0xFFF9) #define ID_EVENT_SYSTIMER_FLASHWIN (0xFFF8) #define ID_EVENT_SYSTIMER_TRACKWIN (0xFFF7) #define ID_EVENT_SYSTIMER_ANIMATEDFADE (0xFFF6) diff --git a/win32ss/user/user32/misc/desktop.c b/win32ss/user/user32/misc/desktop.c index 862ff165034..8c3a0c5bc5d 100644 --- a/win32ss/user/user32/misc/desktop.c +++ b/win32ss/user/user32/misc/desktop.c @@ -63,9 +63,6 @@ DesktopWndProcW(HWND Wnd, break; } - case WM_SETCURSOR: - return (LRESULT)SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW)); - default: return DefWindowProcW(Wnd, Msg, wParam, lParam); } @@ -337,6 +334,9 @@ RealSystemParametersInfoA(UINT uiAction, return NtUserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); } +VOID +LoadSystemCursors(VOID); + BOOL WINAPI RealSystemParametersInfoW(UINT uiAction, UINT uiParam, diff --git a/win32ss/user/user32/misc/dllmain.c b/win32ss/user/user32/misc/dllmain.c index c3c8451985a..5f221e9dbea 100644 --- a/win32ss/user/user32/misc/dllmain.c +++ b/win32ss/user/user32/misc/dllmain.c @@ -212,6 +212,9 @@ PVOID apfnDispatch[USER32_CALLBACK_COUNT] = #undef DEFINE_USER32_CALLBACK +VOID +LoadSystemCursors(VOID); + VOID WINAPI GdiProcessSetup(VOID); @@ -306,6 +309,11 @@ ClientThreadSetupHelper(BOOL IsCallback) TRACE("Checkpoint (MenuInit)\n"); if (MenuInit()) { + /* Load system cursors */ + TRACE("Checkpoint (CursorsInit)\n"); + //if (gfServerProcess) // FIXME + LoadSystemCursors(); + TRACE("Checkpoint initialization done OK\n"); InitializeCriticalSection(&U32AccelCacheLock); LoadAppInitDlls(); diff --git a/win32ss/user/user32/windows/cursoricon.c b/win32ss/user/user32/windows/cursoricon.c index 53c98456e81..58925e8b6f8 100644 --- a/win32ss/user/user32/windows/cursoricon.c +++ b/win32ss/user/user32/windows/cursoricon.c @@ -16,30 +16,95 @@ WINE_DECLARE_DEBUG_CHANNEL(icon); #undef MAKEINTRESOURCE #define MAKEINTRESOURCE MAKEINTRESOURCEW +typedef struct +{ + LPCWSTR resource_name; + HANDLE cursor; + LPCWSTR registry_name; +} SYSTEMCURSOR; + +static SYSTEMCURSOR g_SysCursors[] = +{ + {IDC_ARROW, NULL, L"Arrow" }, + {IDC_IBEAM, NULL, L"IBeam" }, + {IDC_WAIT, NULL, L"Wait" }, + {IDC_CROSS, NULL, L"Crosshair" }, + {IDC_UPARROW, NULL, L"UpArrow" }, + {IDC_ICON, NULL, L"" }, + {IDC_SIZE, NULL, L"" }, + {IDC_SIZENWSE, NULL, L"SizeNWSE" }, + {IDC_SIZENESW, NULL, L"SizeNESW" }, + {IDC_SIZEWE, NULL, L"SizeWE" }, + {IDC_SIZENS, NULL, L"SizeNS" }, + {IDC_SIZEALL, NULL, L"SizeAll" }, + {IDC_NO, NULL, L"No" }, + {IDC_HAND, NULL, L"Hand" }, + {IDC_APPSTARTING,NULL, L"AppStarting" }, + {IDC_HELP, NULL, L"Help" }, +}; + /************* USER32 INTERNAL FUNCTIONS **********/ -VOID LoadSystemCursors(VOID) +VOID +LoadSystemCursors(VOID) { - if (!gpsi->hIconSmWindows) - { - ERR("Loading System Cursors\n"); - NtUserSetSystemCursor(LoadImageW( 0, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_NORMAL); - NtUserSetSystemCursor(LoadImageW( 0, IDC_IBEAM, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_IBEAM); - NtUserSetSystemCursor(LoadImageW( 0, IDC_WAIT, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_WAIT); - NtUserSetSystemCursor(LoadImageW( 0, IDC_CROSS, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_CROSS); - NtUserSetSystemCursor(LoadImageW( 0, IDC_UPARROW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_UP); - NtUserSetSystemCursor(LoadImageW( 0, IDC_ICON, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_ICON); - NtUserSetSystemCursor(LoadImageW( 0, IDC_SIZE, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_SIZE); - NtUserSetSystemCursor(LoadImageW( 0, IDC_SIZENWSE, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_SIZENWSE); - NtUserSetSystemCursor(LoadImageW( 0, IDC_SIZENESW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_SIZENESW); - NtUserSetSystemCursor(LoadImageW( 0, IDC_SIZEWE, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_SIZEWE); - NtUserSetSystemCursor(LoadImageW( 0, IDC_SIZENS, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_SIZENS); - NtUserSetSystemCursor(LoadImageW( 0, IDC_SIZEALL, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_SIZEALL); - NtUserSetSystemCursor(LoadImageW( 0, IDC_NO, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_NO); - NtUserSetSystemCursor(LoadImageW( 0, IDC_HAND, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_HAND); - NtUserSetSystemCursor(LoadImageW( 0, IDC_APPSTARTING, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_APPSTARTING); - NtUserSetSystemCursor(LoadImageW( 0, IDC_HELP, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_HELP); - } + UINT i; + LSTATUS result; + HKEY hCursorsKey; + DWORD type, size = MAX_PATH * sizeof(WCHAR); + WCHAR szCursorPath[MAX_PATH], szExpanded[MAX_PATH]; + + for (i = 0; i < _countof(g_SysCursors); i++) + { + /* Try to load defaults first */ + g_SysCursors[i].cursor = LoadImageW(NULL, g_SysCursors[i].resource_name, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + TRACE("Cursor handle %p\n", g_SysCursors[i].cursor); + } + + result = RegOpenKeyExW(HKEY_CURRENT_USER, + L"Control Panel\\Cursors", + 0, + KEY_READ, + &hCursorsKey); + if (result == ERROR_SUCCESS) + { + for (i = 0; i < _countof(g_SysCursors); i++) + { + result = RegQueryValueExW(hCursorsKey, + g_SysCursors[i].registry_name, + NULL, + &type, + (LPBYTE)szCursorPath, + &size); + if (result == ERROR_SUCCESS && type == REG_EXPAND_SZ) + { + ExpandEnvironmentStringsW(szCursorPath, + szExpanded, + _countof(szExpanded)); + + g_SysCursors[i].cursor = LoadImageW(NULL, szExpanded, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE); + TRACE("Cursor name %S, cursor handle %p\n", g_SysCursors[i].registry_name, g_SysCursors[i].cursor); + } + } + RegCloseKey(hCursorsKey); + } +} + +HANDLE +GetSystemCursor( + _In_ LPCWSTR lpCursorName) +{ + UINT i; + for (i = 0; i < _countof(g_SysCursors); i++) + { + if (lpCursorName == g_SysCursors[i].resource_name) + { + TRACE("Match!!\n"); + return g_SysCursors[i].cursor; + } + } + TRACE("Not found :(\n"); + return NULL; } /* This callback routine is called directly after switching to gui mode */ @@ -48,27 +113,28 @@ WINAPI User32SetupDefaultCursors(PVOID Arguments, ULONG ArgumentLength) { - BOOL *DefaultCursor = (BOOL*)Arguments; - HCURSOR hCursor; + PLOADCURSORS_CALLBACK_ARGUMENTS Common = Arguments; - /* Load system cursors first */ - LoadSystemCursors(); + ERR("Loading System Cursors\n"); - if(*DefaultCursor) - { - /* set default cursor */ - hCursor = LoadCursorW(0, IDC_ARROW); - SetCursor(hCursor); - } - else - { - /* FIXME load system cursor scheme */ - SetCursor(0); - hCursor = LoadCursorW(0, IDC_ARROW); - SetCursor(hCursor); - } + Common->hCursorArrow = LoadImageW(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorIbeam = LoadImageW(NULL, IDC_IBEAM, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorWait = LoadImageW(NULL, IDC_WAIT, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorCross = LoadImageW(NULL, IDC_CROSS, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorUp = LoadImageW(NULL, IDC_UPARROW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorIcon = LoadImageW(NULL, IDC_ICON, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorSize = LoadImageW(NULL, IDC_SIZE, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorSizeNwse = LoadImageW(NULL, IDC_SIZENWSE, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorSizeNesw = LoadImageW(NULL, IDC_SIZENESW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorSizeWe = LoadImageW(NULL, IDC_SIZEWE, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorSizeNs = LoadImageW(NULL, IDC_SIZENS, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorSizeAll = LoadImageW(NULL, IDC_SIZEALL, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorNo = LoadImageW(NULL, IDC_NO, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorHand = LoadImageW(NULL, IDC_HAND, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorAppStarting = LoadImageW(NULL, IDC_APPSTARTING, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + Common->hCursorHelp = LoadImageW(NULL, IDC_HELP, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); - return(ZwCallbackReturn(&hCursor, sizeof(HCURSOR), STATUS_SUCCESS)); + return ZwCallbackReturn(Arguments, ArgumentLength, STATUS_SUCCESS); } BOOL get_icon_size(HICON hIcon, SIZE *size) @@ -1009,6 +1075,8 @@ static BOOL CURSORICON_GetCursorDataFromANI( else pFrameData = pCurData; + pFrameData->cx = pCurData->cx; + pFrameData->cy = pCurData->cy; pFrameData->rt = pCurData->rt; if (pHeader->flags & ANI_FLAG_ICON) @@ -1035,8 +1103,8 @@ static BOOL CURSORICON_GetCursorDataFromANI( } else { - pFrameData->cx = pHeader->width; - pFrameData->cy = pHeader->height; + if (!pFrameData->cx) pFrameData->cx = pHeader->width; + if (!pFrameData->cy) pFrameData->cy = pHeader->height; } pbmi = (const BITMAPINFO *) (icon_data + pDirEntry->dwDIBOffset); } @@ -1372,7 +1440,6 @@ end: return hbmpRet; } - static HANDLE CURSORICON_LoadFromFileW( @@ -1387,6 +1454,7 @@ CURSORICON_LoadFromFileW( const CURSORICONFILEDIR *dir; DWORD filesize = 0; LPBYTE bits; + BOOL isAnimated = FALSE; HANDLE hCurIcon = NULL; CURSORDATA cursorData; @@ -1396,11 +1464,23 @@ CURSORICON_LoadFromFileW( if (!bits) return NULL; + /* A bit of preparation */ + ZeroMemory(&cursorData, sizeof(cursorData)); + cursorData.cx = cxDesired; + cursorData.cy = cyDesired; + cursorData.rt = (USHORT)((ULONG_PTR)(bIcon ? RT_ICON : RT_CURSOR)); + /* Check for .ani. */ if (memcmp( bits, "RIFF", 4 ) == 0) { - UNIMPLEMENTED; - goto end; + if (!CURSORICON_GetCursorDataFromANI(&cursorData, bits, filesize, fuLoad)) + { + ERR("Failing File is \n '%S'.\n", lpszName); + goto end; + } + cursorData.CURSORF_flags = (CURSORF_FROMRESOURCE | CURSORF_LRSHARED | CURSORF_ACON); + isAnimated = TRUE; + goto create; } dir = (CURSORICONFILEDIR*) bits; @@ -1409,25 +1489,24 @@ CURSORICON_LoadFromFileW( goto end; /* Fix dimensions */ - if(!cxDesired) cxDesired = entry->bWidth; - if(!cyDesired) cyDesired = entry->bHeight; - /* A bit of preparation */ - ZeroMemory(&cursorData, sizeof(cursorData)); + if(!cursorData.cx) cursorData.cx = entry->bWidth; + if(!cursorData.cy) cursorData.cy = entry->bHeight; + if(!bIcon) { cursorData.xHotspot = entry->xHotspot; cursorData.yHotspot = entry->yHotspot; } - cursorData.rt = (USHORT)((ULONG_PTR)(bIcon ? RT_ICON : RT_CURSOR)); /* Do the dance */ if(!CURSORICON_GetCursorDataFromBMI(&cursorData, (BITMAPINFO*)(&bits[entry->dwDIBOffset]))) - { - ERR("Failing File is \n '%S'.\n", lpszName); - goto end; - } + { + ERR("Failing File is \n '%S'.\n", lpszName); + goto end; + } - hCurIcon = NtUserxCreateEmptyCurObject(FALSE); +create: + hCurIcon = NtUserxCreateEmptyCurObject(isAnimated); if(!hCurIcon) goto end; @@ -2144,14 +2223,20 @@ HCURSOR WINAPI LoadCursorA( _In_ LPCSTR lpCursorName ) { + HCURSOR hCursor; + TRACE("%p, %s\n", hInstance, debugstr_a(lpCursorName)); - return LoadImageA(hInstance, + //// HACK to properly apply the user-defined cursors on user-mode side + hCursor = GetSystemCursor((LPCWSTR)lpCursorName); + if (!hCursor)//// End of HACK + hCursor = LoadImageA(hInstance, lpCursorName, IMAGE_CURSOR, 0, 0, - LR_SHARED | LR_DEFAULTSIZE ); + LR_SHARED | LR_DEFAULTSIZE); + return hCursor; } HCURSOR WINAPI LoadCursorW( @@ -2159,14 +2244,20 @@ HCURSOR WINAPI LoadCursorW( _In_ LPCWSTR lpCursorName ) { + HCURSOR hCursor; + TRACE("%p, %s\n", hInstance, debugstr_w(lpCursorName)); - return LoadImageW(hInstance, + //// HACK to properly apply the user-defined cursors on user-mode side + hCursor = GetSystemCursor(lpCursorName); + if (!hCursor)//// End of HACK + hCursor = LoadImageW(hInstance, lpCursorName, IMAGE_CURSOR, 0, 0, - LR_SHARED | LR_DEFAULTSIZE ); + LR_SHARED | LR_DEFAULTSIZE); + return hCursor; } HCURSOR WINAPI LoadCursorFromFileA( @@ -2278,6 +2369,36 @@ HANDLE WINAPI LoadImageW( return NULL; } +NTSTATUS WINAPI +User32CallLoadImageFromKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PLOADIMAGE_CALLBACK_ARGUMENTS Common; + HANDLE Result; + DWORD Ret; + WCHAR ExpandedFilePath[MAX_PATH]; + Common = (PLOADIMAGE_CALLBACK_ARGUMENTS) Arguments; + + TRACE("User32CallLoadImageFromKernel called\n"); + + Ret = ExpandEnvironmentStringsW(Common->ImageName, + ExpandedFilePath, + _countof(ExpandedFilePath)); + if (!Ret) + { + ERR("ExpandEnvironmentStringsW failed with error %d\n", GetLastError()); + return ZwCallbackReturn(NULL, 0, STATUS_UNSUCCESSFUL); + } + + Result = LoadImageW(NULL, + ExpandedFilePath, + Common->ImageType, + Common->cxDesired, + Common->cyDesired, + Common->fuFlags); + + return ZwCallbackReturn(&Result, sizeof(HANDLE), STATUS_SUCCESS); +} + int WINAPI LookupIconIdFromDirectory( _In_ PBYTE presbits, _In_ BOOL fIcon diff --git a/win32ss/user/user32/windows/dialog.c b/win32ss/user/user32/windows/dialog.c index 784b43b9493..858a03e7a73 100644 --- a/win32ss/user/user32/windows/dialog.c +++ b/win32ss/user/user32/windows/dialog.c @@ -842,6 +842,8 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate, template.style |= DS_3DLOOK; if (template.style & DS_MODALFRAME) template.exStyle |= WS_EX_DLGMODALFRAME; + if (template.style & DS_CONTEXTHELP) + template.exStyle |= WS_EX_CONTEXTHELP; if ((template.style & DS_CONTROL) || !(template.style & WS_CHILD)) template.exStyle |= WS_EX_CONTROLPARENT; AdjustWindowRectEx( &rect, template.style, (hMenu != 0), template.exStyle );