Author: tkreuzer
Date: Sun Mar 8 13:44:24 2015
New Revision: 66608
URL:
http://svn.reactos.org/svn/reactos?rev=66608&view=rev
Log:
[WIN32K]
- revert an "improvement" in NtUserFindExistingCursorIcon
- Remove boken asserts
- Implement GreSetBitmapOwner and use it to set bitmap owner in IntSetCursorData
- Fix cleanup after failure in setting bitmap owner
- Fix string cleanup (don't free INTRESOURCE)
- Validate frame indices to be within range
- Make sure frame indices and JIR reates are copied
- A few other fixes/improvements
Modified:
trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c
trunk/reactos/win32ss/gdi/ntgdi/bitmaps.h
trunk/reactos/win32ss/user/ntuser/cursoricon.c
Modified: trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/bitmaps.…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c [iso-8859-1] Sun Mar 8 13:44:24 2015
@@ -10,6 +10,37 @@
#define NDEBUG
#include <debug.h>
+
+BOOL
+NTAPI
+GreSetBitmapOwner(
+ _In_ HBITMAP hbmp,
+ _In_ ULONG ulOwner)
+{
+ /* Check if we have the correct object type */
+ if (GDI_HANDLE_GET_TYPE(hbmp) != GDILoObjType_LO_BITMAP_TYPE)
+ {
+ DPRINT1("Incorrect type for hbmp: %p\n", hbmp);
+ return FALSE;
+ }
+
+ /// FIXME: this is a hack and doesn't handle a race condition properly.
+ /// It needs to be done in GDIOBJ_vSetObjectOwner atomically.
+
+ /* Check if we set public or none */
+ if ((ulOwner == GDI_OBJ_HMGR_PUBLIC) ||
+ (ulOwner == GDI_OBJ_HMGR_NONE))
+ {
+ /* Only allow this for owned objects */
+ if (GreGetObjectOwner(hbmp) != GDI_OBJ_HMGR_POWNED)
+ {
+ DPRINT1("Cannot change owner for non-powned hbmp\n");
+ return FALSE;
+ }
+ }
+
+ return GreSetObjectOwner(hbmp, ulOwner);
+}
static
int
Modified: trunk/reactos/win32ss/gdi/ntgdi/bitmaps.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/bitmaps.…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/bitmaps.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/bitmaps.h [iso-8859-1] Sun Mar 8 13:44:24 2015
@@ -2,6 +2,12 @@
INT APIENTRY BITMAP_GetObject(SURFACE * bmp, INT count, LPVOID buffer);
HBITMAP FASTCALL BITMAP_CopyBitmap (HBITMAP hBitmap);
+
+BOOL
+NTAPI
+GreSetBitmapOwner(
+ _In_ HBITMAP hbmp,
+ _In_ ULONG ulOwner);
HBITMAP
NTAPI
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 Mar 8 13:44:24 2015
@@ -107,8 +107,6 @@
NT_ASSERT((pcur->CURSORF_flags & (CURSORF_GLOBAL|CURSORF_LRSHARED)) != 0);
NT_ASSERT((pcur->CURSORF_flags & CURSORF_LINKED) != 0);
- NT_ASSERT((pcur->CURSORF_flags & CURSORF_GLOBAL) == 0);
-
/* Get the right list head */
ppcurHead = (pcur->CURSORF_flags & CURSORF_GLOBAL) ?
&gcurFirst : &ppi->pCursorCache;
@@ -360,7 +358,7 @@
for (i = 0; i < AniCurIcon->cpcur; i++)
{
- NT_VERIFY(UserDereferenceObject(AniCurIcon->aspcur[i]) == TRUE);
+ UserDereferenceObject(AniCurIcon->aspcur[i]);
NT_VERIFY(IntDestroyCurIconObject(AniCurIcon->aspcur[i]) == TRUE);
}
ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR);
@@ -904,11 +902,16 @@
/* See if module names match */
if (atomModName == CurIcon->atomModName)
{
- /* Check if this is an INTRESOURCE */
+ /* They do. Now see if this is the same resource */
+ if (IS_INTRESOURCE(CurIcon->strName.Buffer) !=
IS_INTRESOURCE(ustrRsrcSafe.Buffer))
+ {
+ /* One is an INT resource and the other is not -> no match */
+ CurIcon = CurIcon->pcurNext;
+ continue;
+ }
+
if (IS_INTRESOURCE(CurIcon->strName.Buffer))
{
- /* Compare if it matches the one we are looking for. This also
- handles the case, where ustrRsrcSafe is not an INTRESOURCE */
if (CurIcon->strName.Buffer == ustrRsrcSafe.Buffer)
{
/* INT resources match */
@@ -1111,8 +1114,6 @@
_In_ ATOM atomModName,
_In_ const CURSORDATA* pcursordata)
{
- NT_ASSERT((pcur->CURSORF_flags & CURSORF_ACON) == 0);
-
/* Check if the CURSORF_ACON is also set in the cursor data */
if (pcursordata->CURSORF_flags & CURSORF_ACON)
{
@@ -1133,22 +1134,25 @@
{
ERR("NtUserSetCursorIconData was got no hbmMask.\n");
EngSetLastError(ERROR_INVALID_PARAMETER);
- goto Cleanup;
+ return FALSE;
}
/* Take ownership of the mask bitmap */
- if (!GreSetObjectOwner(pcursordata->hbmMask, GDI_OBJ_HMGR_PUBLIC))
- {
- goto Cleanup;
+ if (!GreSetBitmapOwner(pcursordata->hbmMask, GDI_OBJ_HMGR_PUBLIC))
+ {
+ ERR("Failed to set ownership of hbmMask %p.\n",
pcursordata->hbmMask);
+ return FALSE;
}
/* Check if we have a color bitmap */
if (pcursordata->hbmColor)
{
/* Take ownership of the color bitmap */
- if (!GreSetObjectOwner(pcursordata->hbmColor, GDI_OBJ_HMGR_PUBLIC))
- {
- goto Cleanup;
+ if (!GreSetBitmapOwner(pcursordata->hbmColor, GDI_OBJ_HMGR_PUBLIC))
+ {
+ ERR("Failed to set ownership of hbmColor %p.\n",
pcursordata->hbmColor);
+ GreSetBitmapOwner(pcursordata->hbmMask, GDI_OBJ_HMGR_POWNED);
+ return FALSE;
}
}
@@ -1156,19 +1160,27 @@
if (pcursordata->hbmAlpha)
{
/* Take ownership of the alpha bitmap */
- if (!GreSetObjectOwner(pcursordata->hbmAlpha, GDI_OBJ_HMGR_PUBLIC))
- {
- goto Cleanup;
- }
- }
-
- /* Free the old name */
+ if (!GreSetBitmapOwner(pcursordata->hbmAlpha, GDI_OBJ_HMGR_PUBLIC))
+ {
+ ERR("Failed to set ownership of hbmAlpha %p.\n",
pcursordata->hbmAlpha);
+ GreSetBitmapOwner(pcursordata->hbmMask, GDI_OBJ_HMGR_POWNED);
+ if (pcursordata->hbmColor)
+ {
+ GreSetBitmapOwner(pcursordata->hbmColor, GDI_OBJ_HMGR_POWNED);
+ }
+ return FALSE;
+ }
+ }
+
+ /* Free the old name (Must be NULL atm, but later we might allow this) */
+ NT_ASSERT(pcur->strName.Buffer == NULL);
if (pcur->strName.Buffer != NULL)
{
- ExFreePoolWithTag(pcur->strName.Buffer, TAG_STRING);
- pcur->strName.Buffer = NULL;
- pcur->strName.Length = 0;
- pcur->strName.MaximumLength = 0;
+ if (!IS_INTRESOURCE(pcur->strName.Buffer))
+ {
+ ExFreePoolWithTag(pcur->strName.Buffer, TAG_STRING);
+ }
+ RtlInitEmptyUnicodeString(&pcur->strName, NULL, 0);
}
/* Free the module atom */
@@ -1200,28 +1212,6 @@
}
return TRUE;
-
-Cleanup:
-
- if (pcursordata->hbmMask != NULL)
- {
- GreSetObjectOwner(pcursordata->hbmMask, GDI_OBJ_HMGR_POWNED);
- GreDeleteObject(pcursordata->hbmMask);
- }
-
- if (pcursordata->hbmColor != NULL)
- {
- GreSetObjectOwner(pcursordata->hbmColor, GDI_OBJ_HMGR_POWNED);
- GreDeleteObject(pcursordata->hbmColor);
- }
-
- if (pcursordata->hbmAlpha != NULL)
- {
- GreSetObjectOwner(pcursordata->hbmAlpha, GDI_OBJ_HMGR_POWNED);
- GreDeleteObject(pcursordata->hbmAlpha);
- }
-
- return FALSE;
}
static
@@ -1230,7 +1220,7 @@
_Inout_ PACON pacon,
_In_opt_ PUNICODE_STRING pustrName,
_In_ ATOM atomModName,
- _In_ PCURSORDATA pcursordata)
+ _In_ const CURSORDATA *pcursordata)
{
PCURICON_OBJECT *aspcur;
DWORD *aicur;
@@ -1240,9 +1230,11 @@
UINT cjSize, i;
NT_ASSERT((pacon->CURSORF_flags & CURSORF_ACON) != 0);
+ NT_ASSERT((pacon->CURSORF_flags & CURSORF_ACONFRAME) == 0);
NT_ASSERT((ULONG_PTR)pcursordata->aspcur > MmUserProbeAddress);
NT_ASSERT((ULONG_PTR)pcursordata->aicur > MmUserProbeAddress);
NT_ASSERT((ULONG_PTR)pcursordata->ajifRate > MmUserProbeAddress);
+ NT_ASSERT((pcursordata->CURSORF_flags & ~CURSORF_USER_MASK) == 0);
NT_ASSERT(pcursordata->cpcur > 0);
NT_ASSERT(pcursordata->cicur > 0);
@@ -1259,6 +1251,20 @@
{
ERR("Acon data already set!\n");
return FALSE;
+ }
+
+ /* Loop all frames indexes */
+ for (i = 0; i < pcursordata->cicur; i++)
+ {
+ /* Check if the index is within the range of the frames */
+ if (pcursordata->aicur[i] >= pcursordata->cpcur)
+ {
+ ERR("aicur[%lu] is out or range. Got %lu, cpcur = %u\n",
+ i, pcursordata->aicur[i], pcursordata->cpcur);
+ return FALSE;
+ }
+
+ /* FIXME: check the JIF rates? */
}
/* Calculate size: one cursor object for each frame, and a frame
@@ -1280,6 +1286,13 @@
aicur = (DWORD*)&aspcur[pcursordata->cpcur];
ajifRate = (INT*)&aicur[pcursordata->cicur];
+ /* Copy the values */
+ RtlCopyMemory(aicur, pcursordata->aicur, pcursordata->cicur * sizeof(DWORD));
+ RtlCopyMemory(ajifRate, pcursordata->ajifRate, pcursordata->cicur *
sizeof(INT));
+
+ /* Zero out the array, so we can handle cleanup */
+ RtlZeroMemory(aspcur, pcursordata->cpcur * sizeof(PCURICON_OBJECT));
+
/* Get a pointer to the cursor data for each frame */
pcdFrame = pcursordata->aspcur;
@@ -1291,7 +1304,6 @@
if (hcurFrame == NULL)
{
ERR("Failed to create a cursor for frame %u\n", i);
- aspcur[i] = NULL;
goto Cleanup;
}
@@ -1299,8 +1311,13 @@
aspcur[i] = UserGetCurIconObject(hcurFrame);
NT_ASSERT(aspcur[i] != NULL);
- /* Mark this cursor as an acon frame */
- pcdFrame->CURSORF_flags |= CURSORF_ACONFRAME;
+ /* Check if the flags are valid */
+ if (pcdFrame->CURSORF_flags & ~(CURSORF_USER_MASK|CURSORF_ACONFRAME))
+ {
+ ERR("Invalid flags for acon frame %u: 0x%lx\n",
+ i, pcdFrame->CURSORF_flags);
+ goto Cleanup;
+ }
/* Set the cursor data for this frame */
if (!IntSetCursorData(aspcur[i], NULL, 0, &pcdFrame[i]))
@@ -1308,15 +1325,20 @@
ERR("Failed to set cursor data for frame %u\n", i);
goto Cleanup;
}
- }
-
- /* Free the old name */
+
+ /* Mark this cursor as an acon frame */
+ aspcur[i]->CURSORF_flags |= CURSORF_ACONFRAME;
+ }
+
+ /* Free the old name (Must be NULL atm.) */
+ NT_ASSERT(pacon->strName.Buffer == NULL);
if (pacon->strName.Buffer != NULL)
{
- ExFreePoolWithTag(pacon->strName.Buffer, TAG_STRING);
- pacon->strName.Buffer = NULL;
- pacon->strName.Length = 0;
- pacon->strName.MaximumLength = 0;
+ if (!IS_INTRESOURCE(pacon->strName.Buffer))
+ {
+ ExFreePoolWithTag(pacon->strName.Buffer, TAG_STRING);
+ }
+ RtlInitEmptyUnicodeString(&pacon->strName, NULL, 0);
}
/* Free the module atom */
@@ -1330,7 +1352,7 @@
{
for (i = 0; i < pacon->cpcur; i++)
{
- NT_VERIFY(UserDereferenceObject(pacon->aspcur[i]) == TRUE);
+ UserDereferenceObject(pacon->aspcur[i]);
NT_VERIFY(IntDestroyCurIconObject(pacon->aspcur[i]) == TRUE);
}
ExFreePoolWithTag(pacon->aspcur, USERTAG_CURSOR);
@@ -1362,7 +1384,7 @@
break;
/* Destroy this cursor */
- NT_VERIFY(UserDereferenceObject(aspcur[i]) == TRUE);
+ UserDereferenceObject(aspcur[i]);
NT_VERIFY(IntDestroyCurIconObject(aspcur[i]) == TRUE);
}
@@ -1472,6 +1494,9 @@
CURSORDATA cursordata;
UNICODE_STRING ustrModule, ustrRsrc;
_SEH2_VOLATILE PVOID pvBuffer;
+ CURSORDATA* aspcur;
+ DWORD* aicur;
+ PINT ajifRate;
UINT cjSize;
NTSTATUS status;
BOOL bResult;
@@ -1518,28 +1543,33 @@
goto Exit;
}
- /* Set the pointers */
- cursordata.aspcur = (CURSORDATA*)pvBuffer;
- cursordata.aicur = (DWORD*)&cursordata.aspcur[cursordata.cpcur];
- cursordata.ajifRate = (INT*)&cursordata.aicur[cursordata.cicur];
+ /* Calculate the kernel mode pointers */
+ aspcur = (CURSORDATA*)pvBuffer;
+ aicur = (DWORD*)&aspcur[cursordata.cpcur];
+ ajifRate = (INT*)&aicur[cursordata.cicur];
/* Probe and copy aspcur */
- ProbeForRead(pCursorData->aspcur, cursordata.cpcur * sizeof(CURSORDATA),
1);
- RtlCopyMemory(cursordata.aspcur,
- pCursorData->aspcur,
+ ProbeForRead(cursordata.aspcur, cursordata.cpcur * sizeof(CURSORDATA), 1);
+ RtlCopyMemory(aspcur,
+ cursordata.aspcur,
cursordata.cpcur * sizeof(CURSORDATA));
/* Probe and copy aicur */
- ProbeForRead(pCursorData->aicur, cursordata.cicur * sizeof(DWORD), 1);
- RtlCopyMemory(cursordata.aicur,
- pCursorData->aicur,
+ ProbeForRead(cursordata.aicur, cursordata.cicur * sizeof(DWORD), 1);
+ RtlCopyMemory(aicur,
+ cursordata.aicur,
cursordata.cicur * sizeof(DWORD));
/* Probe and copy ajifRate */
- ProbeForRead(pCursorData->ajifRate, cursordata.cicur * sizeof(INT), 1);
- RtlCopyMemory(cursordata.ajifRate,
- pCursorData->ajifRate,
+ ProbeForRead(cursordata.ajifRate, cursordata.cicur * sizeof(INT), 1);
+ RtlCopyMemory(ajifRate,
+ cursordata.ajifRate,
cursordata.cicur * sizeof(INT));
+
+ /* Set the new pointers */
+ cursordata.aspcur = aspcur;
+ cursordata.aicur = aicur;
+ cursordata.ajifRate = ajifRate;
}
else
{
@@ -1579,6 +1609,13 @@
ERR("Failed to copy pustrRsrc: status 0x%08lx\n", status);
goto Exit;
}
+ }
+
+ /* Make sure the caller doesn't give us invalid flags */
+ if (cursordata.CURSORF_flags & ~CURSORF_USER_MASK)
+ {
+ ERR("Invalid cursor flags: 0x%08lx\n", cursordata.CURSORF_flags);
+ goto Exit;
}
/* Acquire the global user lock */