* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Win32k subsystem
* PURPOSE: Cursor and icon functions
- * FILE: subsystems/win32/win32k/ntuser/cursoricon.c
+ * FILE: win32ss/user/ntuser/cursoricon.c
* PROGRAMER: ReactOS Team
*/
/*
return NULL;
}
- CurIcon = (PCURICON_OBJECT)UserReferenceObjectByHandle(hCurIcon, otCursorIcon);
+ CurIcon = (PCURICON_OBJECT)UserReferenceObjectByHandle(hCurIcon, TYPE_CURSOR);
if (!CurIcon)
{
/* We never set ERROR_INVALID_ICON_HANDLE. lets hope noone ever checks for it */
ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon)
{
PPROCESSINFO Win32Process;
+ PLIST_ENTRY ListEntry;
PCURICON_PROCESS Current;
Win32Process = PsGetCurrentProcessWin32Process();
- LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
+ ListEntry = CurIcon->ProcessList.Flink;
+ while (ListEntry != &CurIcon->ProcessList)
{
+ Current = CONTAINING_RECORD(ListEntry, CURICON_PROCESS, ListEntry);
+ ListEntry = ListEntry->Flink;
if (Current->Process == Win32Process)
{
/* Already registered for this process */
}
InsertHeadList(&CurIcon->ProcessList, &Current->ListEntry);
Current->Process = Win32Process;
+ IntReferenceProcessInfo(Win32Process);
return TRUE;
}
IntFindExistingCurIconObject(HMODULE hModule,
HRSRC hRsrc, LONG cx, LONG cy)
{
+ PLIST_ENTRY ListEntry;
PCURICON_OBJECT CurIcon;
- LIST_FOR_EACH(CurIcon, &gCurIconList, CURICON_OBJECT, ListEntry)
+ ListEntry = gCurIconList.Flink;
+ while (ListEntry != &gCurIconList)
{
+ CurIcon = CONTAINING_RECORD(ListEntry, CURICON_OBJECT, ListEntry);
+ ListEntry = ListEntry->Flink;
- // if (NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) // <- huh????
+ // if (NT_SUCCESS(UserReferenceObjectByPointer(Object, TYPE_CURSOR))) // <- huh????
// UserReferenceObject( CurIcon);
// {
if ((CurIcon->hModule == hModule) && (CurIcon->hRsrc == hRsrc))
return NULL;
}
-PCURICON_OBJECT
-IntCreateCurIconHandle()
+HANDLE
+IntCreateCurIconHandle(BOOLEAN Anim)
{
PCURICON_OBJECT CurIcon;
HANDLE hCurIcon;
- CurIcon = UserCreateObject(gHandleTable, NULL, NULL, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT));
+ CurIcon = UserCreateObject(
+ gHandleTable,
+ NULL,
+ GetW32ThreadInfo(),
+ &hCurIcon,
+ TYPE_CURSOR,
+ sizeof(CURICON_OBJECT));
if (!CurIcon)
{
CurIcon->Self = hCurIcon;
InitializeListHead(&CurIcon->ProcessList);
- if (! ReferenceCurIconByProcess(CurIcon))
+ if (!ReferenceCurIconByProcess(CurIcon))
{
ERR("Failed to add process\n");
- UserDeleteObject(hCurIcon, otCursorIcon);
+ UserDeleteObject(hCurIcon, TYPE_CURSOR);
UserDereferenceObject(CurIcon);
return NULL;
}
InsertHeadList(&gCurIconList, &CurIcon->ListEntry);
- return CurIcon;
+ UserDereferenceObject(CurIcon);
+
+ return hCurIcon;
}
BOOLEAN FASTCALL
-IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOL ProcessCleanup)
+IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi)
{
PSYSTEM_CURSORINFO CurInfo;
HBITMAP bmpMask, bmpColor;
- BOOLEAN Ret;
- PCURICON_PROCESS Current = NULL;
- PPROCESSINFO W32Process = PsGetCurrentProcessWin32Process();
+ BOOLEAN Ret, bListEmpty, bFound = FALSE;
+ PLIST_ENTRY ListEntry;
+ PCURICON_PROCESS Current;
- /* Private objects can only be destroyed by their own process */
- if (NULL == CurIcon->hModule)
- {
- ASSERT(CurIcon->ProcessList.Flink->Flink == &CurIcon->ProcessList);
- Current = CONTAINING_RECORD(CurIcon->ProcessList.Flink, CURICON_PROCESS, ListEntry);
- if (Current->Process != W32Process)
- {
- ERR("Trying to destroy private icon/cursor of another process\n");
- return FALSE;
- }
- }
- else if (! ProcessCleanup)
- {
- TRACE("Trying to destroy shared icon/cursor\n");
- return FALSE;
- }
+ /* For handles created without any data (error handling) */
+ if(IsListEmpty(&CurIcon->ProcessList))
+ goto emptyList;
/* Now find this process in the list of processes referencing this object and
remove it from that list */
- LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
+ ListEntry = CurIcon->ProcessList.Flink;
+ while (ListEntry != &CurIcon->ProcessList)
{
- if (Current->Process == W32Process)
+ Current = CONTAINING_RECORD(ListEntry, CURICON_PROCESS, ListEntry);
+ ListEntry = ListEntry->Flink;
+ if (Current->Process == ppi)
{
- RemoveEntryList(&Current->ListEntry);
+ bFound = TRUE;
+ bListEmpty = RemoveEntryList(&Current->ListEntry);
+ IntDereferenceProcessInfo(ppi);
break;
}
}
+ if(!bFound)
+ {
+ /* This object doesn't belong to this process */
+ EngSetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
ExFreeToPagedLookasideList(pgProcessLookasideList, Current);
/* If there are still processes referencing this object we can't destroy it yet */
- if (! IsListEmpty(&CurIcon->ProcessList))
+ if (!bListEmpty)
{
+ if(CurIcon->head.ppi == ppi)
+ {
+ /* Set the first process of the list as owner */
+ Current = CONTAINING_RECORD(CurIcon->ProcessList.Flink, CURICON_PROCESS, ListEntry);
+ UserSetObjectOwner(CurIcon, TYPE_CURSOR, Current->Process);
+ }
+ UserDereferenceObject(CurIcon);
return TRUE;
}
-
- if (! ProcessCleanup)
- {
- RemoveEntryList(&CurIcon->ListEntry);
- }
+emptyList:
+ /* Remove it from the list */
+ RemoveEntryList(&CurIcon->ListEntry);
CurInfo = IntGetSysCursorInfo();
/* We were given a pointer, no need to keep the reference anylonger! */
UserDereferenceObject(CurIcon);
- Ret = UserDeleteObject(CurIcon->Self, otCursorIcon);
+ Ret = UserDeleteObject(CurIcon->Self, TYPE_CURSOR);
return Ret;
}
-VOID FASTCALL
-IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
+HCURSOR FASTCALL
+IntSetCursor(
+ HCURSOR hCursor)
{
- PCURICON_OBJECT CurIcon, tmp;
- PCURICON_PROCESS ProcessData;
+ PCURICON_OBJECT pcurOld, pcurNew;
+ HCURSOR hOldCursor = NULL;
- LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry)
+ if (hCursor)
{
- UserReferenceObject(CurIcon);
- // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon)))
- {
- LIST_FOR_EACH(ProcessData, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
- {
- if (Win32Process == ProcessData->Process)
- {
- RemoveEntryList(&CurIcon->ListEntry);
- IntDestroyCurIconObject(CurIcon, TRUE);
- CurIcon = NULL;
- break;
- }
- }
-
-// UserDereferenceObject(Object);
- }
-
- if (CurIcon)
+ pcurNew = UserGetCurIconObject(hCursor);
+ if (!pcurNew)
{
- UserDereferenceObject(CurIcon);
+ EngSetLastError(ERROR_INVALID_CURSOR_HANDLE);
+ goto leave;
}
}
+ else
+ {
+ pcurNew = NULL;
+ }
+ pcurOld = UserSetCursor(pcurNew, FALSE);
+ if (pcurOld)
+ {
+ hOldCursor = (HCURSOR)pcurOld->Self;
+ UserDereferenceObject(pcurOld);
+ }
+leave:
+ return hOldCursor;
}
+BOOL FASTCALL
+IntDestroyCursor(
+ HANDLE hCurIcon,
+ BOOL bForce)
+{
+ PCURICON_OBJECT CurIcon;
+ BOOL ret;
+
+ if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
+ {
+ return FALSE;
+ }
+
+ ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process());
+ /* Note: IntDestroyCurIconObject will remove our reference for us! */
+
+ return ret;
+}
/*
* @implemented
ProbeForWrite(IconInfo, sizeof(ICONINFO), 1);
RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO));
+ /// @todo Implement support for lpInstName
+ if (lpInstName)
+ {
+ RtlInitEmptyUnicodeString(lpInstName, NULL, 0);
+ }
+
+ /// @todo Implement support for lpResName
+ if (lpResName)
+ {
+ RtlInitEmptyUnicodeString(lpResName, NULL, 0);
+ }
+
if (pbpp)
{
ProbeForWrite(pbpp, sizeof(DWORD), 1);
BOOL
APIENTRY
NtUserDestroyCursor(
- HANDLE hCurIcon,
- DWORD Unknown)
+ _In_ HANDLE hCurIcon,
+ _In_ BOOL bForce)
{
PCURICON_OBJECT CurIcon;
BOOL ret;
RETURN(FALSE);
}
- ret = IntDestroyCurIconObject(CurIcon, FALSE);
+ ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process());
/* Note: IntDestroyCurIconObject will remove our reference for us! */
RETURN(ret);
RECTL rcDest, rcSrc;
CLIPOBJ* pdcClipObj = NULL;
EXLATEOBJ exlo;
-
+
/* Stupid case */
if((diFlags & DI_NORMAL) == 0)
{
hbmMask = pIcon->IconInfo.hbmMask;
hbmColor = pIcon->IconInfo.hbmColor;
-
+
if (istepIfAniCur)
ERR("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
-
+
/*
- * Get our objects.
+ * Get our objects.
* Shared locks are enough, we are only reading those bitmaps
*/
psurfMask = SURFACE_ShareLockSurface(hbmMask);
ERR("Unable to lock the mask surface.\n");
return FALSE;
}
-
+
/* Color bitmap is not mandatory */
if(hbmColor == NULL)
{
SURFACE_ShareUnlockSurface(psurfMask);
return FALSE;
}
-
+
/* Set source rect */
RECTL_vSetRect(&rcSrc, 0, 0, pIcon->Size.cx, pIcon->Size.cy);
if (!cxWidth)
{
if(diFlags & DI_DEFAULTSIZE)
- cxWidth = pIcon->IconInfo.fIcon ?
+ cxWidth = pIcon->IconInfo.fIcon ?
UserGetSystemMetrics(SM_CXICON) : UserGetSystemMetrics(SM_CXCURSOR);
else
cxWidth = pIcon->Size.cx;
}
-
+
/* Fix height parameter, if needed */
if (!cyHeight)
{
if(diFlags & DI_DEFAULTSIZE)
- cyHeight = pIcon->IconInfo.fIcon ?
+ cyHeight = pIcon->IconInfo.fIcon ?
UserGetSystemMetrics(SM_CYICON) : UserGetSystemMetrics(SM_CYCURSOR);
else
cyHeight = pIcon->Size.cy;
/* Yes: Allocate and paint the offscreen surface */
EBRUSHOBJ eboFill;
PBRUSH pbrush = BRUSH_ShareLockBrush(hbrFlickerFreeDraw);
-
+
TRACE("Performing off-screen rendering.\n");
-
+
if(!pbrush)
{
ERR("Failed to get brush object.\n");
return FALSE;
}
+ if (!psurfColor)
+ {
+ ERR("Attention HAX FIX API DrawIconEx TEST Line 37: psurfColor is NULL going with Mask!\n");
+ psurfColor = SURFACE_ShareLockSurface(hbmMask);
+ }
+
psurfOffScreen = SURFACE_AllocSurface(STYPE_BITMAP,
cxWidth, cyHeight, psurfColor->SurfObj.iBitmapFormat,
0, 0, NULL);
BRUSH_ShareUnlockBrush(pbrush);
return FALSE;
}
-
+
/* Paint the brush */
EBRUSHOBJ_vInit(&eboFill, pbrush, psurfOffScreen, 0x00FFFFFF, 0, NULL);
RECTL_vSetRect(&rcDest, 0, 0, cxWidth, cyHeight);
-
+
Ret = IntEngBitBlt(&psurfOffScreen->SurfObj,
NULL,
NULL,
/* Clean up everything */
EBRUSHOBJ_vCleanup(&eboFill);
BRUSH_ShareUnlockBrush(pbrush);
-
+
if(!Ret)
{
ERR("Failed to paint the off-screen surface.\n");
GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject);
return FALSE;
}
-
+
/* We now have our destination surface */
psurfDest = psurfOffScreen;
}
{
/* We directly draw to the DC */
TRACE("Performing on screen rendering.\n");
-
+
psurfOffScreen = NULL;
pdc = DC_LockDc(hDc);
if(!pdc)
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);
-
+ DC_vPrepareDCsForBlit(pdc, &rcDest, NULL, NULL);
+
/* Get the clip object */
- pdcClipObj = pdc->rosdc.CombinedClip;
-
+ pdcClipObj = &pdc->co.ClipObj;
+
/* We now have our destination surface and rectangle */
psurfDest = pdc->dclevel.pSurface;
-
+
if(psurfDest == NULL)
{
/* Empty DC */
ptr += 4;
}
}
-
+
/* Initialize color translation object */
EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xFFFFFFFF, 0xFFFFFFFF, 0);
-
+
/* Now do it */
Ret = IntEngAlphaBlend(&psurfDest->SurfObj,
&psurf->SurfObj,
&rcDest,
&rcSrc,
&blendobj);
-
+
EXLATEOBJ_vCleanup(&exlo);
-
+
CleanupAlpha:
if(psurf) SURFACE_ShareUnlockSurface(psurf);
if(hsurfCopy) NtGdiDeleteObjectApp(hsurfCopy);
if (diFlags & DI_MASK)
{
DWORD rop4 = (diFlags & DI_IMAGE) ? ROP4_SRCAND : ROP4_SRCCOPY;
-
+
EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0);
-
+
Ret = IntEngStretchBlt(&psurfDest->SurfObj,
&psurfMask->SurfObj,
NULL,
NULL,
NULL,
rop4);
-
+
EXLATEOBJ_vCleanup(&exlo);
if(!Ret)
if (psurfColor)
{
DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY ;
-
+
EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0);
-
+
Ret = IntEngStretchBlt(&psurfDest->SurfObj,
&psurfColor->SurfObj,
NULL,
NULL,
NULL,
rop4);
-
+
EXLATEOBJ_vCleanup(&exlo);
if(!Ret)
/* Mask bitmap holds the information in its bottom half */
DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY;
RECTL_vOffsetRect(&rcSrc, 0, pIcon->Size.cy);
-
+
EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0);
-
+
Ret = IntEngStretchBlt(&psurfDest->SurfObj,
&psurfMask->SurfObj,
NULL,
NULL,
NULL,
rop4);
-
+
EXLATEOBJ_vCleanup(&exlo);
if(!Ret)
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);
-
+ DC_vPrepareDCsForBlit(pdc, &rcDest, NULL, NULL);
+
/* Get the clip object */
- pdcClipObj = pdc->rosdc.CombinedClip;
-
+ pdcClipObj = &pdc->co.ClipObj;
+
/* We now have our destination surface and rectangle */
psurfDest = pdc->dclevel.pSurface;
if(!psurfDest)
DC_UnlockDc(pdc);
goto Cleanup2;
}
-
+
/* Color translation */
EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0);
-
+
/* Blt it! */
Ret = IntEngBitBlt(&psurfDest->SurfObj,
&psurfOffScreen->SurfObj,
NULL,
NULL,
ROP4_SRCCOPY);
-
+
EXLATEOBJ_vCleanup(&exlo);
}
Cleanup:
DC_vFinishBlit(pdc, NULL);
DC_UnlockDc(pdc);
}
-
+
Cleanup2:
/* Delete off screen rendering surface */
if(psurfOffScreen)
GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject);
-
+
/* Unlock other surfaces */
SURFACE_ShareUnlockSurface(psurfMask);
if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
return Ret;
}
+/*
+ * @unimplemented
+ */
+HCURSOR
+NTAPI
+NtUserGetCursorFrameInfo(
+ HCURSOR hCursor,
+ DWORD istep,
+ INT* rate_jiffies,
+ DWORD* num_steps)
+{
+ STUB
+
+ return 0;
+}
+
/* EOF */