diff --git a/win32ss/gdi/eng/mouse.c b/win32ss/gdi/eng/mouse.c index 1ea4ef827fe..ca70aacbcfd 100644 --- a/win32ss/gdi/eng/mouse.c +++ b/win32ss/gdi/eng/mouse.c @@ -425,7 +425,11 @@ EngSetPointerShape( /* Color bitmap must have the same format as the dest surface */ if (psoColor->iBitmapFormat != pso->iBitmapFormat) { - DPRINT1("Screen surface and cursor color bitmap format don't match!.\n"); + /* >>> DPRINT1 #10: el propio ya existente, pero amplíalo con los valores */ + DPRINT1( + "EngSetPointerShape: Screen surface and cursor color bitmap format don't match! " + "psoColor->iBitmapFormat=%lu pso->iBitmapFormat=%lu\n", + psoColor->iBitmapFormat, pso->iBitmapFormat); goto failure; } @@ -632,12 +636,41 @@ IntEngSetPointerShape( pfnSetPointerShape = GDIDEVFUNCS(pso).SetPointerShape; + /* >>> DPRINT1 #5: valor crudo del puntero de función y del SURFOBJ pantalla */ + DPRINT1( + "IntEngSetPointerShape: pfnSetPointerShape=%p pso=%p pso->dhpdev=%p " + "pso->iBitmapFormat=%lu psoMask=%p psoColor=%p pxlo=%p xHot=%ld yHot=%ld x=%ld y=%ld fl=0x%08lx\n", + pfnSetPointerShape, pso, pso->dhpdev, pso->iBitmapFormat, psoMask, psoColor, pxlo, xHot, yHot, x, y, fl); + if (pfnSetPointerShape) { /* Drivers expect to get an XLATEOBJ */ if (pxlo == NULL) pxlo = &gexloTrivial.xlo; + /* >>> DPRINT1 #6: dump detallado de psoMask/psoColor justo antes de cruzar al driver */ + if (psoMask) + DPRINT1( + "IntEngSetPointerShape: psoMask -> iBitmapFormat=%lu sizlBitmap=(%ld,%ld) " + "lDelta=%ld pvScan0=%p pvBits=%p\n", + psoMask->iBitmapFormat, psoMask->sizlBitmap.cx, psoMask->sizlBitmap.cy, psoMask->lDelta, + psoMask->pvScan0, psoMask->pvBits); + if (psoColor) + DPRINT1( + "IntEngSetPointerShape: psoColor -> iBitmapFormat=%lu sizlBitmap=(%ld,%ld) " + "lDelta=%ld pvScan0=%p pvBits=%p (screen fmt=%lu -> %s)\n", + psoColor->iBitmapFormat, psoColor->sizlBitmap.cx, psoColor->sizlBitmap.cy, psoColor->lDelta, + psoColor->pvScan0, psoColor->pvBits, pso->iBitmapFormat, + psoColor->iBitmapFormat == pso->iBitmapFormat ? "COINCIDE" : "*** NO COINCIDE ***"); + + DPRINT1( + "IntEngSetPointerShape: pxlo=%p flXlate=0x%08lx cEntries=%lu iSrcType=%lu iDstType=%lu\n", pxlo, + pxlo->flXlate, pxlo->cEntries, pxlo->iSrcType, pxlo->iDstType); + + /* >>> DPRINT1 #7: justo antes de la llamada indirecta — última línea segura antes del posible BSOD */ + DPRINT1("IntEngSetPointerShape: ---> ENTRANDO al driver DrvSetPointerShape en %p\n", pfnSetPointerShape); + + /* Call the driver */ ulResult = pfnSetPointerShape(pso, psoMask, @@ -650,12 +683,21 @@ IntEngSetPointerShape( prcl, fl); + + /* >>> DPRINT1 #8: si esto se imprime, el driver volvió con vida */ + DPRINT1("IntEngSetPointerShape: <--- SALIÓ del driver, ulResult=%lu\n", ulResult); + /* Check if the driver accepted it */ if (ulResult == SPS_ACCEPT_NOEXCLUDE) bHardwarePointer = TRUE; bSoftwarePointer = !bHardwarePointer; } + else + { + /* >>> DPRINT1 #9: no hay función de driver instalada — se usará el cursor software */ + DPRINT1("IntEngSetPointerShape: pfnSetPointerShape es NULL, se usará EngSetPointerShape\n"); + } if (bSoftwarePointer) { @@ -745,7 +787,7 @@ GreSetPointerShape( psurfMask = NULL; } - /* Check for color bitmap */ +/* Check for color bitmap */ if (hbmColor) { /* We have one, lock it */ @@ -755,11 +797,36 @@ GreSetPointerShape( { /* Create an XLATEOBJ, no mono support */ EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurf->ppal, 0, 0, 0); + + /* >>> DPRINT1 #1: estado del bitmap de color y de la paleta */ + DPRINT1( + "GreSetPointerShape: hbmColor=%p psurfColor=%p iBitmapFormat=%lu " + "sizlBitmap=(%ld,%ld) lDelta=%ld pvScan0=%p ppalColor=%p ppalScreen=%p\n", + hbmColor, psurfColor, psurfColor->SurfObj.iBitmapFormat, psurfColor->SurfObj.sizlBitmap.cx, + psurfColor->SurfObj.sizlBitmap.cy, psurfColor->SurfObj.lDelta, psurfColor->SurfObj.pvScan0, + psurfColor->ppal, psurf->ppal); + } + else + { + /* >>> DPRINT1 #2: SURFACE_ShareLockSurface falló para hbmColor */ + DPRINT1("GreSetPointerShape: SURFACE_ShareLockSurface(hbmColor=%p) devolvió NULL\n", hbmColor); } } else psurfColor = NULL; + /* >>> DPRINT1 #3: estado de la máscara y de la superficie de pantalla destino */ +DPRINT1( + "GreSetPointerShape: hbmMask=%p psurfMask=%p psurf(screen)=%p " + "screen.iBitmapFormat=%lu screen.sizlBitmap=(%ld,%ld) fl=0x%08lx\n", + hbmMask, + psurfMask, + psurf, + psurf->SurfObj.iBitmapFormat, + psurf->SurfObj.sizlBitmap.cx, + psurf->SurfObj.sizlBitmap.cy, + fl); + /* We must have a valid surface in case of alpha bitmap */ ASSERT(((fl & SPS_ALPHA) && psurfColor) || !(fl & SPS_ALPHA)); @@ -775,6 +842,16 @@ GreSetPointerShape( &pdc->ppdev->Pointer.Exclude, fl | SPS_CHANGE); + /* >>> DPRINT1 #4: resultado devuelto por toda la cadena */ + DPRINT1( + "GreSetPointerShape: IntEngSetPointerShape devolvió ulResult=%lu " + "(%s)\n", + ulResult, + ulResult == SPS_ACCEPT_NOEXCLUDE ? "SPS_ACCEPT_NOEXCLUDE" + : ulResult == SPS_DECLINE ? "SPS_DECLINE" + : ulResult == SPS_ERROR ? "SPS_ERROR" + : "?"); + /* Cleanup */ if (psurfColor) { diff --git a/win32ss/user/ntuser/cursoricon.c b/win32ss/user/ntuser/cursoricon.c index 84972a744b4..755372b09f3 100644 --- a/win32ss/user/ntuser/cursoricon.c +++ b/win32ss/user/ntuser/cursoricon.c @@ -20,6 +20,7 @@ */ #include +#include DBG_DEFAULT_CHANNEL(UserIcon); SYSTEM_CURSORINFO gSysCursorInfo; @@ -338,6 +339,13 @@ FreeCurIconObject( { PCURICON_OBJECT CurIcon = Object; + /* >>> DPRINT1 RACE-DESTROY: entrada a la liberación real del objeto */ + DPRINT1("RACE-DESTROY tid=%p tick=%lu CurIcon=%p ENTRA a FreeCurIconObject " + "hbmMask=%p hbmColor=%p hbmAlpha=%p ACON=%d\n", + PsGetCurrentThreadId(), KeQueryInterruptTime(), CurIcon, + CurIcon->hbmMask, CurIcon->hbmColor, CurIcon->hbmAlpha, + (CurIcon->CURSORF_flags & CURSORF_ACON) ? 1 : 0); + if (!(CurIcon->CURSORF_flags & CURSORF_ACON)) { HBITMAP bmpMask = CurIcon->hbmMask; @@ -347,28 +355,57 @@ FreeCurIconObject( /* Delete bitmaps */ if (bmpMask) { + /* >>> DPRINT1 RACE-DESTROY: justo antes de borrar hbmMask */ + DPRINT1("RACE-DESTROY tid=%p tick=%lu CurIcon=%p ---> borrando hbmMask=%p\n", + PsGetCurrentThreadId(), KeQueryInterruptTime(), CurIcon, bmpMask); + GreSetObjectOwner(bmpMask, GDI_OBJ_HMGR_POWNED); NT_VERIFY(GreDeleteObject(bmpMask) == TRUE); CurIcon->hbmMask = NULL; + + /* >>> DPRINT1 RACE-DESTROY: justo después, handle ya liberado/reciclable */ + DPRINT1("RACE-DESTROY tid=%p tick=%lu CurIcon=%p <--- hbmMask=%p BORRADO " + "(handle libre para reciclar)\n", + PsGetCurrentThreadId(), KeQueryInterruptTime(), CurIcon, bmpMask); } if (bmpColor) { + /* >>> DPRINT1 RACE-DESTROY: justo antes de borrar hbmColor */ + DPRINT1("RACE-DESTROY tid=%p tick=%lu CurIcon=%p ---> borrando hbmColor=%p\n", + PsGetCurrentThreadId(), KeQueryInterruptTime(), CurIcon, bmpColor); + GreSetObjectOwner(bmpColor, GDI_OBJ_HMGR_POWNED); NT_VERIFY(GreDeleteObject(bmpColor) == TRUE); CurIcon->hbmColor = NULL; + + /* >>> DPRINT1 RACE-DESTROY: justo después */ + DPRINT1("RACE-DESTROY tid=%p tick=%lu CurIcon=%p <--- hbmColor=%p BORRADO " + "(handle libre para reciclar)\n", + PsGetCurrentThreadId(), KeQueryInterruptTime(), CurIcon, bmpColor); } if (bmpAlpha) { + /* >>> DPRINT1 RACE-DESTROY: justo antes de borrar hbmAlpha */ + DPRINT1("RACE-DESTROY tid=%p tick=%lu CurIcon=%p ---> borrando hbmAlpha=%p\n", + PsGetCurrentThreadId(), KeQueryInterruptTime(), CurIcon, bmpAlpha); + GreSetObjectOwner(bmpAlpha, GDI_OBJ_HMGR_POWNED); NT_VERIFY(GreDeleteObject(bmpAlpha) == TRUE); CurIcon->hbmAlpha = NULL; + + /* >>> DPRINT1 RACE-DESTROY: justo después — este es el más importante: + * si el siguiente CreateBitmap/CreateDIBitmap de un cursor NUEVO recicla + * este mismo handle, y coincide en tick con un RACE-CHK de otro hilo, + * tenemos la prueba definitiva */ + DPRINT1("RACE-DESTROY tid=%p tick=%lu CurIcon=%p <--- hbmAlpha=%p BORRADO " + "(handle libre para reciclar)\n", + PsGetCurrentThreadId(), KeQueryInterruptTime(), CurIcon, bmpAlpha); } } else { PACON AniCurIcon = (PACON)CurIcon; UINT i; - for (i = 0; i < AniCurIcon->cpcur; i++) { UserDereferenceObject(AniCurIcon->aspcur[i]); @@ -376,7 +413,6 @@ FreeCurIconObject( } ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR); } - if (CurIcon->CURSORF_flags & CURSORF_LRSHARED) { if (!IS_INTRESOURCE(CurIcon->strName.Buffer)) @@ -386,7 +422,6 @@ FreeCurIconObject( CurIcon->strName.Buffer = NULL; CurIcon->atomModName = 0; } - /* Finally free the thing */ FreeProcMarkObject(CurIcon); } @@ -1211,6 +1246,11 @@ IntSetCursorData( } /* Now set the new cursor data */ + /* >>> DPRINT1 RACE-WRITE: qué hilo escribe los campos del CURICON_OBJECT + * y con qué valores, para poder cruzarlo con los timestamps de RACE-CHK */ + DPRINT1("RACE-WRITE tid=%p tick=%lu pcur=%p ANTES: hbmMask=%p hbmColor=%p hbmAlpha=%p\n", + PsGetCurrentThreadId(), KeQueryInterruptTime(), pcur, + pcur->hbmMask, pcur->hbmColor, pcur->hbmAlpha); pcur->atomModName = atomModName; pcur->rt = pcursordata->rt; pcur->CURSORF_flags = pcursordata->CURSORF_flags & CURSORF_USER_MASK; @@ -1219,6 +1259,10 @@ IntSetCursorData( pcur->hbmMask = pcursordata->hbmMask; pcur->hbmColor = pcursordata->hbmColor; pcur->hbmAlpha = pcursordata->hbmAlpha; + /* >>> DPRINT1 RACE-WRITE: valores DESPUÉS de la asignación */ + DPRINT1("RACE-WRITE tid=%p tick=%lu pcur=%p DESPUÉS: hbmMask=%p hbmColor=%p hbmAlpha=%p\n", + PsGetCurrentThreadId(), KeQueryInterruptTime(), pcur, + pcur->hbmMask, pcur->hbmColor, pcur->hbmAlpha); pcur->rcBounds.left = 0; pcur->rcBounds.top = 0; pcur->rcBounds.right = pcursordata->cx; diff --git a/win32ss/user/ntuser/msgqueue.c b/win32ss/user/ntuser/msgqueue.c index 13a3a106d7d..2103cee5b33 100644 --- a/win32ss/user/ntuser/msgqueue.c +++ b/win32ss/user/ntuser/msgqueue.c @@ -9,6 +9,7 @@ */ #include +#include DBG_DEFAULT_CHANNEL(UserMsgQ); /* GLOBALS *******************************************************************/ @@ -141,6 +142,34 @@ UserSetCursor( FIXME("Should animate the cursor, using only the first frame now.\n"); CursorFrame = ((PACON)NewCursor)->aspcur[0]; } + + /* >>> DPRINT1 RACE-1/2/3: leer hbmAlpha tres veces por separado, como + * hace el ternario original, para detectar si cambia entre lecturas */ + { + HANDLE hCurrentThread = PsGetCurrentThreadId(); + HBITMAP hAlphaRead1 = CursorFrame->hbmAlpha; + DPRINT1("RACE-CHK tid=%p tick=%lu NewCursor=%p CursorFrame=%p " + "[lectura#1 hbmAlpha]=%p hbmMask=%p hbmColor=%p\n", + hCurrentThread, KeQueryInterruptTime(), NewCursor, CursorFrame, + hAlphaRead1, NewCursor->hbmMask, NewCursor->hbmColor); + + HBITMAP hAlphaRead2 = CursorFrame->hbmAlpha; + DPRINT1("RACE-CHK tid=%p [lectura#2 hbmAlpha]=%p %s\n", + hCurrentThread, hAlphaRead2, + hAlphaRead2 != hAlphaRead1 ? "*** CAMBIÓ ENTRE LECTURA 1 Y 2 ***" : "igual"); + + HBITMAP hAlphaRead3 = CursorFrame->hbmAlpha; + DPRINT1("RACE-CHK tid=%p [lectura#3 hbmAlpha]=%p %s\n", + hCurrentThread, hAlphaRead3, + hAlphaRead3 != hAlphaRead2 ? "*** CAMBIÓ ENTRE LECTURA 2 Y 3 ***" : "igual"); + + DPRINT1("RACE-CHK tid=%p ---> parámetros finales que se enviarán: " + "hbmMask_param=%p hbmColor_param=%p fl=0x%08lx\n", + hCurrentThread, + hAlphaRead1 ? NULL : NewCursor->hbmMask, + hAlphaRead2 ? hAlphaRead2 : NewCursor->hbmColor, + hAlphaRead3 ? SPS_ALPHA : 0); + } GreSetPointerShape(hdcScreen, CursorFrame->hbmAlpha ? NULL : NewCursor->hbmMask, CursorFrame->hbmAlpha ? NewCursor->hbmAlpha : NewCursor->hbmColor, @@ -671,6 +700,35 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook if(CurInfo->CurrentCursorObject != MessageQueue->CursorObject) { /* Call GDI to set the new screen cursor */ + /* >>> DPRINT1 RACE-CHK: leer hbmAlpha tres veces por separado, + * como hace el ternario original, para detectar si cambia entre lecturas */ + { + HANDLE hCurrentThread = PsGetCurrentThreadId(); + PCURICON_OBJECT pCurObj = MessageQueue->CursorObject; + HBITMAP hAlphaRead1 = pCurObj->hbmAlpha; + + DPRINT1("RACE-CHK tid=%p tick=%lu pCurObj=%p " + "[lectura#1 hbmAlpha]=%p hbmMask=%p hbmColor=%p\n", + hCurrentThread, KeQueryInterruptTime(), pCurObj, + hAlphaRead1, pCurObj->hbmMask, pCurObj->hbmColor); + + HBITMAP hAlphaRead2 = pCurObj->hbmAlpha; + DPRINT1("RACE-CHK tid=%p [lectura#2 hbmAlpha]=%p %s\n", + hCurrentThread, hAlphaRead2, + hAlphaRead2 != hAlphaRead1 ? "*** CAMBIÓ ENTRE LECTURA 1 Y 2 ***" : "igual"); + + HBITMAP hAlphaRead3 = pCurObj->hbmAlpha; + DPRINT1("RACE-CHK tid=%p [lectura#3 hbmAlpha]=%p %s\n", + hCurrentThread, hAlphaRead3, + hAlphaRead3 != hAlphaRead2 ? "*** CAMBIÓ ENTRE LECTURA 2 Y 3 ***" : "igual"); + + DPRINT1("RACE-CHK tid=%p ---> parámetros finales que se enviarán: " + "hbmMask_param=%p hbmColor_param=%p fl=0x%08lx\n", + hCurrentThread, + hAlphaRead1 ? NULL : pCurObj->hbmMask, + hAlphaRead2 ? hAlphaRead2 : pCurObj->hbmColor, + hAlphaRead3 ? SPS_ALPHA : 0); + } GreSetPointerShape(hdcScreen, MessageQueue->CursorObject->hbmAlpha ? NULL : MessageQueue->CursorObject->hbmMask,