Author: jgardou
Date: Sun Nov 4 12:56:44 2012
New Revision: 57672
URL:
http://svn.reactos.org/svn/reactos?rev=57672&view=rev
Log:
[USER32]
- 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.
Modified:
trunk/reactos/win32ss/CMakeLists.txt
trunk/reactos/win32ss/include/ntuser.h
trunk/reactos/win32ss/include/ntusrtyp.h
trunk/reactos/win32ss/user/ntuser/class.c
trunk/reactos/win32ss/user/ntuser/class.h
trunk/reactos/win32ss/user/ntuser/cursoricon.c
trunk/reactos/win32ss/user/ntuser/cursoricon.h
trunk/reactos/win32ss/user/ntuser/cursoricon_new.c
trunk/reactos/win32ss/user/ntuser/simplecall.c
trunk/reactos/win32ss/user/user32/windows/cursoricon_new.c
Modified: trunk/reactos/win32ss/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/CMakeLists.txt?rev…
==============================================================================
--- trunk/reactos/win32ss/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/win32ss/CMakeLists.txt [iso-8859-1] Sun Nov 4 12:56:44 2012
@@ -9,6 +9,10 @@
if(USE_DIBLIB)
add_subdirectory(gdi/diblib)
+endif()
+
+if(USE_NEW_CURSORICON)
+ add_definitions(-DNEW_CURSORICON)
endif()
add_subdirectory(gdi/gdi32)
@@ -190,7 +194,6 @@
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)
Modified: trunk/reactos/win32ss/include/ntuser.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/include/ntuser.h?r…
==============================================================================
--- trunk/reactos/win32ss/include/ntuser.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/include/ntuser.h [iso-8859-1] Sun Nov 4 12:56:44 2012
@@ -1659,8 +1659,8 @@
BOOL
NTAPI
NtUserDestroyCursor(
- HANDLE Handle,
- DWORD Unknown);
+ _In_ HANDLE Handle,
+ _In_ BOOL bForce);
DWORD
NTAPI
@@ -1818,14 +1818,6 @@
HDC hDC,
HBRUSH hBrush);
-HICON
-NTAPI
-NtUserFindExistingCursorIcon(
- HMODULE hModule,
- HRSRC hRsrc,
- LONG cx,
- LONG cy);
-
HWND
NTAPI
NtUserFindWindowEx(
@@ -1998,12 +1990,12 @@
BOOL
NTAPI
NtUserGetIconInfo(
- HANDLE hCurIcon,
- PICONINFO IconInfo,
- PUNICODE_STRING lpInstName,
- PUNICODE_STRING lpResName,
- LPDWORD pbpp,
- BOOL bInternal);
+ _In_ HANDLE hCurIcon,
+ _Out_opt_ PICONINFO IconInfo,
+ _Out_opt_ PUNICODE_STRING lpInstName,
+ _Out_opt_ PUNICODE_STRING lpResName,
+ _Out_opt_ LPDWORD pbpp,
+ _In_ BOOL bInternal);
BOOL
NTAPI
@@ -2743,9 +2735,17 @@
NTAPI
NtUserSetCursorIconData(
_In_ HCURSOR hCursor,
- _In_ HINSTANCE hinst,
- _In_ HRSRC hrsrc,
+ _In_ PUNICODE_STRING pustrModule,
+ _In_ PUNICODE_STRING puSrcName,
_In_ PICONINFO pii);
+
+HICON
+NTAPI
+NtUserFindExistingCursorIcon(
+ _In_ PUNICODE_STRING pustrModule,
+ _In_ PUNICODE_STRING pustrRsrc,
+ _In_ LONG cxDesired,
+ _In_ LONG cyDesired);
#else
BOOL
NTAPI
@@ -2756,6 +2756,14 @@
HMODULE hModule,
HRSRC hRsrc,
HRSRC hGroupRsrc);
+
+HICON
+NTAPI
+NtUserFindExistingCursorIcon(
+ HMODULE hModule,
+ HRSRC hRsrc,
+ LONG cx,
+ LONG cy);
#endif
DWORD
Modified: trunk/reactos/win32ss/include/ntusrtyp.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/include/ntusrtyp.h…
==============================================================================
--- trunk/reactos/win32ss/include/ntusrtyp.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/include/ntusrtyp.h [iso-8859-1] Sun Nov 4 12:56:44 2012
@@ -88,8 +88,9 @@
typedef struct
{ union
- { ICONRESDIR icon;
- CURSORDIR cursor;
+ {
+ ICONRESDIR icon;
+ CURSORDIR cursor;
} ResInfo;
WORD wPlanes;
WORD wBitCount;
Modified: trunk/reactos/win32ss/user/ntuser/class.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/class.…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/class.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/class.c [iso-8859-1] Sun Nov 4 12:56:44 2012
@@ -124,7 +124,7 @@
_Must_inspect_result_
NTSTATUS
NTAPI
-CaptureUnicodeStringOrAtom(
+ProbeAndCaptureUnicodeStringOrAtom(
_Out_ PUNICODE_STRING pustrOut,
__in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe)
{
@@ -2294,7 +2294,7 @@
NTSTATUS Status;
BOOL Ret;
- Status = CaptureUnicodeStringOrAtom(&SafeClassName, ClassNameOrAtom);
+ Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassNameOrAtom);
if (!NT_SUCCESS(Status))
{
ERR("Error capturing the class name\n");
@@ -2346,7 +2346,7 @@
}
_SEH2_END;
- Status = CaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
+ Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
if (!NT_SUCCESS(Status))
{
ERR("Error capturing the class name\n");
@@ -2480,7 +2480,7 @@
RTL_ATOM ClassAtom = 0;
NTSTATUS Status;
- Status = CaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
+ Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
if (!NT_SUCCESS(Status))
{
ERR("Error capturing the class name\n");
Modified: trunk/reactos/win32ss/user/ntuser/class.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/class.…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/class.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/class.h [iso-8859-1] Sun Nov 4 12:56:44 2012
@@ -59,4 +59,11 @@
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 */
Modified: trunk/reactos/win32ss/user/ntuser/cursoricon.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/cursor…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/cursoricon.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/cursoricon.c [iso-8859-1] Sun Nov 4 12:56:44 2012
@@ -204,7 +204,7 @@
}
PCURICON_OBJECT
-IntCreateCurIconHandle()
+IntCreateCurIconHandle(DWORD dwNumber)
{
PCURICON_OBJECT CurIcon;
HANDLE hCurIcon;
@@ -613,8 +613,8 @@
BOOL
APIENTRY
NtUserDestroyCursor(
- HANDLE hCurIcon,
- DWORD Unknown)
+ _In_ HANDLE hCurIcon,
+ _In_ BOOL bForce)
{
PCURICON_OBJECT CurIcon;
BOOL ret;
Modified: trunk/reactos/win32ss/user/ntuser/cursoricon.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/cursor…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/cursoricon.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/cursoricon.h [iso-8859-1] Sun Nov 4 12:56:44 2012
@@ -22,8 +22,8 @@
LIST_ENTRY ListEntry;
HANDLE Self;
LIST_ENTRY ProcessList;
- HMODULE hModule;
- HRSRC hRsrc;
+ UNICODE_STRING ustrModule;
+ UNICODE_STRING ustrRsrc;
SIZE Size;
BYTE Shadow;
BOOL bIcon;
@@ -88,7 +88,7 @@
} SYSTEM_CURSORINFO, *PSYSTEM_CURSORINFO;
BOOL InitCursorImpl(VOID);
-PCURICON_OBJECT IntCreateCurIconHandle(VOID);
+PCURICON_OBJECT IntCreateCurIconHandle(DWORD dwNumber);
VOID FASTCALL IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process);
BOOL UserDrawIconEx(HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxWidth,
Modified: trunk/reactos/win32ss/user/ntuser/cursoricon_new.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/cursor…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/cursoricon_new.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/cursoricon_new.c [iso-8859-1] Sun Nov 4 12:56:44
2012
@@ -169,47 +169,59 @@
return TRUE;
}
-PCURICON_OBJECT FASTCALL
-IntFindExistingCurIconObject(HMODULE hModule,
- HRSRC hRsrc, LONG cx, LONG cy)
+static
+PCURICON_OBJECT
+FASTCALL
+IntFindExistingCurIconObject(
+ PUNICODE_STRING pustrModule,
+ PUNICODE_STRING pustrRsrc,
+ LONG cxDesired,
+ LONG cyDesired)
{
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)))
+ /* See if module names match */
+ if(RtlCompareUnicodeString(pustrModule, &CurIcon->ustrModule, TRUE) == 0)
+ {
+ /* 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;
+ else if(RtlCompareUnicodeString(pustrRsrc, &CurIcon->ustrRsrc, TRUE)
!= 0)
+ continue;
+
+ if ((cxDesired == CurIcon->Size.cx) &&(cyDesired ==
CurIcon->Size.cy))
+ {
+ if (! ReferenceCurIconByProcess(CurIcon))
+ {
+ return NULL;
+ }
+
+ return CurIcon;
}
- if (! ReferenceCurIconByProcess(CurIcon))
- {
- return NULL;
- }
-
- return CurIcon;
- }
-// }
-// UserDereferenceObject(CurIcon);
-
+ }
}
return NULL;
}
PCURICON_OBJECT
-IntCreateCurIconHandle()
+IntCreateCurIconHandle(DWORD dwNumber)
{
PCURICON_OBJECT CurIcon;
+ BOOLEAN bIcon = dwNumber == 0;
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)
{
@@ -218,6 +230,7 @@
}
CurIcon->Self = hCurIcon;
+ CurIcon->bIcon = bIcon;
InitializeListHead(&CurIcon->ProcessList);
if (! ReferenceCurIconByProcess(CurIcon))
@@ -234,7 +247,7 @@
}
BOOLEAN FASTCALL
-IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi)
+IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi, BOOLEAN bForce)
{
PSYSTEM_CURSORINFO CurInfo;
HBITMAP bmpMask, bmpColor, bmpAlpha;
@@ -261,7 +274,17 @@
{
/* This object doesn't belong to this process */
EngSetLastError(ERROR_INVALID_HANDLE);
+ /* Caller expects us to dereference! */
+ UserDereferenceObject(CurIcon);
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);
@@ -314,6 +337,11 @@
GreDeleteObject(bmpAlpha);
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! */
UserDereferenceObject(CurIcon);
@@ -331,7 +359,7 @@
LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry)
{
UserReferenceObject(CurIcon);
- IntDestroyCurIconObject(CurIcon, Win32Process);
+ IntDestroyCurIconObject(CurIcon, Win32Process, TRUE);
}
}
@@ -342,12 +370,12 @@
BOOL
APIENTRY
NtUserGetIconInfo(
- HANDLE hCurIcon,
- PICONINFO IconInfo,
- PUNICODE_STRING lpInstName, // Optional
- PUNICODE_STRING lpResName, // Optional
- LPDWORD pbpp, // Optional
- BOOL bInternal)
+ _In_ HANDLE hCurIcon,
+ _Out_opt_ PICONINFO IconInfo,
+ _Out_opt_ PUNICODE_STRING lpModule, // Optional
+ _Out_opt_ PUNICODE_STRING lpResName, // Optional
+ _Out_opt_ LPDWORD pbpp, // Optional
+ _In_ BOOL bInternal)
{
ICONINFO ii;
PCURICON_OBJECT CurIcon;
@@ -356,66 +384,145 @@
DWORD colorBpp = 0;
TRACE("Enter NtUserGetIconInfo\n");
+
+ /* Check if something was actually asked */
+ if (!IconInfo && !lpModule && !lpResName)
+ {
+ WARN("Nothing to fill.\n");
+ EngSetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
UserEnterExclusive();
- if (!IconInfo)
- {
- EngSetLastError(ERROR_INVALID_PARAMETER);
+ if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
+ {
+ WARN("UserGetIconObject(0x%08x) Failed.\n", hCurIcon);
+ UserLeave();
+ return FALSE;
+ }
+
+ /* Give back the icon information */
+ if(IconInfo)
+ {
+ /* 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);
+ GreSetObjectOwner(ii.hbmMask, GDI_OBJ_HMGR_POWNED);
+ ii.hbmColor = BITMAP_CopyBitmap(CurIcon->aFrame[0].hbmColor);
+ GreSetObjectOwner(ii.hbmColor, GDI_OBJ_HMGR_POWNED);
+
+ 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))
+ {
+ WARN("Status: 0x%08x.\n", Status);
+ SetLastNtError(Status);
goto leave;
}
- if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
- {
+ /* 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;
}
- /* 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
+ 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:
UserDereferenceObject(CurIcon);
-leave:
TRACE("Leave NtUserGetIconInfo, ret=%i\n", Ret);
UserLeave();
@@ -623,8 +730,8 @@
BOOL
APIENTRY
NtUserDestroyCursor(
- HANDLE hCurIcon,
- DWORD Unknown)
+ _In_ HANDLE hCurIcon,
+ _In_ BOOL bForce)
{
PCURICON_OBJECT CurIcon;
BOOL ret;
@@ -638,7 +745,7 @@
RETURN(FALSE);
}
- ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process());
+ ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process(), bForce);
/* Note: IntDestroyCurIconObject will remove our reference for us! */
RETURN(ret);
@@ -654,36 +761,40 @@
* @implemented
*/
HICON
-APIENTRY
+NTAPI
NtUserFindExistingCursorIcon(
- HMODULE hModule,
- HRSRC hRsrc,
- LONG cx,
- LONG cy)
+ _In_ PUNICODE_STRING pustrModule,
+ _In_ PUNICODE_STRING pustrRsrc,
+ _In_ LONG cxDesired,
+ _In_ LONG cyDesired)
{
PCURICON_OBJECT CurIcon;
- HANDLE Ret = (HANDLE)0;
- DECLARE_RETURN(HICON);
+ HICON Ret = NULL;
+ UNICODE_STRING ustrModuleSafe, ustrRsrcSafe;
+ NTSTATUS Status;
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();
-
- CurIcon = IntFindExistingCurIconObject(hModule, hRsrc, cx, cy);
+ CurIcon = IntFindExistingCurIconObject(&ustrModuleSafe, &ustrRsrcSafe,
cxDesired, cyDesired);
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;
+
+done:
+ if(!IS_INTRESOURCE(ustrRsrcSafe.Buffer))
+ ExFreePoolWithTag(ustrRsrcSafe.Buffer, TAG_STRING);
+ ReleaseCapturedUnicodeString(&ustrModuleSafe, UserMode);
+
+ return Ret;
}
@@ -920,12 +1031,6 @@
done:
- if(!Ret)
- {
- IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process());
- CurIcon = NULL;
- }
-
if (CurIcon)
{
UserDereferenceObject(CurIcon);
@@ -942,32 +1047,34 @@
/*
* @implemented
*/
-#ifdef NEW_CURSORICON
BOOL
APIENTRY
NtUserSetCursorIconData(
- _In_ HCURSOR Handle,
- _In_ HINSTANCE hinst,
- _In_ HRSRC hrsrc,
- _In_ PICONINFO pIconInfo)
+ _In_ HCURSOR Handle,
+ _In_opt_ PUNICODE_STRING pustrModule,
+ _In_opt_ PUNICODE_STRING pustrRsrc,
+ _In_ PICONINFO pIconInfo)
{
PCURICON_OBJECT CurIcon;
PSURFACE psurfBmp;
NTSTATUS Status = STATUS_SUCCESS;
BOOL Ret = FALSE;
- DECLARE_RETURN(BOOL);
ICONINFO ii;
-
+
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();
if (!(CurIcon = UserGetCurIconObject(Handle)))
{
- RETURN(FALSE);
- }
-
- CurIcon->hModule = hinst;
- CurIcon->hRsrc =hrsrc;
+ UserLeave();
+ EngSetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
_SEH2_TRY
{
@@ -1014,28 +1121,37 @@
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
+ psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmColor);
+ if(!psurfBmp)
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
{
- 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
+ psurfBmp = SURFACE_ShareLockSurface(CurIcon->aFrame[0].hbmMask);
+ if(!psurfBmp)
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);
+
+ 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;
@@ -1055,97 +1171,17 @@
GreDeleteObject(CurIcon->aFrame[0].hbmColor);
CurIcon->aFrame[0].hbmColor = NULL;
}
- }
- RETURN(Ret);
-
-CLEANUP:
- TRACE("Leave NtUserSetCursorIconData, ret=%i\n",_ret_);
+ if(!IS_INTRESOURCE(CurIcon->ustrRsrc.Buffer))
+ ExFreePoolWithTag(CurIcon->ustrRsrc.Buffer, TAG_STRING);
+ if(CurIcon->ustrModule.Buffer)
+ ReleaseCapturedUnicodeString(&CurIcon->ustrModule, UserMode);
+ }
+
+ 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
+
+ return Ret;
+}
/* Mostly inspired from wine code.
* We use low level functions because:
@@ -1167,7 +1203,7 @@
HBRUSH hbrFlickerFreeDraw,
UINT diFlags)
{
- PSURFACE psurfDest, psurfMask, psurfColor, psurfOffScreen;
+ PSURFACE psurfDest, psurfMask, psurfColor; //, psurfOffScreen = NULL;
PDC pdc = NULL;
BOOL Ret = FALSE;
HBITMAP hbmMask, hbmColor, hbmAlpha;
@@ -1215,6 +1251,35 @@
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 */
RECTL_vSetRect(&rcSrc, 0, 0, pIcon->Size.cx, pIcon->Size.cy);
@@ -1239,7 +1304,8 @@
}
/* 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)
{
@@ -1252,21 +1318,18 @@
if(!pbrush)
{
ERR("Failed to get brush object.\n");
- SURFACE_ShareUnlockSurface(psurfMask);
- if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
- return FALSE;
- }
-
+ goto Cleanup;
+ }
+
+#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,
- cxWidth, cyHeight, psurfColor->SurfObj.iBitmapFormat,
+ cxWidth, cyHeight, psurfDest->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;
+ goto Cleanup;
}
/* Paint the brush */
@@ -1292,52 +1355,45 @@
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;
+ goto Cleanup;
}
/* We now have our destination surface */
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
{
/* 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;
- }
+ // psurfOffScreen = NULL;
}
/* Now do the rendering */
@@ -1460,36 +1516,23 @@
}
done:
+#if 0
/* 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);
@@ -1509,18 +1552,20 @@
EXLATEOBJ_vCleanup(&exlo);
}
+#endif
Cleanup:
if(pdc)
{
DC_vFinishBlit(pdc, NULL);
DC_UnlockDc(pdc);
}
-
-Cleanup2:
+
+#if 0
/* Delete off screen rendering surface */
if(psurfOffScreen)
GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject);
-
+#endif
+
/* Unlock other surfaces */
SURFACE_ShareUnlockSurface(psurfMask);
if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
@@ -1554,7 +1599,7 @@
if (!(pIcon = UserGetCurIconObject(hIcon)))
{
- ERR("UserGetCurIconObject() failed!\n");
+ ERR("UserGetCurIconObject(0x%08x) failed!\n", hIcon);
UserLeave();
return FALSE;
}
Modified: trunk/reactos/win32ss/user/ntuser/simplecall.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/simple…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/simplecall.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/simplecall.c [iso-8859-1] Sun Nov 4 12:56:44 2012
@@ -248,7 +248,7 @@
PCURICON_OBJECT CurIcon;
DWORD_PTR Result ;
- if (!(CurIcon = IntCreateCurIconHandle()))
+ if (!(CurIcon = IntCreateCurIconHandle((DWORD)Param)))
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
RETURN(0);
Modified: trunk/reactos/win32ss/user/user32/windows/cursoricon_new.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/user32/window…
==============================================================================
--- trunk/reactos/win32ss/user/user32/windows/cursoricon_new.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/user32/windows/cursoricon_new.c [iso-8859-1] Sun Nov 4
12:56:44 2012
@@ -11,7 +11,7 @@
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(cursor);
-//WINE_DECLARE_DEBUG_CHANNEL(icon);
+WINE_DECLARE_DEBUG_CHANNEL(icon);
//WINE_DECLARE_DEBUG_CHANNEL(resource);
/************* USER32 INTERNAL FUNCTIONS **********/
@@ -54,6 +54,30 @@
}
/************* IMPLEMENTATION HELPERS ******************/
+
+static const WCHAR DISPLAYW[] = L"DISPLAY";
+
+static void *map_fileW( LPCWSTR name, LPDWORD filesize )
+{
+ HANDLE hFile, hMapping;
+ LPVOID ptr = NULL;
+
+ hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0 );
+ if (hFile != INVALID_HANDLE_VALUE)
+ {
+ hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
+ if (hMapping)
+ {
+ ptr = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
+ CloseHandle( hMapping );
+ if (filesize)
+ *filesize = GetFileSize( hFile, NULL );
+ }
+ CloseHandle( hFile );
+ }
+ return ptr;
+}
static int get_dib_image_size( int width, int height, int depth )
{
@@ -121,6 +145,32 @@
}
}
+static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
+ LONG *height, WORD *bpp, DWORD *compr )
+{
+ if (header->biSize == sizeof(BITMAPCOREHEADER))
+ {
+ const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
+ *width = core->bcWidth;
+ *height = core->bcHeight;
+ *bpp = core->bcBitCount;
+ *compr = 0;
+ return 0;
+ }
+ else if (header->biSize == sizeof(BITMAPINFOHEADER) ||
+ header->biSize == sizeof(BITMAPV4HEADER) ||
+ header->biSize == sizeof(BITMAPV5HEADER))
+ {
+ *width = header->biWidth;
+ *height = header->biHeight;
+ *bpp = header->biBitCount;
+ *compr = header->biCompression;
+ return 1;
+ }
+ ERR("(%d): unknown/wrong size for header\n", header->biSize );
+ return -1;
+}
+
/************* IMPLEMENTATION CORE ****************/
static BOOL CURSORICON_GetIconInfoFromBMI(
@@ -132,28 +182,35 @@
{
UINT ubmiSize = bitmap_info_size(pbmi, DIB_RGB_COLORS);
BOOL monochrome = is_dib_monochrome(pbmi);
+ LONG width, height;
+ WORD bpp;
+ DWORD compr;
+ int ibmpType;
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;
- }
+ ibmpType = DIB_GetBitmapInfo(&pbmi->bmiHeader, &width, &height,
&bpp, &compr);
+ /* Invalid data */
+ if(ibmpType < 0)
+ return FALSE;
+
+ /* No compression for icons */
+ if(compr != BI_RGB)
+ 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(!pii->fIcon)
+ {
+ 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(DISPLAYW, NULL, NULL, NULL);
if(!hdcScreen)
return FALSE;
hdc = CreateCompatibleDC(hdcScreen);
@@ -167,8 +224,13 @@
if(!pbmiCopy)
goto done;
RtlCopyMemory(pbmiCopy, pbmi, ubmiSize);
- pbmiCopy->bmiHeader.biHeight /= 2;
-
+
+ /* In an icon/cursor, the BITMAPINFO holds twice the height */
+ if(pbmiCopy->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+ ((BITMAPCOREHEADER*)&pbmiCopy->bmiHeader)->bcHeight /= 2;
+ else
+ 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 );
@@ -250,7 +312,7 @@
}
static
-HANDLE
+HBITMAP
BITMAP_LoadImageW(
_In_opt_ HINSTANCE hinst,
_In_ LPCWSTR lpszName,
@@ -259,8 +321,400 @@
_In_ UINT fuLoad
)
{
- UNIMPLEMENTED;
- return NULL;
+ const BITMAPINFO* pbmi;
+ BITMAPINFO* pbmiScaled = NULL;
+ BITMAPINFO* pbmiCopy = NULL;
+ const VOID* pvMapping;
+ DWORD dwOffset = 0;
+ HGLOBAL hgRsrc;
+ int iBMISize;
+ PVOID pvBits;
+ HDC hdcScreen = NULL;
+ HDC hdc = NULL;
+ HBITMAP hbmpRet, hbmpOld;
+
+ /* Map the bitmap info */
+ if(fuLoad & LR_LOADFROMFILE)
+ {
+ const BITMAPFILEHEADER* pbmfh;
+
+ pvMapping = map_fileW(lpszName, NULL);
+ if(!pvMapping)
+ return NULL;
+ pbmfh = pvMapping;
+ if (pbmfh->bfType != 0x4d42 /* 'BM' */)
+ {
+ WARN("Invalid/unsupported bitmap format!\n");
+ goto end;
+ }
+ pbmi = (const BITMAPINFO*)(pbmfh + 1);
+
+ /* Get the image bits */
+ if(pbmfh->bfOffBits)
+ dwOffset = pbmfh->bfOffBits - sizeof(BITMAPFILEHEADER);
+ }
+ else
+ {
+ HRSRC hrsrc;
+
+ /* Caller wants an OEM bitmap */
+ if(!hinst)
+ hinst = User32Instance;
+ hrsrc = FindResourceW(hinst, lpszName, (LPWSTR)RT_BITMAP);
+ if(!hrsrc)
+ return NULL;
+ hgRsrc = LoadResource(hinst, hrsrc);
+ if(!hgRsrc)
+ return NULL;
+ pbmi = LockResource(hgRsrc);
+ if(!pbmi)
+ return NULL;
+ }
+
+ /* See if we must scale the bitmap */
+ iBMISize = bitmap_info_size(pbmi, DIB_RGB_COLORS);
+
+ /* Get a pointer to the image data */
+ pvBits = (char*)pbmi + (dwOffset ? dwOffset : iBMISize);
+
+ /* Create a copy of the info describing the bitmap in the file */
+ pbmiCopy = HeapAlloc(GetProcessHeap(), 0, iBMISize);
+ if(!pbmiCopy)
+ goto end;
+ CopyMemory(pbmiCopy, pbmi, iBMISize);
+
+ /* Fix it up, if needed */
+ if(fuLoad & (LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS))
+ {
+ WORD bpp, incr, numColors;
+ char* pbmiColors;
+ RGBTRIPLE* ptr;
+ COLORREF crWindow, cr3DShadow, cr3DFace, cr3DLight;
+ BYTE pixel = *((BYTE*)pvBits);
+ UINT i;
+
+ if(pbmiCopy->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+ {
+ bpp = ((BITMAPCOREHEADER*)&pbmiCopy->bmiHeader)->bcBitCount;
+ numColors = 1 << bpp;
+ /* BITMAPCOREINFO holds RGBTRIPLEs */
+ incr = 3;
+ }
+ else
+ {
+ bpp = pbmiCopy->bmiHeader.biBitCount;
+ /* BITMAPINFOHEADER holds RGBQUADs */
+ incr = 4;
+ numColors = pbmiCopy->bmiHeader.biClrUsed;
+ if(numColors > 256) numColors = 256;
+ if (!numColors && (bpp <= 8)) numColors = 1 << bpp;
+ }
+
+ if(bpp > 8)
+ goto create_bitmap;
+
+ pbmiColors = (char*)pbmiCopy + pbmiCopy->bmiHeader.biSize;
+
+ /* Get the relevant colors */
+ crWindow = GetSysColor(COLOR_WINDOW);
+ cr3DShadow = GetSysColor(COLOR_3DSHADOW);
+ cr3DFace = GetSysColor(COLOR_3DFACE);
+ cr3DLight = GetSysColor(COLOR_3DLIGHT);
+
+ /* Fix the transparent palette entry */
+ if(fuLoad & LR_LOADTRANSPARENT)
+ {
+ switch(bpp)
+ {
+ case 1: pixel >>= 7; break;
+ case 4: pixel >>= 4; break;
+ case 8: break;
+ default:
+ FIXME("Unhandled bit depth %d.\n", bpp);
+ goto create_bitmap;
+ }
+
+ if(pixel >= numColors)
+ {
+ ERR("Wrong pixel passed in.\n");
+ goto create_bitmap;
+ }
+
+ /* If both flags are set, we must use COLOR_3DFACE */
+ if(fuLoad & LR_LOADMAP3DCOLORS) crWindow = cr3DFace;
+
+ /* Define the color */
+ ptr = (RGBTRIPLE*)(pbmiColors + pixel*incr);
+ ptr->rgbtBlue = GetBValue(crWindow);
+ ptr->rgbtGreen = GetGValue(crWindow);
+ ptr->rgbtRed = GetRValue(crWindow);
+ goto create_bitmap;
+ }
+
+ /* If we are here, then LR_LOADMAP3DCOLORS is set without LR_TRANSPARENT */
+ for(i = 0; i<numColors; i++)
+ {
+ ptr = (RGBTRIPLE*)(pbmiColors + i*incr);
+ if((ptr->rgbtBlue == ptr->rgbtRed) && (ptr->rgbtBlue ==
ptr->rgbtGreen))
+ {
+ if(ptr->rgbtBlue == 128)
+ {
+ ptr->rgbtBlue = GetBValue(cr3DShadow);
+ ptr->rgbtGreen = GetGValue(cr3DShadow);
+ ptr->rgbtRed = GetRValue(cr3DShadow);
+ }
+ if(ptr->rgbtBlue == 192)
+ {
+ ptr->rgbtBlue = GetBValue(cr3DFace);
+ ptr->rgbtGreen = GetGValue(cr3DFace);
+ ptr->rgbtRed = GetRValue(cr3DFace);
+ }
+ if(ptr->rgbtBlue == 223)
+ {
+ ptr->rgbtBlue = GetBValue(cr3DLight);
+ ptr->rgbtGreen = GetGValue(cr3DLight);
+ ptr->rgbtRed = GetRValue(cr3DLight);
+ }
+ }
+ }
+ }
+
+create_bitmap:
+ if(fuLoad & LR_CREATEDIBSECTION)
+ {
+ /* Allocate the BMI describing the new bitmap */
+ pbmiScaled = HeapAlloc(GetProcessHeap(), 0, iBMISize);
+ if(!pbmiScaled)
+ goto end;
+ CopyMemory(pbmiScaled, pbmiCopy, iBMISize);
+
+ /* Fix it up */
+ if(pbmiScaled->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+ {
+ BITMAPCOREHEADER* pbmch = (BITMAPCOREHEADER*)&pbmiScaled->bmiHeader;
+ if(cxDesired == 0)
+ cxDesired = pbmch->bcWidth;
+ if(cyDesired == 0)
+ cyDesired == pbmch->bcHeight;
+ else if(pbmch->bcHeight < 0)
+ cyDesired = -cyDesired;
+
+ pbmch->bcWidth = cxDesired;
+ pbmch->bcHeight = cyDesired;
+ }
+ else
+ {
+ if ((pbmi->bmiHeader.biHeight > 65535) || (pbmi->bmiHeader.biWidth
> 65535)) {
+ WARN("Broken BITMAPINFO!\n");
+ goto end;
+ }
+
+ if(cxDesired == 0)
+ cxDesired = pbmi->bmiHeader.biWidth;
+ if(cyDesired == 0)
+ cyDesired = pbmi->bmiHeader.biHeight;
+ else if(pbmi->bmiHeader.biHeight < 0)
+ cyDesired = -cyDesired;
+
+ pbmiScaled->bmiHeader.biWidth = cxDesired;
+ pbmiScaled->bmiHeader.biHeight = cyDesired;
+ /* No compression for DIB sections */
+ if(fuLoad & LR_CREATEDIBSECTION)
+ pbmiScaled->bmiHeader.biCompression = BI_RGB;
+ }
+ }
+
+ /* Top-down image */
+ if(cyDesired < 0) cyDesired = -cyDesired;
+
+ /* We need a device context */
+ hdcScreen = CreateDCW(DISPLAYW, NULL, NULL, NULL);
+ if(!hdcScreen)
+ goto end;
+ hdc = CreateCompatibleDC(hdcScreen);
+ if(!hdc)
+ goto end;
+
+ /* Now create the bitmap */
+ if(fuLoad & LR_CREATEDIBSECTION)
+ hbmpRet = CreateDIBSection(hdc, pbmiScaled, DIB_RGB_COLORS, NULL, 0, 0);
+ else
+ {
+ if(is_dib_monochrome(pbmiCopy) || (fuLoad & LR_MONOCHROME))
+ hbmpRet = CreateBitmap(cxDesired, cyDesired, 1, 1, NULL);
+ else
+ hbmpRet = CreateCompatibleBitmap(hdcScreen, cxDesired, cyDesired);
+ }
+
+ if(!hbmpRet)
+ goto end;
+
+ hbmpOld = SelectObject(hdc, hbmpRet);
+ if(!hbmpOld)
+ goto end;
+ if(!StretchDIBits(hdc, 0, 0, cxDesired, cyDesired,
+ 0, 0, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biWidth,
+ pvBits, pbmiCopy, DIB_RGB_COLORS, SRCCOPY))
+ {
+ ERR("StretchDIBits failed!.\n");
+ SelectObject(hdc, hbmpOld);
+ DeleteObject(hbmpRet);
+ hbmpRet = NULL;
+ goto end;
+ }
+
+ SelectObject(hdc, hbmpOld);
+
+end:
+ if(hdcScreen)
+ DeleteDC(hdcScreen);
+ if(hdc)
+ DeleteDC(hdc);
+ if(pbmiScaled)
+ HeapFree(GetProcessHeap(), 0, pbmiScaled);
+ if(pbmiCopy)
+ HeapFree(GetProcessHeap(), 0, pbmiCopy);
+ if (fuLoad & LR_LOADFROMFILE)
+ UnmapViewOfFile( pvMapping );
+ else
+ FreeResource(hgRsrc);
+
+ return hbmpRet;
+}
+
+#include "pshpack1.h"
+
+typedef struct {
+ BYTE bWidth;
+ BYTE bHeight;
+ BYTE bColorCount;
+ BYTE bReserved;
+ WORD xHotspot;
+ WORD yHotspot;
+ DWORD dwDIBSize;
+ DWORD dwDIBOffset;
+} CURSORICONFILEDIRENTRY;
+
+typedef struct
+{
+ WORD idReserved;
+ WORD idType;
+ WORD idCount;
+ CURSORICONFILEDIRENTRY idEntries[1];
+} CURSORICONFILEDIR;
+
+#include "poppack.h"
+
+static
+HANDLE
+CURSORICON_LoadFromFileW(
+ _In_ LPCWSTR lpszName,
+ _In_ int cxDesired,
+ _In_ int cyDesired,
+ _In_ UINT fuLoad,
+ _In_ BOOL bIcon
+)
+{
+ CURSORICONDIR* fakeDir;
+ CURSORICONDIRENTRY* fakeEntry;
+ CURSORICONFILEDIRENTRY *entry;
+ CURSORICONFILEDIR *dir;
+ DWORD filesize = 0;
+ LPBYTE bits;
+ HANDLE hRet = NULL;
+ WORD i;
+ ICONINFO ii;
+
+ TRACE("loading %s\n", debugstr_w( lpszName ));
+
+ bits = map_fileW( lpszName, &filesize );
+ if (!bits)
+ return NULL;
+
+ /* Check for .ani. */
+ if (memcmp( bits, "RIFF", 4 ) == 0)
+ {
+ UNIMPLEMENTED;
+ goto end;
+ }
+
+ dir = (CURSORICONFILEDIR*) bits;
+ if ( filesize < sizeof(*dir) )
+ goto end;
+
+ if ( filesize < (sizeof(*dir) + sizeof(dir->idEntries[0])*(dir->idCount-1))
)
+ goto end;
+
+ /*
+ * Cute little hack:
+ * We allocate a buffer, fake it as if it was a pointer to a resource in a module,
+ * pass it to LookupIconIdFromDirectoryEx and get back the index we have to use
+ */
+ fakeDir = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(CURSORICONDIR,
idEntries[dir->idCount]));
+ if(!fakeDir)
+ goto end;
+ fakeDir->idReserved = 0;
+ fakeDir->idType = dir->idType;
+ fakeDir->idCount = dir->idCount;
+ for(i = 0; i<dir->idCount; i++)
+ {
+ fakeEntry = &fakeDir->idEntries[i];
+ entry = &dir->idEntries[i];
+ /* Take this as an occasion to perform a size check */
+ if((entry->dwDIBOffset + entry->dwDIBSize) > filesize)
+ goto end;
+ /* File icon/cursors are not like resource ones */
+ if(bIcon)
+ {
+ fakeEntry->ResInfo.icon.bWidth = entry->bWidth;
+ fakeEntry->ResInfo.icon.bHeight = entry->bHeight;
+ fakeEntry->ResInfo.icon.bColorCount = 0;
+ fakeEntry->ResInfo.icon.bReserved = 0;
+ }
+ else
+ {
+ fakeEntry->ResInfo.cursor.wWidth = entry->bWidth;
+ fakeEntry->ResInfo.cursor.wHeight = entry->bHeight;
+ }
+ /* Let's assume there's always one plane */
+ fakeEntry->wPlanes = 1;
+ /* We must get the bitcount from the BITMAPINFOHEADER itself */
+ fakeEntry->wBitCount = ((BITMAPINFOHEADER *)((char *)dir +
entry->dwDIBOffset))->biBitCount;
+ fakeEntry->dwBytesInRes = entry->dwDIBSize;
+ fakeEntry->wResId = i + 1;
+ }
+
+ /* Now call LookupIconIdFromResourceEx */
+ i = LookupIconIdFromDirectoryEx((PBYTE)fakeDir, bIcon, cxDesired, cyDesired, fuLoad
& LR_MONOCHROME);
+ /* We don't need this anymore */
+ HeapFree(GetProcessHeap(), 0, fakeDir);
+ if(i == 0)
+ {
+ WARN("Unable to get a fit entry index.\n");
+ goto end;
+ }
+
+ /* Get our entry */
+ entry = &dir->idEntries[i-1];
+ /* A bit of preparation */
+ ii.xHotspot = entry->xHotspot;
+ ii.yHotspot = entry->yHotspot;
+ ii.fIcon = bIcon;
+
+ /* Do the dance */
+ if(!CURSORICON_GetIconInfoFromBMI(&ii,
(BITMAPINFO*)&bits[entry->dwDIBOffset], cxDesired, cyDesired))
+ goto end;
+
+ /* Create the icon. NOTE: there's no LR_SHARED icons if they are created from
file */
+ hRet = CreateIconIndirect(&ii);
+
+ /* Clean up */
+ DeleteObject(ii.hbmMask);
+ DeleteObject(ii.hbmColor);
+
+end:
+ UnmapViewOfFile(bits);
+ return hRet;
}
static
@@ -274,24 +728,79 @@
_In_ BOOL bIcon
)
{
- HRSRC hrsrc, hrsrc2;
- HANDLE handle, hCurIcon;
+ HRSRC hrsrc;
+ HANDLE handle, hCurIcon = NULL;
CURSORICONDIR* dir;
WORD wResId;
LPBYTE bits;
ICONINFO ii;
BOOL bStatus;
+ UNICODE_STRING ustrRsrc;
+ UNICODE_STRING ustrModule = {0, 0, 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(fuLoad & LR_LOADFROMFILE)
{
- UNIMPLEMENTED;
- return NULL;
+ return CURSORICON_LoadFromFileW(lpszName, cxDesired, cyDesired, fuLoad, bIcon);
}
/* Check if caller wants OEM icons */
if(!hinst)
hinst = User32Instance;
+ if(fuLoad & LR_SHARED)
+ {
+ DWORD size = MAX_PATH;
+
+ TRACE("Checking for an LR_SHARED cursor/icon.\n");
+ /* Prepare the resource name string */
+ if(IS_INTRESOURCE(lpszName))
+ {
+ ustrRsrc.Buffer = (LPWSTR)lpszName;
+ ustrRsrc.Length = 0;
+ ustrRsrc.MaximumLength = 0;
+ }
+ else
+ RtlInitUnicodeString(&ustrRsrc, lpszName);
+
+ /* Prepare the module name string */
+ ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));
+ /* Get it */
+ do
+ {
+ DWORD ret = GetModuleFileName(hinst, ustrModule.Buffer, size);
+ if(ret == 0)
+ {
+ HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
+ return NULL;
+ }
+ if(ret < size)
+ {
+ ustrModule.Length = ret;
+ ustrModule.MaximumLength = size;
+ break;
+ }
+ size *= 2;
+ ustrModule.Buffer = HeapReAlloc(GetProcessHeap(), 0, ustrModule.Buffer,
size*sizeof(WCHAR));
+ } while(TRUE);
+
+ /* Ask win32k */
+ hCurIcon = NtUserFindExistingCursorIcon(&ustrModule, &ustrRsrc,
cxDesired, cyDesired);
+ if(hCurIcon)
+ {
+ /* Woohoo, got it! */
+ TRACE("MATCH!\n");
+ HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
+ return hCurIcon;
+ }
+ }
+
/* Find resource ID */
hrsrc = FindResourceW(
hinst,
@@ -300,57 +809,45 @@
/* 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;
+ goto done;
handle = LoadResource(hinst, hrsrc);
if(!handle)
- return NULL;
+ goto done;
dir = LockResource(handle);
- if(!dir) return NULL;
-
- /* For now, take the first entry */
- wResId = dir->idEntries[0].wResId;
+ if(!dir)
+ goto done;
+
+ wResId = LookupIconIdFromDirectoryEx((PBYTE)dir, bIcon, cxDesired, cyDesired, fuLoad
& LR_MONOCHROME);
FreeResource(handle);
/* Get the relevant resource pointer */
- hrsrc2 = FindResourceW(
+ hrsrc = FindResourceW(
hinst,
MAKEINTRESOURCEW(wResId),
(LPWSTR)(bIcon ? RT_ICON : RT_CURSOR));
- if(!hrsrc2)
- return NULL;
-
- handle = LoadResource(hinst, hrsrc2);
+ if(!hrsrc)
+ goto done;
+
+ handle = LoadResource(hinst, hrsrc);
if(!handle)
- return NULL;
+ goto done;
bits = LockResource(handle);
if(!bits)
{
FreeResource(handle);
- return NULL;
- }
-
- /* Get the hospot */
+ goto done;
+ }
+
+ /* Get the hotspot */
if(bIcon)
{
ii.xHotspot = cxDesired/2;
ii.yHotspot = cyDesired/2;
}
- else
+ if(!bIcon)
{
SHORT* ptr = (SHORT*)bits;
ii.xHotspot = ptr[0];
@@ -369,16 +866,20 @@
FreeResource( handle );
if(!bStatus)
- return NULL;
+ goto done;
/* Create the handle */
hCurIcon = NtUserxCreateEmptyCurObject(bIcon ? 0 : 1);
if(!hCurIcon)
- return NULL;
+ {
+ DeleteObject(ii.hbmMask);
+ if(ii.hbmColor) DeleteObject(ii.hbmColor);
+ goto done;
+ }
/* Tell win32k */
if(fuLoad & LR_SHARED)
- bStatus = NtUserSetCursorIconData(hCurIcon, hinst, hrsrc, &ii);
+ bStatus = NtUserSetCursorIconData(hCurIcon, &ustrModule, &ustrRsrc,
&ii);
else
bStatus = NtUserSetCursorIconData(hCurIcon, NULL, NULL, &ii);
@@ -389,9 +890,332 @@
}
DeleteObject(ii.hbmMask);
- DeleteObject(ii.hbmColor);
-
+ if(ii.hbmColor) DeleteObject(ii.hbmColor);
+
+done:
+ if(ustrModule.Buffer)
+ HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
return hCurIcon;
+}
+
+static
+HBITMAP
+BITMAP_CopyImage(
+ _In_ HBITMAP hbmp,
+ _In_ int cxDesired,
+ _In_ int cyDesired,
+ _In_ UINT fuFlags
+)
+{
+ HBITMAP res = NULL;
+ DIBSECTION ds;
+ int objSize;
+ BITMAPINFO * bi;
+
+ objSize = GetObjectW( hbmp, sizeof(ds), &ds );
+ if (!objSize) return 0;
+ if ((cxDesired < 0) || (cyDesired < 0)) return 0;
+
+ if (fuFlags & LR_COPYFROMRESOURCE)
+ {
+ FIXME("The flag LR_COPYFROMRESOURCE is not implemented for
bitmaps\n");
+ }
+
+ if (fuFlags & LR_COPYRETURNORG)
+ {
+ FIXME("The flag LR_COPYRETURNORG is not implemented for bitmaps\n");
+ }
+
+ if (cxDesired == 0) cxDesired = ds.dsBm.bmWidth;
+ if (cyDesired == 0) cyDesired = ds.dsBm.bmHeight;
+
+ /* Allocate memory for a BITMAPINFOHEADER structure and a
+ color table. The maximum number of colors in a color table
+ is 256 which corresponds to a bitmap with depth 8.
+ Bitmaps with higher depths don't have color tables. */
+ bi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 *
sizeof(RGBQUAD));
+ if (!bi) return 0;
+
+ bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
+ bi->bmiHeader.biPlanes = ds.dsBm.bmPlanes;
+ bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel;
+ bi->bmiHeader.biCompression = BI_RGB;
+
+ if (fuFlags & LR_CREATEDIBSECTION)
+ {
+ /* Create a DIB section. LR_MONOCHROME is ignored */
+ void * bits;
+ HDC dc = CreateCompatibleDC(NULL);
+
+ if (objSize == sizeof(DIBSECTION))
+ {
+ /* The source bitmap is a DIB.
+ Get its attributes to create an exact copy */
+ memcpy(bi, &ds.dsBmih, sizeof(BITMAPINFOHEADER));
+ }
+
+ /* Get the color table or the color masks */
+ GetDIBits(dc, hbmp, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
+
+ bi->bmiHeader.biWidth = cxDesired;
+ bi->bmiHeader.biHeight = cyDesired;
+ bi->bmiHeader.biSizeImage = 0;
+
+ res = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
+ DeleteDC(dc);
+ }
+ else
+ {
+ /* Create a device-dependent bitmap */
+
+ BOOL monochrome = (fuFlags & LR_MONOCHROME);
+
+ if (objSize == sizeof(DIBSECTION))
+ {
+ /* The source bitmap is a DIB section.
+ Get its attributes */
+ HDC dc = CreateCompatibleDC(NULL);
+ bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
+ bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel;
+ GetDIBits(dc, hbmp, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
+ DeleteDC(dc);
+
+ if (!monochrome && ds.dsBm.bmBitsPixel == 1)
+ {
+ /* Look if the colors of the DIB are black and white */
+
+ monochrome =
+ (bi->bmiColors[0].rgbRed == 0xff
+ && bi->bmiColors[0].rgbGreen == 0xff
+ && bi->bmiColors[0].rgbBlue == 0xff
+ && bi->bmiColors[0].rgbReserved == 0
+ && bi->bmiColors[1].rgbRed == 0
+ && bi->bmiColors[1].rgbGreen == 0
+ && bi->bmiColors[1].rgbBlue == 0
+ && bi->bmiColors[1].rgbReserved == 0)
+ ||
+ (bi->bmiColors[0].rgbRed == 0
+ && bi->bmiColors[0].rgbGreen == 0
+ && bi->bmiColors[0].rgbBlue == 0
+ && bi->bmiColors[0].rgbReserved == 0
+ && bi->bmiColors[1].rgbRed == 0xff
+ && bi->bmiColors[1].rgbGreen == 0xff
+ && bi->bmiColors[1].rgbBlue == 0xff
+ && bi->bmiColors[1].rgbReserved == 0);
+ }
+ }
+ else if (!monochrome)
+ {
+ monochrome = ds.dsBm.bmBitsPixel == 1;
+ }
+
+ if (monochrome)
+ {
+ res = CreateBitmap(cxDesired, cyDesired, 1, 1, NULL);
+ }
+ else
+ {
+ HDC screenDC = GetDC(NULL);
+ res = CreateCompatibleBitmap(screenDC, cxDesired, cyDesired);
+ ReleaseDC(NULL, screenDC);
+ }
+ }
+
+ if (res)
+ {
+ /* Only copy the bitmap if it's a DIB section or if it's
+ compatible to the screen */
+ BOOL copyContents;
+
+ if (objSize == sizeof(DIBSECTION))
+ {
+ copyContents = TRUE;
+ }
+ else
+ {
+ HDC screenDC = GetDC(NULL);
+ int screen_depth = GetDeviceCaps(screenDC, BITSPIXEL);
+ ReleaseDC(NULL, screenDC);
+
+ copyContents = (ds.dsBm.bmBitsPixel == 1 || ds.dsBm.bmBitsPixel ==
screen_depth);
+ }
+
+ if (copyContents)
+ {
+ /* The source bitmap may already be selected in a device context,
+ use GetDIBits/StretchDIBits and not StretchBlt */
+
+ HDC dc;
+ void * bits;
+
+ dc = CreateCompatibleDC(NULL);
+
+ bi->bmiHeader.biWidth = ds.dsBm.bmWidth;
+ bi->bmiHeader.biHeight = ds.dsBm.bmHeight;
+ bi->bmiHeader.biSizeImage = 0;
+ bi->bmiHeader.biClrUsed = 0;
+ bi->bmiHeader.biClrImportant = 0;
+
+ /* Fill in biSizeImage */
+ GetDIBits(dc, hbmp, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
+ bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
bi->bmiHeader.biSizeImage);
+
+ if (bits)
+ {
+ HBITMAP oldBmp;
+
+ /* Get the image bits of the source bitmap */
+ GetDIBits(dc, hbmp, 0, ds.dsBm.bmHeight, bits, bi, DIB_RGB_COLORS);
+
+ /* Copy it to the destination bitmap */
+ oldBmp = SelectObject(dc, res);
+ StretchDIBits(dc, 0, 0, cxDesired, cyDesired,
+ 0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight,
+ bits, bi, DIB_RGB_COLORS, SRCCOPY);
+ SelectObject(dc, oldBmp);
+
+ HeapFree(GetProcessHeap(), 0, bits);
+ }
+
+ DeleteDC(dc);
+ }
+
+ if (fuFlags & LR_COPYDELETEORG)
+ {
+ DeleteObject(hbmp);
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, bi);
+ return res;
+}
+
+static
+HICON
+CURSORICON_CopyImage(
+ _In_ HICON hicon,
+ _In_ BOOL bIcon,
+ _In_ int cxDesired,
+ _In_ int cyDesired,
+ _In_ UINT fuFlags
+)
+{
+ HICON ret = NULL;
+ ICONINFO ii;
+
+ if(fuFlags & LR_COPYFROMRESOURCE)
+ {
+ /* Get the icon module/resource names */
+ UNICODE_STRING ustrModule;
+ UNICODE_STRING ustrRsrc;
+ PVOID pvBuf;
+ HMODULE hModule;
+
+ ustrModule.MaximumLength = MAX_PATH;
+ ustrRsrc.MaximumLength = 256;
+
+ ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, ustrModule.MaximumLength *
sizeof(WCHAR));
+ if(!ustrModule.Buffer)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+ /* Keep track of the buffer for the resource, NtUserGetIconInfo might overwrite
it */
+ pvBuf = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(WCHAR));
+ if(!pvBuf)
+ {
+ HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+ ustrRsrc.Buffer = pvBuf;
+
+ do
+ {
+ if(!NtUserGetIconInfo(hicon, NULL, &ustrModule, &ustrRsrc, NULL,
FALSE))
+ {
+ HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
+ HeapFree(GetProcessHeap(), 0, pvBuf);
+ return NULL;
+ }
+
+ if((ustrModule.Length < ustrModule.MaximumLength) &&
(ustrRsrc.Length < ustrRsrc.MaximumLength))
+ {
+ /* Buffers were big enough */
+ break;
+ }
+
+ /* Find which buffer were too small */
+ if(ustrModule.Length == ustrModule.MaximumLength)
+ {
+ PWSTR newBuffer;
+ ustrModule.MaximumLength *= 2;
+ newBuffer = HeapReAlloc(GetProcessHeap(), 0, ustrModule.Buffer,
ustrModule.MaximumLength * sizeof(WCHAR));
+ if(!ustrModule.Buffer)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto leave;
+ }
+ ustrModule.Buffer = newBuffer;
+ }
+
+ if(ustrRsrc.Length == ustrRsrc.MaximumLength)
+ {
+ ustrRsrc.MaximumLength *= 2;
+ pvBuf = HeapReAlloc(GetProcessHeap(), 0, ustrRsrc.Buffer,
ustrRsrc.MaximumLength * sizeof(WCHAR));
+ if(!pvBuf)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto leave;
+ }
+ ustrRsrc.Buffer = pvBuf;
+ }
+ } while(TRUE);
+
+ /* NULL-terminate our strings */
+ ustrModule.Buffer[ustrModule.Length] = 0;
+ if(!IS_INTRESOURCE(ustrRsrc.Buffer))
+ ustrRsrc.Buffer[ustrRsrc.Length] = 0;
+
+ /* Get the module handle */
+ if(!GetModuleHandleExW(0, ustrModule.Buffer, &hModule))
+ {
+ /* This hould never happen */
+ SetLastError(ERROR_INVALID_PARAMETER);
+ goto leave;
+ }
+
+ /* Call the relevant function */
+ ret = CURSORICON_LoadImageW(hModule, ustrRsrc.Buffer, cxDesired, cyDesired,
bIcon, fuFlags & LR_DEFAULTSIZE);
+
+ FreeLibrary(hModule);
+
+ /* If we're here, that means that the passed icon is shared. Don't
destroy it, even if LR_COPYDELETEORG is specified */
+ leave:
+ HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
+ HeapFree(GetProcessHeap(), 0, pvBuf);
+
+ return ret;
+ }
+
+ /* This is a regular copy */
+ if(fuFlags & ~LR_COPYDELETEORG)
+ FIXME("Unimplemented flags: 0x%08x\n", fuFlags);
+
+ if(!GetIconInfo(hicon, &ii))
+ {
+ ERR("GetIconInfo failed.\n");
+ return NULL;
+ }
+
+ ret = CreateIconIndirect(&ii);
+
+ DeleteObject(ii.hbmMask);
+ if(ii.hbmColor) DeleteObject(ii.hbmColor);
+
+ if(ret && (fuFlags & LR_COPYDELETEORG))
+ DestroyIcon(hicon);
+
+ return hicon;
}
/************* PUBLIC FUNCTIONS *******************/
@@ -404,7 +1228,19 @@
_In_ UINT fuFlags
)
{
- UNIMPLEMENTED;
+ TRACE("hImage=%p, uType=%u, cxDesired=%d, cyDesired=%d, fuFlags=%x\n",
+ hImage, uType, cxDesired, cyDesired, fuFlags);
+ switch(uType)
+ {
+ case IMAGE_BITMAP:
+ return BITMAP_CopyImage(hImage, cxDesired, cyDesired, fuFlags);
+ case IMAGE_CURSOR:
+ case IMAGE_ICON:
+ return CURSORICON_CopyImage(hImage, uType == IMAGE_ICON, cxDesired,
cyDesired, fuFlags);
+ default:
+ SetLastError(ERROR_INVALID_PARAMETER);
+ break;
+ }
return NULL;
}
@@ -438,8 +1274,9 @@
_In_ UINT diFlags
)
{
- UNIMPLEMENTED;
- return FALSE;
+ return NtUserDrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
+ istepIfAniCur, hbrFlickerFreeDraw, diFlags,
+ 0, 0);
}
BOOL WINAPI GetIconInfo(
@@ -447,16 +1284,14 @@
_Out_ PICONINFO piconinfo
)
{
- UNIMPLEMENTED;
- return FALSE;
+ return NtUserGetIconInfo(hIcon, piconinfo, NULL, NULL, NULL, FALSE);
}
BOOL WINAPI DestroyIcon(
_In_ HICON hIcon
)
{
- UNIMPLEMENTED;
- return FALSE;
+ return NtUserDestroyCursor(hIcon, FALSE);
}
HICON WINAPI LoadIconA(
@@ -631,8 +1466,9 @@
_In_ BOOL fIcon
)
{
- UNIMPLEMENTED;
- return 0;
+ return LookupIconIdFromDirectoryEx( presbits, fIcon,
+ fIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
+ fIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), fIcon ? 0
: LR_MONOCHROME );
}
int WINAPI LookupIconIdFromDirectoryEx(
@@ -643,8 +1479,134 @@
_In_ UINT Flags
)
{
- UNIMPLEMENTED;
- return 0;
+ WORD bppDesired;
+ CURSORICONDIR* dir = (CURSORICONDIR*)presbits;
+ CURSORICONDIRENTRY* entry;
+ int i, numMatch, iIndex = -1;
+ WORD width, height;
+ USHORT bitcount;
+ ULONG cxyDiff, cxyDiffTmp;
+
+ TRACE("%p, %x, %i, %i, %x.\n", presbits, fIcon, cxDesired, cyDesired,
Flags);
+
+ if(!(dir && !dir->idReserved && (dir->idType & 3)))
+ {
+ WARN("Invalid resource.\n");
+ return 0;
+ }
+
+ /* idType == 2 is for cursors, 1 for icons */
+ /*if(fIcon)
+ {
+ if(dir->idType == 2)
+ {
+ WARN("An icon was asked for a cursor resource.\n");
+ return 0;
+ }
+ }
+ else if(dir->idType == 1)
+ {
+ WARN("A cursor was asked for an icon resource.\n");
+ return 0;
+ }*/
+
+ if(Flags & LR_MONOCHROME)
+ bppDesired = 1;
+ else
+ {
+ HDC icScreen;
+ icScreen = CreateICW(DISPLAYW, NULL, NULL, NULL);
+ if(!icScreen)
+ return FALSE;
+
+ bppDesired = GetDeviceCaps(icScreen, BITSPIXEL);
+ DeleteDC(icScreen);
+ }
+
+ /* Find the best match for the desired size */
+ cxyDiff = 0xFFFFFFFF;
+ numMatch = 0;
+ for(i = 0; i < dir->idCount; i++)
+ {
+ entry = &dir->idEntries[i];
+ width = fIcon ? entry->ResInfo.icon.bWidth : entry->ResInfo.cursor.wWidth;
+ /* Height is twice as big in cursor resources */
+ height = fIcon ? entry->ResInfo.icon.bHeight :
entry->ResInfo.cursor.wHeight/2;
+ /* 0 represents 256 */
+ if(!width) width = 256;
+ if(!height) height = 256;
+ /* Let it be a 1-norm */
+ cxyDiffTmp = max(abs(width - cxDesired), abs(height - cyDesired));
+ if( cxyDiffTmp > cxyDiff)
+ continue;
+ if( cxyDiffTmp == cxyDiff)
+ {
+ numMatch++;
+ continue;
+ }
+ iIndex = i;
+ numMatch = 1;
+ cxyDiff = cxyDiffTmp;
+ }
+
+ if(numMatch == 1)
+ {
+ /* Only one entry fit the asked dimensions */
+ return dir->idEntries[iIndex].wResId;
+ }
+
+ bitcount = 0;
+ iIndex = -1;
+ /* Now find the entry with the best depth */
+ for(i = 0; i < dir->idCount; i++)
+ {
+ entry = &dir->idEntries[i];
+ width = fIcon ? entry->ResInfo.icon.bWidth : entry->ResInfo.cursor.wWidth;
+ height = fIcon ? entry->ResInfo.icon.bHeight :
entry->ResInfo.cursor.wHeight/2;
+ /* 0 represents 256 */
+ if(!width) width = 256;
+ if(!height) height = 256;
+ /* Check if this is the best match we had */
+ cxyDiffTmp = max(abs(width - cxDesired), abs(height - cyDesired));
+ if(cxyDiffTmp != cxyDiff)
+ continue;
+ /* Exact match? */
+ if(entry->wBitCount == bppDesired)
+ return entry->wResId;
+ /* We take the highest possible but smaller than the display depth */
+ if((entry->wBitCount > bitcount) && (entry->wBitCount <
bppDesired))
+ {
+ iIndex = i;
+ bitcount = entry->wBitCount;
+ }
+ }
+
+ if(iIndex >= 0)
+ return dir->idEntries[iIndex].wResId;
+
+ /* No inferior or equal depth available. Get the smallest one */
+ bitcount = 0x7FFF;
+ for(i = 0; i < dir->idCount; i++)
+ {
+ entry = &dir->idEntries[i];
+ width = fIcon ? entry->ResInfo.icon.bWidth : entry->ResInfo.cursor.wWidth;
+ height = fIcon ? entry->ResInfo.icon.bHeight :
entry->ResInfo.cursor.wHeight/2;
+ /* 0 represents 256 */
+ if(!width) width = 256;
+ if(!height) height = 256;
+ /* Check if this is the best match we had */
+ cxyDiffTmp = max(abs(width - cxDesired), abs(height - cyDesired));
+ if(cxyDiffTmp != cxyDiff)
+ continue;
+ /* Check the bit depth */
+ if(entry->wBitCount < bitcount)
+ {
+ iIndex = i;
+ bitcount = entry->wBitCount;
+ }
+ }
+
+ return dir->idEntries[iIndex].wResId;
}
HICON WINAPI CreateIcon(
@@ -657,8 +1619,32 @@
_In_ const BYTE *lpbXORbits
)
{
- UNIMPLEMENTED;
- return NULL;
+ ICONINFO iinfo;
+ HICON hIcon;
+
+ TRACE_(icon)("%dx%d, planes %d, bpp %d, xor %p, and %p\n",
+ nWidth, nHeight, cPlanes, cBitsPixel, lpbXORbits, lpbANDbits);
+
+ iinfo.fIcon = TRUE;
+ iinfo.xHotspot = nWidth / 2;
+ iinfo.yHotspot = nHeight / 2;
+ if (cPlanes * cBitsPixel > 1)
+ {
+ iinfo.hbmColor = CreateBitmap( nWidth, nHeight, cPlanes, cBitsPixel, lpbXORbits
);
+ iinfo.hbmMask = CreateBitmap( nWidth, nHeight, 1, 1, lpbANDbits );
+ }
+ else
+ {
+ iinfo.hbmMask = CreateBitmap( nWidth, nHeight * 2, 1, 1, lpbANDbits );
+ iinfo.hbmColor = NULL;
+ }
+
+ hIcon = CreateIconIndirect( &iinfo );
+
+ DeleteObject( iinfo.hbmMask );
+ if (iinfo.hbmColor) DeleteObject( iinfo.hbmColor );
+
+ return hIcon;
}
HICON WINAPI CreateIconFromResource(
@@ -681,16 +1667,60 @@
_In_ UINT uFlags
)
{
- UNIMPLEMENTED;
- return NULL;
+ ICONINFO ii;
+ HICON hIcon;
+
+ if(uFlags)
+ FIXME("uFlags 0x%08x ignored.\n", uFlags);
+
+ if(fIcon)
+ {
+ ii.xHotspot = cxDesired/2;
+ ii.yHotspot = cyDesired/2;
+ }
+ else
+ {
+ WORD* pt = (WORD*)pbIconBits;
+ ii.xHotspot = *pt++;
+ ii.yHotspot = *pt++;
+ pbIconBits = (PBYTE)pt;
+ }
+ ii.fIcon = fIcon;
+
+ if(!CURSORICON_GetIconInfoFromBMI(&ii, (BITMAPINFO*)pbIconBits, cxDesired,
cyDesired))
+ return NULL;
+
+ hIcon = CreateIconIndirect(&ii);
+
+ /* Clean up */
+ DeleteObject(ii.hbmMask);
+ if(ii.hbmColor) DeleteObject(ii.hbmColor);
+
+ return hIcon;
}
HICON WINAPI CreateIconIndirect(
_In_ PICONINFO piconinfo
)
{
- UNIMPLEMENTED;
- return NULL;
+ /* As simple as creating a handle, and let win32k deal with the bitmaps */
+ HICON hiconRet;
+
+ TRACE("%p.\n", piconinfo);
+
+ hiconRet = NtUserxCreateEmptyCurObject(piconinfo->fIcon ? 0 : 1);
+ if(!hiconRet)
+ return NULL;
+
+ if(!NtUserSetCursorIconData(hiconRet, NULL, NULL, piconinfo))
+ {
+ NtUserDestroyCursor(hiconRet, FALSE);
+ hiconRet = NULL;
+ }
+
+ TRACE("Returning 0x%08x.\n", hiconRet);
+
+ return hiconRet;
}
HCURSOR WINAPI CreateCursor(
@@ -703,8 +1733,21 @@
_In_ const VOID *pvXORPlane
)
{
- UNIMPLEMENTED;
- return NULL;
+ ICONINFO info;
+ HCURSOR hCursor;
+
+ TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
+ nWidth, nHeight, xHotSpot, yHotSpot, pvXORPlane, pvANDPlane);
+
+ info.fIcon = FALSE;
+ info.xHotspot = xHotSpot;
+ info.yHotspot = yHotSpot;
+ info.hbmMask = CreateBitmap( nWidth, nHeight, 1, 1, pvANDPlane );
+ info.hbmColor = CreateBitmap( nWidth, nHeight, 1, 1, pvXORPlane );
+ hCursor = CreateIconIndirect( &info );
+ DeleteObject( info.hbmMask );
+ DeleteObject( info.hbmColor );
+ return hCursor;
}
BOOL WINAPI SetSystemCursor(
@@ -729,8 +1772,7 @@
_Out_ LPPOINT lpPoint
)
{
- UNIMPLEMENTED;
- return FALSE;
+ return NtUserxGetCursorPos(lpPoint);
}
int WINAPI ShowCursor(
@@ -751,6 +1793,5 @@
_In_ HCURSOR hCursor
)
{
- UNIMPLEMENTED;
- return FALSE;
-}
+ return NtUserDestroyCursor(hCursor, FALSE);
+}