- Implement LookupIconIdFromDirectoryEx.
- Implement CopyImage
- Finish Implementing LoadImage
- Implement various functions.
[WIN32SS]
- Add a first working implementation for LR_SHARED cursors and icons.User32 support is there, but more work is needed in win32k.

svn path=/trunk/; revision=57672
This commit is contained in:
Jérôme Gardou 2012-11-04 12:56:44 +00:00
parent db13cd87ac
commit 4a467211be
10 changed files with 1495 additions and 390 deletions

View file

@ -11,6 +11,10 @@ if(USE_DIBLIB)
add_subdirectory(gdi/diblib) add_subdirectory(gdi/diblib)
endif() endif()
if(USE_NEW_CURSORICON)
add_definitions(-DNEW_CURSORICON)
endif()
add_subdirectory(gdi/gdi32) add_subdirectory(gdi/gdi32)
add_subdirectory(reactx) add_subdirectory(reactx)
add_subdirectory(user/user32) add_subdirectory(user/user32)
@ -190,7 +194,6 @@ else()
endif() endif()
if(USE_NEW_CURSORICON) if(USE_NEW_CURSORICON)
add_definitions(-DNEW_CURSORICON)
list(APPEND SOURCE user/ntuser/cursoricon_new.c) list(APPEND SOURCE user/ntuser/cursoricon_new.c)
else() else()
list(APPEND SOURCE user/ntuser/cursoricon.c) list(APPEND SOURCE user/ntuser/cursoricon.c)

View file

@ -1659,8 +1659,8 @@ NtUserDestroyAcceleratorTable(
BOOL BOOL
NTAPI NTAPI
NtUserDestroyCursor( NtUserDestroyCursor(
HANDLE Handle, _In_ HANDLE Handle,
DWORD Unknown); _In_ BOOL bForce);
DWORD DWORD
NTAPI NTAPI
@ -1818,14 +1818,6 @@ NtUserFillWindow(
HDC hDC, HDC hDC,
HBRUSH hBrush); HBRUSH hBrush);
HICON
NTAPI
NtUserFindExistingCursorIcon(
HMODULE hModule,
HRSRC hRsrc,
LONG cx,
LONG cy);
HWND HWND
NTAPI NTAPI
NtUserFindWindowEx( NtUserFindWindowEx(
@ -1998,12 +1990,12 @@ NtUserGetGUIThreadInfo(
BOOL BOOL
NTAPI NTAPI
NtUserGetIconInfo( NtUserGetIconInfo(
HANDLE hCurIcon, _In_ HANDLE hCurIcon,
PICONINFO IconInfo, _Out_opt_ PICONINFO IconInfo,
PUNICODE_STRING lpInstName, _Out_opt_ PUNICODE_STRING lpInstName,
PUNICODE_STRING lpResName, _Out_opt_ PUNICODE_STRING lpResName,
LPDWORD pbpp, _Out_opt_ LPDWORD pbpp,
BOOL bInternal); _In_ BOOL bInternal);
BOOL BOOL
NTAPI NTAPI
@ -2743,9 +2735,17 @@ BOOL
NTAPI NTAPI
NtUserSetCursorIconData( NtUserSetCursorIconData(
_In_ HCURSOR hCursor, _In_ HCURSOR hCursor,
_In_ HINSTANCE hinst, _In_ PUNICODE_STRING pustrModule,
_In_ HRSRC hrsrc, _In_ PUNICODE_STRING puSrcName,
_In_ PICONINFO pii); _In_ PICONINFO pii);
HICON
NTAPI
NtUserFindExistingCursorIcon(
_In_ PUNICODE_STRING pustrModule,
_In_ PUNICODE_STRING pustrRsrc,
_In_ LONG cxDesired,
_In_ LONG cyDesired);
#else #else
BOOL BOOL
NTAPI NTAPI
@ -2756,6 +2756,14 @@ NtUserSetCursorIconData(
HMODULE hModule, HMODULE hModule,
HRSRC hRsrc, HRSRC hRsrc,
HRSRC hGroupRsrc); HRSRC hGroupRsrc);
HICON
NTAPI
NtUserFindExistingCursorIcon(
HMODULE hModule,
HRSRC hRsrc,
LONG cx,
LONG cy);
#endif #endif
DWORD DWORD

View file

@ -88,8 +88,9 @@ typedef struct
typedef struct typedef struct
{ union { union
{ ICONRESDIR icon; {
CURSORDIR cursor; ICONRESDIR icon;
CURSORDIR cursor;
} ResInfo; } ResInfo;
WORD wPlanes; WORD wPlanes;
WORD wBitCount; WORD wBitCount;

View file

@ -124,7 +124,7 @@ LookupFnIdToiCls(int FnId, int *iCls )
_Must_inspect_result_ _Must_inspect_result_
NTSTATUS NTSTATUS
NTAPI NTAPI
CaptureUnicodeStringOrAtom( ProbeAndCaptureUnicodeStringOrAtom(
_Out_ PUNICODE_STRING pustrOut, _Out_ PUNICODE_STRING pustrOut,
__in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe) __in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe)
{ {
@ -2294,7 +2294,7 @@ NtUserUnregisterClass(
NTSTATUS Status; NTSTATUS Status;
BOOL Ret; BOOL Ret;
Status = CaptureUnicodeStringOrAtom(&SafeClassName, ClassNameOrAtom); Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassNameOrAtom);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ERR("Error capturing the class name\n"); ERR("Error capturing the class name\n");
@ -2346,7 +2346,7 @@ NtUserGetClassInfo(
} }
_SEH2_END; _SEH2_END;
Status = CaptureUnicodeStringOrAtom(&SafeClassName, ClassName); Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ERR("Error capturing the class name\n"); ERR("Error capturing the class name\n");
@ -2480,7 +2480,7 @@ NtUserGetWOWClass(
RTL_ATOM ClassAtom = 0; RTL_ATOM ClassAtom = 0;
NTSTATUS Status; NTSTATUS Status;
Status = CaptureUnicodeStringOrAtom(&SafeClassName, ClassName); Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ERR("Error capturing the class name\n"); ERR("Error capturing the class name\n");

View file

@ -59,4 +59,11 @@ IntCheckProcessDesktopClasses(IN PDESKTOP Desktop,
ULONG_PTR FASTCALL UserGetCPD(PVOID,GETCPD,ULONG_PTR); ULONG_PTR FASTCALL UserGetCPD(PVOID,GETCPD,ULONG_PTR);
_Must_inspect_result_
NTSTATUS
NTAPI
ProbeAndCaptureUnicodeStringOrAtom(
_Out_ PUNICODE_STRING pustrOut,
__in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe);
/* EOF */ /* EOF */

View file

@ -204,7 +204,7 @@ IntFindExistingCurIconObject(HMODULE hModule,
} }
PCURICON_OBJECT PCURICON_OBJECT
IntCreateCurIconHandle() IntCreateCurIconHandle(DWORD dwNumber)
{ {
PCURICON_OBJECT CurIcon; PCURICON_OBJECT CurIcon;
HANDLE hCurIcon; HANDLE hCurIcon;
@ -613,8 +613,8 @@ NtUserClipCursor(
BOOL BOOL
APIENTRY APIENTRY
NtUserDestroyCursor( NtUserDestroyCursor(
HANDLE hCurIcon, _In_ HANDLE hCurIcon,
DWORD Unknown) _In_ BOOL bForce)
{ {
PCURICON_OBJECT CurIcon; PCURICON_OBJECT CurIcon;
BOOL ret; BOOL ret;

View file

@ -22,8 +22,8 @@ typedef struct _CURICON_OBJECT
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
HANDLE Self; HANDLE Self;
LIST_ENTRY ProcessList; LIST_ENTRY ProcessList;
HMODULE hModule; UNICODE_STRING ustrModule;
HRSRC hRsrc; UNICODE_STRING ustrRsrc;
SIZE Size; SIZE Size;
BYTE Shadow; BYTE Shadow;
BOOL bIcon; BOOL bIcon;
@ -88,7 +88,7 @@ typedef struct _SYSTEM_CURSORINFO
} SYSTEM_CURSORINFO, *PSYSTEM_CURSORINFO; } SYSTEM_CURSORINFO, *PSYSTEM_CURSORINFO;
BOOL InitCursorImpl(VOID); BOOL InitCursorImpl(VOID);
PCURICON_OBJECT IntCreateCurIconHandle(VOID); PCURICON_OBJECT IntCreateCurIconHandle(DWORD dwNumber);
VOID FASTCALL IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process); VOID FASTCALL IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process);
BOOL UserDrawIconEx(HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxWidth, BOOL UserDrawIconEx(HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxWidth,

View file

@ -169,47 +169,59 @@ ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon)
return TRUE; return TRUE;
} }
PCURICON_OBJECT FASTCALL static
IntFindExistingCurIconObject(HMODULE hModule, PCURICON_OBJECT
HRSRC hRsrc, LONG cx, LONG cy) FASTCALL
IntFindExistingCurIconObject(
PUNICODE_STRING pustrModule,
PUNICODE_STRING pustrRsrc,
LONG cxDesired,
LONG cyDesired)
{ {
PCURICON_OBJECT CurIcon; PCURICON_OBJECT CurIcon;
LIST_FOR_EACH(CurIcon, &gCurIconList, CURICON_OBJECT, ListEntry) LIST_FOR_EACH(CurIcon, &gCurIconList, CURICON_OBJECT, ListEntry)
{ {
/* See if module names match */
// if (NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) // <- huh???? if(RtlCompareUnicodeString(pustrModule, &CurIcon->ustrModule, TRUE) == 0)
// UserReferenceObject( CurIcon);
// {
if ((CurIcon->hModule == hModule) && (CurIcon->hRsrc == hRsrc))
{ {
if (cx && ((cx != CurIcon->Size.cx) || (cy != CurIcon->Size.cy))) /* They do. Now see if this is the same resource */
if(IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer) && IS_INTRESOURCE(pustrRsrc->Buffer))
{ {
// UserDereferenceObject(CurIcon); if(CurIcon->ustrRsrc.Buffer != pustrRsrc->Buffer)
continue;
}
else if(IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer) || IS_INTRESOURCE(pustrRsrc->Buffer))
continue; continue;
} else if(RtlCompareUnicodeString(pustrRsrc, &CurIcon->ustrRsrc, TRUE) != 0)
if (! ReferenceCurIconByProcess(CurIcon)) continue;
if ((cxDesired == CurIcon->Size.cx) &&(cyDesired == CurIcon->Size.cy))
{ {
return NULL; if (! ReferenceCurIconByProcess(CurIcon))
{
return NULL;
}
return CurIcon;
} }
return CurIcon;
} }
// }
// UserDereferenceObject(CurIcon);
} }
return NULL; return NULL;
} }
PCURICON_OBJECT PCURICON_OBJECT
IntCreateCurIconHandle() IntCreateCurIconHandle(DWORD dwNumber)
{ {
PCURICON_OBJECT CurIcon; PCURICON_OBJECT CurIcon;
BOOLEAN bIcon = dwNumber == 0;
HANDLE hCurIcon; HANDLE hCurIcon;
CurIcon = UserCreateObject(gHandleTable, NULL, NULL, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT)); if(dwNumber == 0)
dwNumber = 1;
CurIcon = UserCreateObject(gHandleTable, NULL, NULL, &hCurIcon, otCursorIcon, FIELD_OFFSET(CURICON_OBJECT, aFrame[dwNumber]));
if (!CurIcon) if (!CurIcon)
{ {
@ -218,6 +230,7 @@ IntCreateCurIconHandle()
} }
CurIcon->Self = hCurIcon; CurIcon->Self = hCurIcon;
CurIcon->bIcon = bIcon;
InitializeListHead(&CurIcon->ProcessList); InitializeListHead(&CurIcon->ProcessList);
if (! ReferenceCurIconByProcess(CurIcon)) if (! ReferenceCurIconByProcess(CurIcon))
@ -234,7 +247,7 @@ IntCreateCurIconHandle()
} }
BOOLEAN FASTCALL BOOLEAN FASTCALL
IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi) IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi, BOOLEAN bForce)
{ {
PSYSTEM_CURSORINFO CurInfo; PSYSTEM_CURSORINFO CurInfo;
HBITMAP bmpMask, bmpColor, bmpAlpha; HBITMAP bmpMask, bmpColor, bmpAlpha;
@ -261,9 +274,19 @@ IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi)
{ {
/* This object doesn't belong to this process */ /* This object doesn't belong to this process */
EngSetLastError(ERROR_INVALID_HANDLE); EngSetLastError(ERROR_INVALID_HANDLE);
/* Caller expects us to dereference! */
UserDereferenceObject(CurIcon);
return FALSE; return FALSE;
} }
/* We found our process, but we're told to not destroy it in case it is shared */
if((CurIcon->ustrModule.Buffer != NULL) && !bForce)
{
/* Tests show this is a valid call */
UserDereferenceObject(CurIcon);
return TRUE;
}
ExFreeToPagedLookasideList(pgProcessLookasideList, Current); ExFreeToPagedLookasideList(pgProcessLookasideList, Current);
/* If there are still processes referencing this object we can't destroy it yet */ /* If there are still processes referencing this object we can't destroy it yet */
@ -315,6 +338,11 @@ emptyList:
CurIcon->aFrame[0].hbmAlpha = NULL; CurIcon->aFrame[0].hbmAlpha = NULL;
} }
if(!IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer))
ExFreePoolWithTag(CurIcon->ustrRsrc.Buffer, TAG_STRING);
if(CurIcon->ustrModule.Buffer)
ReleaseCapturedUnicodeString(&CurIcon->ustrModule, UserMode);
/* We were given a pointer, no need to keep the reference anylonger! */ /* We were given a pointer, no need to keep the reference anylonger! */
UserDereferenceObject(CurIcon); UserDereferenceObject(CurIcon);
Ret = UserDeleteObject(CurIcon->Self, otCursorIcon); Ret = UserDeleteObject(CurIcon->Self, otCursorIcon);
@ -331,7 +359,7 @@ IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry) LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry)
{ {
UserReferenceObject(CurIcon); UserReferenceObject(CurIcon);
IntDestroyCurIconObject(CurIcon, Win32Process); IntDestroyCurIconObject(CurIcon, Win32Process, TRUE);
} }
} }
@ -342,12 +370,12 @@ IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
BOOL BOOL
APIENTRY APIENTRY
NtUserGetIconInfo( NtUserGetIconInfo(
HANDLE hCurIcon, _In_ HANDLE hCurIcon,
PICONINFO IconInfo, _Out_opt_ PICONINFO IconInfo,
PUNICODE_STRING lpInstName, // Optional _Out_opt_ PUNICODE_STRING lpModule, // Optional
PUNICODE_STRING lpResName, // Optional _Out_opt_ PUNICODE_STRING lpResName, // Optional
LPDWORD pbpp, // Optional _Out_opt_ LPDWORD pbpp, // Optional
BOOL bInternal) _In_ BOOL bInternal)
{ {
ICONINFO ii; ICONINFO ii;
PCURICON_OBJECT CurIcon; PCURICON_OBJECT CurIcon;
@ -356,66 +384,145 @@ NtUserGetIconInfo(
DWORD colorBpp = 0; DWORD colorBpp = 0;
TRACE("Enter NtUserGetIconInfo\n"); TRACE("Enter NtUserGetIconInfo\n");
UserEnterExclusive();
if (!IconInfo) /* Check if something was actually asked */
if (!IconInfo && !lpModule && !lpResName)
{ {
WARN("Nothing to fill.\n");
EngSetLastError(ERROR_INVALID_PARAMETER); EngSetLastError(ERROR_INVALID_PARAMETER);
goto leave; return FALSE;
} }
UserEnterExclusive();
if (!(CurIcon = UserGetCurIconObject(hCurIcon))) if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
{ {
goto leave; WARN("UserGetIconObject(0x%08x) Failed.\n", hCurIcon);
UserLeave();
return FALSE;
} }
/* Fill data */ /* Give back the icon information */
ii.fIcon = CurIcon->bIcon; if(IconInfo)
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; /* Fill data */
ii.fIcon = CurIcon->bIcon;
ii.xHotspot = CurIcon->ptlHotspot.x;
ii.yHotspot = CurIcon->ptlHotspot.y;
psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor); /* Copy bitmaps */
if (psurfBmp) ii.hbmMask = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmMask);
{ GreSetObjectOwner(ii.hbmMask, GDI_OBJ_HMGR_POWNED);
colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat); ii.hbmColor = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmColor);
SURFACE_ShareUnlockSurface(psurfBmp); GreSetObjectOwner(ii.hbmColor, GDI_OBJ_HMGR_POWNED);
}
}
/* Copy fields */
_SEH2_TRY
{
ProbeForWrite(IconInfo, sizeof(ICONINFO), 1);
RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO));
if (pbpp) if (pbpp)
{ {
ProbeForWrite(pbpp, sizeof(DWORD), 1); PSURFACE psurfBmp;
*pbpp = colorBpp;
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
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
if (!NT_SUCCESS(Status))
{ {
Status = _SEH2_GetExceptionCode(); WARN("Status: 0x%08x.\n", Status);
}
_SEH2_END
if (NT_SUCCESS(Status))
Ret = TRUE;
else
SetLastNtError(Status); SetLastNtError(Status);
goto leave;
}
UserDereferenceObject(CurIcon); /* Give back the module name */
if(lpModule)
{
if(!CurIcon->ustrModule.Buffer)
{
EngSetLastError(ERROR_INVALID_HANDLE);
goto leave;
}
/* Copy what we can */
_SEH2_TRY
{
ProbeForWrite(lpModule, sizeof(UNICODE_STRING), 1);
ProbeForWrite(lpModule->Buffer, lpModule->MaximumLength, 1);
lpModule->Length = min(lpModule->MaximumLength, CurIcon->ustrModule.Length);
RtlCopyMemory(lpModule->Buffer, CurIcon->ustrModule.Buffer, lpModule->Length);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
}
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
goto leave;
}
if(lpResName)
{
if(!CurIcon->ustrRsrc.Buffer)
{
EngSetLastError(ERROR_INVALID_HANDLE);
goto leave;
}
/* Copy it */
_SEH2_TRY
{
ProbeForWrite(lpResName, sizeof(UNICODE_STRING), 1);
if(IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer))
{
lpResName->Buffer = CurIcon->ustrRsrc.Buffer;
lpResName->Length = 0;
}
else
{
lpResName->Length = min(lpResName->MaximumLength, CurIcon->ustrRsrc.Length);
RtlCopyMemory(lpResName->Buffer, CurIcon->ustrRsrc.Buffer, lpResName->Length);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
}
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
goto leave;
}
Ret = TRUE;
leave: leave:
UserDereferenceObject(CurIcon);
TRACE("Leave NtUserGetIconInfo, ret=%i\n", Ret); TRACE("Leave NtUserGetIconInfo, ret=%i\n", Ret);
UserLeave(); UserLeave();
@ -623,8 +730,8 @@ NtUserClipCursor(
BOOL BOOL
APIENTRY APIENTRY
NtUserDestroyCursor( NtUserDestroyCursor(
HANDLE hCurIcon, _In_ HANDLE hCurIcon,
DWORD Unknown) _In_ BOOL bForce)
{ {
PCURICON_OBJECT CurIcon; PCURICON_OBJECT CurIcon;
BOOL ret; BOOL ret;
@ -638,7 +745,7 @@ NtUserDestroyCursor(
RETURN(FALSE); RETURN(FALSE);
} }
ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process()); ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process(), bForce);
/* Note: IntDestroyCurIconObject will remove our reference for us! */ /* Note: IntDestroyCurIconObject will remove our reference for us! */
RETURN(ret); RETURN(ret);
@ -654,36 +761,40 @@ CLEANUP:
* @implemented * @implemented
*/ */
HICON HICON
APIENTRY NTAPI
NtUserFindExistingCursorIcon( NtUserFindExistingCursorIcon(
HMODULE hModule, _In_ PUNICODE_STRING pustrModule,
HRSRC hRsrc, _In_ PUNICODE_STRING pustrRsrc,
LONG cx, _In_ LONG cxDesired,
LONG cy) _In_ LONG cyDesired)
{ {
PCURICON_OBJECT CurIcon; PCURICON_OBJECT CurIcon;
HANDLE Ret = (HANDLE)0; HICON Ret = NULL;
DECLARE_RETURN(HICON); UNICODE_STRING ustrModuleSafe, ustrRsrcSafe;
NTSTATUS Status;
TRACE("Enter NtUserFindExistingCursorIcon\n"); TRACE("Enter NtUserFindExistingCursorIcon\n");
/* Capture resource name (it can be an INTRESOURCE == ATOM) */
Status = ProbeAndCaptureUnicodeStringOrAtom(&ustrRsrcSafe, pustrRsrc);
if(!NT_SUCCESS(Status))
return NULL;
Status = ProbeAndCaptureUnicodeString(&ustrModuleSafe, UserMode, pustrModule);
if(!NT_SUCCESS(Status))
goto done;
UserEnterExclusive(); UserEnterExclusive();
CurIcon = IntFindExistingCurIconObject(&ustrModuleSafe, &ustrRsrcSafe, cxDesired, cyDesired);
CurIcon = IntFindExistingCurIconObject(hModule, hRsrc, cx, cy);
if (CurIcon) if (CurIcon)
{
Ret = CurIcon->Self; 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(); UserLeave();
END_CLEANUP;
done:
if(!IS_INTRESOURCE(ustrRsrcSafe.Buffer))
ExFreePoolWithTag(ustrRsrcSafe.Buffer, TAG_STRING);
ReleaseCapturedUnicodeString(&ustrModuleSafe, UserMode);
return Ret;
} }
@ -920,12 +1031,6 @@ NtUserSetCursorContents(
done: done:
if(!Ret)
{
IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process());
CurIcon = NULL;
}
if (CurIcon) if (CurIcon)
{ {
UserDereferenceObject(CurIcon); UserDereferenceObject(CurIcon);
@ -942,33 +1047,35 @@ CLEANUP:
/* /*
* @implemented * @implemented
*/ */
#ifdef NEW_CURSORICON
BOOL BOOL
APIENTRY APIENTRY
NtUserSetCursorIconData( NtUserSetCursorIconData(
_In_ HCURSOR Handle, _In_ HCURSOR Handle,
_In_ HINSTANCE hinst, _In_opt_ PUNICODE_STRING pustrModule,
_In_ HRSRC hrsrc, _In_opt_ PUNICODE_STRING pustrRsrc,
_In_ PICONINFO pIconInfo) _In_ PICONINFO pIconInfo)
{ {
PCURICON_OBJECT CurIcon; PCURICON_OBJECT CurIcon;
PSURFACE psurfBmp; PSURFACE psurfBmp;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
BOOL Ret = FALSE; BOOL Ret = FALSE;
DECLARE_RETURN(BOOL);
ICONINFO ii; ICONINFO ii;
TRACE("Enter NtUserSetCursorIconData\n"); TRACE("Enter NtUserSetCursorIconData\n");
/* If a module name is provided, we need a resource name, and vice versa */
if((pustrModule && !pustrRsrc) || (!pustrModule && pustrRsrc))
return FALSE;
UserEnterExclusive(); UserEnterExclusive();
if (!(CurIcon = UserGetCurIconObject(Handle))) if (!(CurIcon = UserGetCurIconObject(Handle)))
{ {
RETURN(FALSE); UserLeave();
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
} }
CurIcon->hModule = hinst;
CurIcon->hRsrc =hrsrc;
_SEH2_TRY _SEH2_TRY
{ {
ProbeForRead(pIconInfo, sizeof(ICONINFO), 1); ProbeForRead(pIconInfo, sizeof(ICONINFO), 1);
@ -1014,29 +1121,38 @@ NtUserSetCursorIconData(
if (CurIcon->aFrame[0].hbmColor) if (CurIcon->aFrame[0].hbmColor)
{ {
if ((psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor))) psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor);
{ if(!psurfBmp)
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; goto done;
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
SURFACE_ShareUnlockSurface(psurfBmp);
GreSetObjectOwner(CurIcon->aFrame[0].hbmColor, GDI_OBJ_HMGR_PUBLIC);
} }
else else
{ {
if ((psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmMask))) psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmMask);
{ if(!psurfBmp)
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy/2;
SURFACE_ShareUnlockSurface(psurfBmp);
}
else
goto done; goto done;
CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy/2;
SURFACE_ShareUnlockSurface(psurfBmp);
} }
GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC); GreSetObjectOwner(CurIcon->aFrame[0].hbmMask, GDI_OBJ_HMGR_PUBLIC);
if(pustrModule)
{
/* We use this convenient function, because INTRESOURCEs and ATOMs are the same */
Status = ProbeAndCaptureUnicodeStringOrAtom(&CurIcon->ustrRsrc, pustrRsrc);
if(!NT_SUCCESS(Status))
goto done;
Status = ProbeAndCaptureUnicodeString(&CurIcon->ustrModule, UserMode, pustrModule);
if(!NT_SUCCESS(Status))
goto done;
}
Ret = TRUE; Ret = TRUE;
done: done:
@ -1055,97 +1171,17 @@ done:
GreDeleteObject(CurIcon->aFrame[0].hbmColor); GreDeleteObject(CurIcon->aFrame[0].hbmColor);
CurIcon->aFrame[0].hbmColor = NULL; CurIcon->aFrame[0].hbmColor = NULL;
} }
if(!IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer))
ExFreePoolWithTag(CurIcon->ustrRsrc.Buffer, TAG_STRING);
if(CurIcon->ustrModule.Buffer)
ReleaseCapturedUnicodeString(&CurIcon->ustrModule, UserMode);
} }
RETURN(Ret);
CLEANUP: TRACE("Leave NtUserSetCursorIconData, ret=%i\n",Ret);
TRACE("Leave NtUserSetCursorIconData, ret=%i\n",_ret_);
UserLeave(); UserLeave();
END_CLEANUP;
return Ret;
} }
#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. /* Mostly inspired from wine code.
* We use low level functions because: * We use low level functions because:
@ -1167,7 +1203,7 @@ UserDrawIconEx(
HBRUSH hbrFlickerFreeDraw, HBRUSH hbrFlickerFreeDraw,
UINT diFlags) UINT diFlags)
{ {
PSURFACE psurfDest, psurfMask, psurfColor, psurfOffScreen; PSURFACE psurfDest, psurfMask, psurfColor; //, psurfOffScreen = NULL;
PDC pdc = NULL; PDC pdc = NULL;
BOOL Ret = FALSE; BOOL Ret = FALSE;
HBITMAP hbmMask, hbmColor, hbmAlpha; HBITMAP hbmMask, hbmColor, hbmAlpha;
@ -1215,6 +1251,35 @@ UserDrawIconEx(
return FALSE; return FALSE;
} }
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);
/* 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;
}
/* Set source rect */ /* Set source rect */
RECTL_vSetRect(&rcSrc, 0, 0, pIcon->Size.cx, pIcon->Size.cy); RECTL_vSetRect(&rcSrc, 0, 0, pIcon->Size.cx, pIcon->Size.cy);
@ -1239,7 +1304,8 @@ UserDrawIconEx(
} }
/* Should we render off-screen? */ /* Should we render off-screen? */
bOffScreen = hbrFlickerFreeDraw && (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH); bOffScreen = hbrFlickerFreeDraw &&
(GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH);
if (bOffScreen) if (bOffScreen)
{ {
@ -1252,21 +1318,18 @@ UserDrawIconEx(
if(!pbrush) if(!pbrush)
{ {
ERR("Failed to get brush object.\n"); ERR("Failed to get brush object.\n");
SURFACE_ShareUnlockSurface(psurfMask); goto Cleanup;
if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
return FALSE;
} }
#if 0 //We lock the hdc surface during the whole function it makes no sense to use an offscreen surface for "flicker free" drawing
psurfOffScreen = SURFACE_AllocSurface(STYPE_BITMAP, psurfOffScreen = SURFACE_AllocSurface(STYPE_BITMAP,
cxWidth, cyHeight, psurfColor->SurfObj.iBitmapFormat, cxWidth, cyHeight, psurfDest->SurfObj.iBitmapFormat,
0, 0, NULL); 0, 0, NULL);
if(!psurfOffScreen) if(!psurfOffScreen)
{ {
ERR("Failed to allocate the off-screen surface.\n"); ERR("Failed to allocate the off-screen surface.\n");
SURFACE_ShareUnlockSurface(psurfMask);
if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
BRUSH_ShareUnlockBrush(pbrush); BRUSH_ShareUnlockBrush(pbrush);
return FALSE; goto Cleanup;
} }
/* Paint the brush */ /* Paint the brush */
@ -1292,52 +1355,45 @@ UserDrawIconEx(
if(!Ret) if(!Ret)
{ {
ERR("Failed to paint the off-screen surface.\n"); ERR("Failed to paint the off-screen surface.\n");
SURFACE_ShareUnlockSurface(psurfMask); goto Cleanup;
if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject);
return FALSE;
} }
/* We now have our destination surface */ /* We now have our destination surface */
psurfDest = psurfOffScreen; psurfDest = psurfOffScreen;
#else
pdcClipObj = pdc->rosdc.CombinedClip;
/* Paint the brush */
EBRUSHOBJ_vInit(&eboFill, pbrush, psurfDest, 0x00FFFFFF, 0, NULL);
Ret = IntEngBitBlt(&psurfDest->SurfObj,
NULL,
NULL,
pdcClipObj,
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");
goto Cleanup;
}
#endif
} }
else else
{ {
/* We directly draw to the DC */ /* We directly draw to the DC */
TRACE("Performing on screen rendering.\n"); 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; pdcClipObj = pdc->rosdc.CombinedClip;
// psurfOffScreen = NULL;
/* 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 */ /* Now do the rendering */
@ -1460,36 +1516,23 @@ NoAlpha:
} }
done: done:
#if 0
/* We're done. Was it a double buffered draw ? */ /* We're done. Was it a double buffered draw ? */
if(bOffScreen) if(bOffScreen)
{ {
/* Yes. Draw it back to our DC */ /* Yes. Draw it back to our DC */
POINTL ptSrc = {0, 0}; POINTL ptSrc = {0, 0};
pdc = DC_LockDc(hDc);
if(!pdc)
{
ERR("Could not lock the destination DC.\n");
return FALSE;
}
/* Calculate destination rectangle */ /* Calculate destination rectangle */
RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight);
IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); IntLPtoDP(pdc, (LPPOINT)&rcDest, 2);
RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
/* Prepare the underlying surface */
DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest);
/* Get the clip object */ /* Get the clip object */
pdcClipObj = pdc->rosdc.CombinedClip; pdcClipObj = pdc->rosdc.CombinedClip;
/* We now have our destination surface and rectangle */ /* We now have our destination surface and rectangle */
psurfDest = pdc->dclevel.pSurface; psurfDest = pdc->dclevel.pSurface;
if(!psurfDest)
{
/* So, you did all of this for an empty DC. */
DC_UnlockDc(pdc);
goto Cleanup2;
}
/* Color translation */ /* Color translation */
EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0); EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0);
@ -1509,6 +1552,7 @@ done:
EXLATEOBJ_vCleanup(&exlo); EXLATEOBJ_vCleanup(&exlo);
} }
#endif
Cleanup: Cleanup:
if(pdc) if(pdc)
{ {
@ -1516,10 +1560,11 @@ Cleanup:
DC_UnlockDc(pdc); DC_UnlockDc(pdc);
} }
Cleanup2: #if 0
/* Delete off screen rendering surface */ /* Delete off screen rendering surface */
if(psurfOffScreen) if(psurfOffScreen)
GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject); GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject);
#endif
/* Unlock other surfaces */ /* Unlock other surfaces */
SURFACE_ShareUnlockSurface(psurfMask); SURFACE_ShareUnlockSurface(psurfMask);
@ -1554,7 +1599,7 @@ NtUserDrawIconEx(
if (!(pIcon = UserGetCurIconObject(hIcon))) if (!(pIcon = UserGetCurIconObject(hIcon)))
{ {
ERR("UserGetCurIconObject() failed!\n"); ERR("UserGetCurIconObject(0x%08x) failed!\n", hIcon);
UserLeave(); UserLeave();
return FALSE; return FALSE;
} }

View file

@ -248,7 +248,7 @@ NtUserCallOneParam(
PCURICON_OBJECT CurIcon; PCURICON_OBJECT CurIcon;
DWORD_PTR Result ; DWORD_PTR Result ;
if (!(CurIcon = IntCreateCurIconHandle())) if (!(CurIcon = IntCreateCurIconHandle((DWORD)Param)))
{ {
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
RETURN(0); RETURN(0);

File diff suppressed because it is too large Load diff