BOOL TestAllocFailCount( VOID ) /*++ Routine Description: Determines whether the memory allocator should return failure for testing purposes. Arguments: Return Value: TRUE - Alloc should fail FALSE - Alloc should succeed --*/ { EngAcquireSemaphore(hsem); gAllocCount++; EngReleaseSemaphore(hsem); #if 0 if ( gFailCount != 0 && !gFailCountHit && gFailCount <= gAllocCount ) { gFailCountHit = TRUE; return TRUE; } #endif return FALSE; }
VOID APIENTRY EngUnloadImage( _In_ HANDLE hModule) { PLDEVOBJ pldev = (PLDEVOBJ)hModule; /* Make sure the LDEV is in the list */ ASSERT(pldev->pldevPrev || pldev->pldevNext); /* Lock loader */ EngAcquireSemaphore(ghsemLDEVList); /* Decrement reference count */ pldev->cRefs--; /* No more references left? */ if (pldev->cRefs == 0) { /* Remove ldev from the list */ if (pldev->pldevPrev) pldev->pldevPrev->pldevNext = pldev->pldevNext; if (pldev->pldevNext) pldev->pldevNext->pldevPrev = pldev->pldevPrev; /* Unload the image and free the LDEV */ LDEVOBJ_vUnloadImage(pldev); LDEVOBJ_vFreeLDEV(pldev); } /* Unlock loader */ EngReleaseSemaphore(ghsemLDEVList); }
void Test_EngReleaseSemaphore() { HSEMAPHORE hsem; PRTL_CRITICAL_SECTION lpcrit; hsem = EngCreateSemaphore(); ok(hsem != NULL, "EngCreateSemaphore failed\n"); if (!hsem) return; lpcrit = (PRTL_CRITICAL_SECTION)hsem; EngAcquireSemaphore(hsem); EngReleaseSemaphore(hsem); ok(lpcrit->LockCount != 0, "lpcrit->LockCount=%ld\n", lpcrit->LockCount); ok(lpcrit->RecursionCount == 0, "lpcrit->RecursionCount=%ld\n", lpcrit->RecursionCount); ok(lpcrit->OwningThread == 0, "lpcrit->OwningThread=%p\n", lpcrit->OwningThread); ok(lpcrit->LockSemaphore == 0, "lpcrit->LockSemaphore=%p\n", lpcrit->LockSemaphore); ok(lpcrit->SpinCount == 0, "lpcrit->SpinCount=%ld\n", lpcrit->SpinCount); ok(lpcrit->DebugInfo != NULL, "no DebugInfo\n"); if (lpcrit->DebugInfo) { ok(lpcrit->DebugInfo->Type == 0, "DebugInfo->Type=%d\n", lpcrit->DebugInfo->Type); ok(lpcrit->DebugInfo->CreatorBackTraceIndex == 0, "DebugInfo->CreatorBackTraceIndex=%d\n", lpcrit->DebugInfo->CreatorBackTraceIndex); ok(lpcrit->DebugInfo->EntryCount == 0, "DebugInfo->EntryCount=%ld\n", lpcrit->DebugInfo->EntryCount); ok(lpcrit->DebugInfo->ContentionCount == 0, "DebugInfo->ContentionCount=%ld\n", lpcrit->DebugInfo->ContentionCount); } EngDeleteSemaphore(hsem); }
DHPDEV APIENTRY NtGdiGetDhpdev( IN HDEV hdev) { PPDEVOBJ ppdev; DHPDEV dhpdev = NULL; /* Check parameter */ if (!hdev || (PCHAR)hdev < (PCHAR)MmSystemRangeStart) return NULL; /* Lock PDEV list */ EngAcquireSemaphore(ghsemPDEV); /* Walk through the list of PDEVs */ for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext) { /* Compare with the given HDEV */ if (ppdev == hdev) { /* Found the PDEV! Get it's dhpdev and break */ dhpdev = ppdev->dhpdev; break; } } /* Unlock PDEV list */ EngReleaseSemaphore(ghsemPDEV); return dhpdev; }
VOID vAcquireCrtc(PDEV* ppdev) { EngAcquireSemaphore(ppdev->csCrtc); if (gbCrtcCriticalSection) RIP("Had already acquired Critical Section"); gbCrtcCriticalSection = TRUE; }
PGRAPHICS_DEVICE NTAPI EngpFindGraphicsDevice( _In_opt_ PUNICODE_STRING pustrDevice, _In_ ULONG iDevNum, _In_ DWORD dwFlags) { UNICODE_STRING ustrCurrent; PGRAPHICS_DEVICE pGraphicsDevice; ULONG i; TRACE("EngpFindGraphicsDevice('%wZ', %lu, 0x%lx)\n", pustrDevice, iDevNum, dwFlags); /* Lock list */ EngAcquireSemaphore(ghsemGraphicsDeviceList); if (pustrDevice && pustrDevice->Buffer) { /* Loop through the list of devices */ for (pGraphicsDevice = gpGraphicsDeviceFirst; pGraphicsDevice; pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice) { /* Compare the device name */ RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName); if (RtlEqualUnicodeString(&ustrCurrent, pustrDevice, FALSE)) { break; } } } else { /* Loop through the list of devices */ for (pGraphicsDevice = gpGraphicsDeviceFirst, i = 0; pGraphicsDevice && i < iDevNum; pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice, i++); } /* Unlock list */ EngReleaseSemaphore(ghsemGraphicsDeviceList); return pGraphicsDevice; }
VOID NTAPI GreMovePointer( _In_ HDC hdc, _In_ LONG x, _In_ LONG y) { PDC pdc; PRECTL prcl; /* Lock the DC */ pdc = DC_LockDc(hdc); if (!pdc) { DPRINT1("Failed to lock the DC.\n"); return; } ASSERT(pdc->dctype == DCTYPE_DIRECT); /* Acquire PDEV lock */ EngAcquireSemaphore(pdc->ppdev->hsemDevLock); /* Check if we need to move it */ if(pdc->ppdev->SafetyRemoveLevel == 0) { /* Store the cursor exclude position in the PDEV */ prcl = &pdc->ppdev->Pointer.Exclude; /* Call Eng/Drv function */ pdc->ppdev->pfnMovePointer(&pdc->ppdev->pSurface->SurfObj, x, y, prcl); } /* Release PDEV lock */ EngReleaseSemaphore(pdc->ppdev->hsemDevLock); /* Unlock the DC */ DC_UnlockDc(pdc); }
/* rc1 and rc2 are the rectangles where we want to draw or * from where we take pixels. */ VOID FASTCALL DC_vPrepareDCsForBlit(PDC pdc1, RECT rc1, PDC pdc2, RECT rc2) { PDC pdcFirst, pdcSecond; PRECT prcFirst, prcSecond; /* Update brushes */ if (pdc1->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(pdc1); if (pdc1->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) DC_vUpdateLineBrush(pdc1); if(pdc1->pdcattr->ulDirty_ & DIRTY_TEXT) DC_vUpdateTextBrush(pdc1); /* Lock them in good order */ if(pdc2) { if((ULONG_PTR)pdc1->ppdev->hsemDevLock >= (ULONG_PTR)pdc2->ppdev->hsemDevLock) { pdcFirst = pdc1; prcFirst = &rc1; pdcSecond = pdc2; prcSecond = &rc2; } else { pdcFirst = pdc2; prcFirst = &rc2; pdcSecond = pdc1; prcSecond = &rc1; } } else { pdcFirst = pdc1 ; prcFirst = &rc1; pdcSecond = NULL; prcSecond = NULL; } if(pdcFirst && pdcFirst->dctype == DCTYPE_DIRECT) { EngAcquireSemaphore(pdcFirst->ppdev->hsemDevLock); MouseSafetyOnDrawStart(pdcFirst->ppdev, prcFirst->left, prcFirst->top, prcFirst->right, prcFirst->bottom) ; /* Update surface if needed */ if(pdcFirst->ppdev->pSurface != pdcFirst->dclevel.pSurface) { DC_vUpdateDC(pdcFirst); } } if(pdcSecond && pdcSecond->dctype == DCTYPE_DIRECT) { EngAcquireSemaphore(pdcSecond->ppdev->hsemDevLock); MouseSafetyOnDrawStart(pdcSecond->ppdev, prcSecond->left, prcSecond->top, prcSecond->right, prcSecond->bottom) ; /* Update surface if needed */ if(pdcSecond->ppdev->pSurface != pdcSecond->dclevel.pSurface) { DC_vUpdateDC(pdcSecond); } } }
PLDEVOBJ NTAPI EngLoadImageEx( _In_z_ LPWSTR pwszDriverName, _In_ ULONG ldevtype) { WCHAR acwBuffer[MAX_PATH]; PLDEVOBJ pldev; UNICODE_STRING strDriverName; SIZE_T cwcLength; LPWSTR pwsz; TRACE("EngLoadImageEx(%ls, %lu)\n", pwszDriverName, ldevtype); ASSERT(pwszDriverName); /* Initialize buffer for the the driver name */ RtlInitEmptyUnicodeString(&strDriverName, acwBuffer, sizeof(acwBuffer)); /* Start path with systemroot */ RtlAppendUnicodeToString(&strDriverName, L"\\SystemRoot\\System32\\"); /* Get Length of given string */ cwcLength = wcslen(pwszDriverName); /* Check if we have a system32 path given */ pwsz = pwszDriverName + cwcLength; while (pwsz > pwszDriverName) { if ((*pwsz == L'\\') && (_wcsnicmp(pwsz, L"\\system32\\", 10) == 0)) { /* Driver name starts after system32 */ pwsz += 10; break; } pwsz--; } /* Append the driver name */ RtlAppendUnicodeToString(&strDriverName, pwsz); /* MSDN says "The driver must include this suffix in the pwszDriver string." But in fact it's optional. The function can also load .sys files without appending the .dll extension. */ if ((cwcLength < 4) || ((_wcsnicmp(pwszDriverName + cwcLength - 4, L".dll", 4) != 0) && (_wcsnicmp(pwszDriverName + cwcLength - 4, L".sys", 4) != 0)) ) { /* Append the .dll suffix */ RtlAppendUnicodeToString(&strDriverName, L".dll"); } /* Lock loader */ EngAcquireSemaphore(ghsemLDEVList); /* Search the List of LDEVS for the driver name */ for (pldev = gpldevHead; pldev != NULL; pldev = pldev->pldevNext) { /* Check if the ldev is associated with a file */ if (pldev->pGdiDriverInfo) { ERR("Driver Name 1 %wZ\n", &strDriverName); ERR("Driver Name 2 %wZ\n", &pldev->pGdiDriverInfo->DriverName); /* Check for match (case insensative) */ if (RtlEqualUnicodeString(&pldev->pGdiDriverInfo->DriverName, &strDriverName, 1)) { /* Image found in LDEV list */ break; } } } /* Did we find one? */ if (!pldev) { /* No, allocate a new LDEVOBJ */ pldev = LDEVOBJ_AllocLDEV(ldevtype); if (!pldev) { ERR("Could not allocate LDEV\n"); goto leave; } /* Load the image */ if (!LDEVOBJ_bLoadImage(pldev, &strDriverName)) { LDEVOBJ_vFreeLDEV(pldev); pldev = NULL; ERR("LDEVOBJ_bLoadImage failed\n"); goto leave; } /* Shall we load a driver? */ if (ldevtype != LDEV_IMAGE) { /* Load the driver */ if (!LDEVOBJ_bEnableDriver(pldev)) { ERR("LDEVOBJ_bEnableDriver failed\n"); /* Unload the image. */ LDEVOBJ_vUnloadImage(pldev); LDEVOBJ_vFreeLDEV(pldev); pldev = NULL; goto leave; } } /* Insert the LDEV into the global list */ pldev->pldevPrev = NULL; pldev->pldevNext = gpldevHead; if (gpldevHead) gpldevHead->pldevPrev = pldev; gpldevHead = pldev; } /* Increase ref count */ pldev->cRefs++; leave: /* Unlock loader */ EngReleaseSemaphore(ghsemLDEVList); TRACE("EngLoadImageEx returning %p\n", pldev); return pldev; }
ULONG NTAPI GreSetPointerShape( _In_ HDC hdc, _In_opt_ HBITMAP hbmMask, _In_opt_ HBITMAP hbmColor, _In_ LONG xHot, _In_ LONG yHot, _In_ LONG x, _In_ LONG y, _In_ FLONG fl) { PDC pdc; PSURFACE psurf, psurfMask, psurfColor; EXLATEOBJ exlo; ULONG ulResult = 0; pdc = DC_LockDc(hdc); if (!pdc) { DPRINT1("Failed to lock the DC.\n"); return 0; } ASSERT(pdc->dctype == DCTYPE_DIRECT); EngAcquireSemaphore(pdc->ppdev->hsemDevLock); /* We're not sure DC surface is the good one */ psurf = pdc->ppdev->pSurface; if (!psurf) { DPRINT1("DC has no surface.\n"); EngReleaseSemaphore(pdc->ppdev->hsemDevLock); DC_UnlockDc(pdc); return 0; } /* Lock the mask bitmap */ if (hbmMask) { psurfMask = SURFACE_ShareLockSurface(hbmMask); } else { //ASSERT(fl & SPS_ALPHA); psurfMask = NULL; } /* Check for color bitmap */ if (hbmColor) { /* We have one, lock it */ psurfColor = SURFACE_ShareLockSurface(hbmColor); if (psurfColor) { /* Create an XLATEOBJ, no mono support */ EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurf->ppal, 0, 0, 0); } } else psurfColor = NULL; /* We must have a valid surface in case of alpha bitmap */ ASSERT(((fl & SPS_ALPHA) && psurfColor) || !(fl & SPS_ALPHA)); /* Call the driver or eng function */ ulResult = IntEngSetPointerShape(&psurf->SurfObj, psurfMask ? &psurfMask->SurfObj : NULL, psurfColor ? &psurfColor->SurfObj : NULL, psurfColor ? &exlo.xlo : NULL, xHot, yHot, x, y, &pdc->ppdev->Pointer.Exclude, fl | SPS_CHANGE); /* Cleanup */ if (psurfColor) { EXLATEOBJ_vCleanup(&exlo); SURFACE_ShareUnlockSurface(psurfColor); } if (psurfMask) SURFACE_ShareUnlockSurface(psurfMask); EngReleaseSemaphore(pdc->ppdev->hsemDevLock); /* Unlock the DC */ DC_UnlockDc(pdc); /* Return result */ return ulResult; }
PGRAPHICS_DEVICE NTAPI EngpRegisterGraphicsDevice( _In_ PUNICODE_STRING pustrDeviceName, _In_ PUNICODE_STRING pustrDiplayDrivers, _In_ PUNICODE_STRING pustrDescription, _In_ PDEVMODEW pdmDefault) { PGRAPHICS_DEVICE pGraphicsDevice; PDEVICE_OBJECT pDeviceObject; PFILE_OBJECT pFileObject; NTSTATUS Status; PWSTR pwsz; ULONG cj; SIZE_T cjWritten; BOOL bEnable = TRUE; TRACE("EngpRegisterGraphicsDevice(%wZ)\n", pustrDeviceName); /* Allocate a GRAPHICS_DEVICE structure */ pGraphicsDevice = ExAllocatePoolWithTag(PagedPool, sizeof(GRAPHICS_DEVICE), GDITAG_GDEVICE); if (!pGraphicsDevice) { ERR("ExAllocatePoolWithTag failed\n"); return NULL; } /* Try to open the driver */ Status = IoGetDeviceObjectPointer(pustrDeviceName, FILE_READ_DATA | FILE_WRITE_DATA, &pFileObject, &pDeviceObject); if (!NT_SUCCESS(Status)) { ERR("Could not open driver %wZ, 0x%lx\n", pustrDeviceName, Status); ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); return NULL; } /* Enable the device */ EngFileWrite(pFileObject, &bEnable, sizeof(BOOL), &cjWritten); /* Copy the device and file object pointers */ pGraphicsDevice->DeviceObject = pDeviceObject; pGraphicsDevice->FileObject = pFileObject; /* Copy device name */ RtlStringCbCopyNW(pGraphicsDevice->szNtDeviceName, sizeof(pGraphicsDevice->szNtDeviceName), pustrDeviceName->Buffer, pustrDeviceName->Length); /* Create a win device name (FIXME: virtual devices!) */ swprintf(pGraphicsDevice->szWinDeviceName, L"\\\\.\\DISPLAY%d", (int)giDevNum); /* Allocate a buffer for the strings */ cj = pustrDiplayDrivers->Length + pustrDescription->Length + sizeof(WCHAR); pwsz = ExAllocatePoolWithTag(PagedPool, cj, GDITAG_DRVSUP); if (!pwsz) { ERR("Could not allocate string buffer\n"); ASSERT(FALSE); // FIXME ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); return NULL; } /* Copy display driver names */ pGraphicsDevice->pDiplayDrivers = pwsz; RtlCopyMemory(pGraphicsDevice->pDiplayDrivers, pustrDiplayDrivers->Buffer, pustrDiplayDrivers->Length); /* Copy description */ pGraphicsDevice->pwszDescription = pwsz + pustrDiplayDrivers->Length / sizeof(WCHAR); RtlCopyMemory(pGraphicsDevice->pwszDescription, pustrDescription->Buffer, pustrDescription->Length); pGraphicsDevice->pwszDescription[pustrDescription->Length/sizeof(WCHAR)] = 0; /* Initialize the pdevmodeInfo list and default index */ pGraphicsDevice->pdevmodeInfo = NULL; pGraphicsDevice->iDefaultMode = 0; pGraphicsDevice->iCurrentMode = 0; // FIXME: initialize state flags pGraphicsDevice->StateFlags = 0; /* Create the mode list */ pGraphicsDevice->pDevModeList = NULL; if (!EngpPopulateDeviceModeList(pGraphicsDevice, pdmDefault)) { ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); return NULL; } /* Lock loader */ EngAcquireSemaphore(ghsemGraphicsDeviceList); /* Insert the device into the global list */ pGraphicsDevice->pNextGraphicsDevice = NULL; if (gpGraphicsDeviceLast) gpGraphicsDeviceLast->pNextGraphicsDevice = pGraphicsDevice; gpGraphicsDeviceLast = pGraphicsDevice; if (!gpGraphicsDeviceFirst) gpGraphicsDeviceFirst = pGraphicsDevice; /* Increment device number */ giDevNum++; /* Unlock loader */ EngReleaseSemaphore(ghsemGraphicsDeviceList); TRACE("Prepared %lu modes for %ls\n", pGraphicsDevice->cDevModes, pGraphicsDevice->pwszDescription); return pGraphicsDevice; }
/* rc1 and rc2 are the rectangles where we want to draw or * from where we take pixels. */ VOID FASTCALL DC_vPrepareDCsForBlit( PDC pdcDest, const RECT* rcDest, PDC pdcSrc, const RECT* rcSrc) { PDC pdcFirst, pdcSecond; const RECT *prcFirst, *prcSecond; /* Update brushes */ if (pdcDest->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(pdcDest); if (pdcDest->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) DC_vUpdateLineBrush(pdcDest); if(pdcDest->pdcattr->ulDirty_ & DIRTY_TEXT) DC_vUpdateTextBrush(pdcDest); /* Lock them in good order */ if(pdcSrc) { if((ULONG_PTR)pdcDest->ppdev->hsemDevLock >= (ULONG_PTR)pdcSrc->ppdev->hsemDevLock) { pdcFirst = pdcDest; prcFirst = rcDest; pdcSecond = pdcSrc; prcSecond = rcSrc; } else { pdcFirst = pdcSrc; prcFirst = rcSrc; pdcSecond = pdcDest; prcSecond = rcDest; } } else { pdcFirst = pdcDest ; prcFirst = rcDest; pdcSecond = NULL; prcSecond = NULL; } /* Update clipping of dest DC if needed */ if (pdcDest->dctype == DCTYPE_DIRECT) { DCE* dce = DceGetDceFromDC(pdcDest->BaseObject.hHmgr); if (dce) DceUpdateVisRgn(dce, dce->pwndOrg, dce->DCXFlags); } if (pdcDest->fs & DC_FLAG_DIRTY_RAO) CLIPPING_UpdateGCRegion(pdcDest); /* Lock and update first DC */ if(pdcFirst->dctype == DCTYPE_DIRECT) { EngAcquireSemaphore(pdcFirst->ppdev->hsemDevLock); /* Update surface if needed */ if(pdcFirst->ppdev->pSurface != pdcFirst->dclevel.pSurface) { DC_vUpdateDC(pdcFirst); } } if(pdcFirst->dctype == DCTYPE_DIRECT) { if (!prcFirst) prcFirst = &pdcFirst->erclClip; MouseSafetyOnDrawStart(pdcFirst->ppdev, prcFirst->left, prcFirst->top, prcFirst->right, prcFirst->bottom) ; } if (!pdcSecond) return; /* Lock and update second DC */ if(pdcSecond->dctype == DCTYPE_DIRECT) { EngAcquireSemaphore(pdcSecond->ppdev->hsemDevLock); /* Update surface if needed */ if(pdcSecond->ppdev->pSurface != pdcSecond->dclevel.pSurface) { DC_vUpdateDC(pdcSecond); } } if(pdcSecond->dctype == DCTYPE_DIRECT) { if (!prcSecond) prcSecond = &pdcSecond->erclClip; MouseSafetyOnDrawStart(pdcSecond->ppdev, prcSecond->left, prcSecond->top, prcSecond->right, prcSecond->bottom) ; } }
PGRAPHICS_DEVICE NTAPI EngpRegisterGraphicsDevice( PUNICODE_STRING pustrDeviceName, PUNICODE_STRING pustrDiplayDrivers, PUNICODE_STRING pustrDescription, PDEVMODEW pdmDefault) { PGRAPHICS_DEVICE pGraphicsDevice; PDEVICE_OBJECT pDeviceObject; PFILE_OBJECT pFileObject; NTSTATUS Status; PWSTR pwsz; ULONG i, cj, cModes = 0; SIZE_T cjWritten; BOOL bEnable = TRUE; PDEVMODEINFO pdminfo; PDEVMODEW pdm, pdmEnd; PLDEVOBJ pldev; BOOLEAN bModeMatch = FALSE; TRACE("EngpRegisterGraphicsDevice(%wZ)\n", pustrDeviceName); /* Allocate a GRAPHICS_DEVICE structure */ pGraphicsDevice = ExAllocatePoolWithTag(PagedPool, sizeof(GRAPHICS_DEVICE), GDITAG_GDEVICE); if (!pGraphicsDevice) { ERR("ExAllocatePoolWithTag failed\n"); return NULL; } /* Try to open the driver */ Status = IoGetDeviceObjectPointer(pustrDeviceName, FILE_READ_DATA | FILE_WRITE_DATA, &pFileObject, &pDeviceObject); if (!NT_SUCCESS(Status)) { ERR("Could not open driver %wZ, 0x%lx\n", pustrDeviceName, Status); ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); return NULL; } /* Enable the device */ EngFileWrite(pFileObject, &bEnable, sizeof(BOOL), &cjWritten); /* Copy the device and file object pointers */ pGraphicsDevice->DeviceObject = pDeviceObject; pGraphicsDevice->FileObject = pFileObject; /* Copy device name */ RtlStringCbCopyNW(pGraphicsDevice->szNtDeviceName, sizeof(pGraphicsDevice->szNtDeviceName), pustrDeviceName->Buffer, pustrDeviceName->Length); /* Create a win device name (FIXME: virtual devices!) */ swprintf(pGraphicsDevice->szWinDeviceName, L"\\\\.\\DISPLAY%d", (int)giDevNum); /* Allocate a buffer for the strings */ cj = pustrDiplayDrivers->Length + pustrDescription->Length + sizeof(WCHAR); pwsz = ExAllocatePoolWithTag(PagedPool, cj, GDITAG_DRVSUP); if (!pwsz) { ERR("Could not allocate string buffer\n"); ASSERT(FALSE); // FIXME ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); return NULL; } /* Copy display driver names */ pGraphicsDevice->pDiplayDrivers = pwsz; RtlCopyMemory(pGraphicsDevice->pDiplayDrivers, pustrDiplayDrivers->Buffer, pustrDiplayDrivers->Length); /* Copy description */ pGraphicsDevice->pwszDescription = pwsz + pustrDiplayDrivers->Length / sizeof(WCHAR); RtlCopyMemory(pGraphicsDevice->pwszDescription, pustrDescription->Buffer, pustrDescription->Length); pGraphicsDevice->pwszDescription[pustrDescription->Length/sizeof(WCHAR)] = 0; /* Initialize the pdevmodeInfo list and default index */ pGraphicsDevice->pdevmodeInfo = NULL; pGraphicsDevice->iDefaultMode = 0; pGraphicsDevice->iCurrentMode = 0; // FIXME: initialize state flags pGraphicsDevice->StateFlags = 0; /* Loop through the driver names * This is a REG_MULTI_SZ string */ for (; *pwsz; pwsz += wcslen(pwsz) + 1) { TRACE("trying driver: %ls\n", pwsz); /* Try to load the display driver */ pldev = EngLoadImageEx(pwsz, LDEV_DEVICE_DISPLAY); if (!pldev) { ERR("Could not load driver: '%ls'\n", pwsz); continue; } /* Get the mode list from the driver */ pdminfo = LDEVOBJ_pdmiGetModes(pldev, pDeviceObject); if (!pdminfo) { ERR("Could not get mode list for '%ls'\n", pwsz); continue; } /* Attach the mode info to the device */ pdminfo->pdmiNext = pGraphicsDevice->pdevmodeInfo; pGraphicsDevice->pdevmodeInfo = pdminfo; /* Loop all DEVMODEs */ pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode); for (pdm = pdminfo->adevmode; (pdm + 1 <= pdmEnd) && (pdm->dmSize != 0); pdm = (DEVMODEW*)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra)) { /* Count this DEVMODE */ cModes++; /* Some drivers like the VBox driver don't fill the dmDeviceName with the name of the display driver. So fix that here. */ wcsncpy(pdm->dmDeviceName, pwsz, CCHDEVICENAME); pdm->dmDeviceName[CCHDEVICENAME - 1] = 0; } // FIXME: release the driver again until it's used? } if (!pGraphicsDevice->pdevmodeInfo || cModes == 0) { ERR("No devmodes\n"); ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); return NULL; } /* Allocate an index buffer */ pGraphicsDevice->cDevModes = cModes; pGraphicsDevice->pDevModeList = ExAllocatePoolWithTag(PagedPool, cModes * sizeof(DEVMODEENTRY), GDITAG_GDEVICE); if (!pGraphicsDevice->pDevModeList) { ERR("No devmode list\n"); ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); return NULL; } TRACE("Looking for mode %lux%lux%lu(%lu Hz)\n", pdmDefault->dmPelsWidth, pdmDefault->dmPelsHeight, pdmDefault->dmBitsPerPel, pdmDefault->dmDisplayFrequency); /* Loop through all DEVMODEINFOs */ for (pdminfo = pGraphicsDevice->pdevmodeInfo, i = 0; pdminfo; pdminfo = pdminfo->pdmiNext) { /* Calculate End of the DEVMODEs */ pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode); /* Loop through the DEVMODEs */ for (pdm = pdminfo->adevmode; (pdm + 1 <= pdmEnd) && (pdm->dmSize != 0); pdm = (PDEVMODEW)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra)) { TRACE(" %S has mode %lux%lux%lu(%lu Hz)\n", pdm->dmDeviceName, pdm->dmPelsWidth, pdm->dmPelsHeight, pdm->dmBitsPerPel, pdm->dmDisplayFrequency); /* Compare with the default entry */ if (!bModeMatch && pdm->dmBitsPerPel == pdmDefault->dmBitsPerPel && pdm->dmPelsWidth == pdmDefault->dmPelsWidth && pdm->dmPelsHeight == pdmDefault->dmPelsHeight) { pGraphicsDevice->iDefaultMode = i; pGraphicsDevice->iCurrentMode = i; TRACE("Found default entry: %lu '%ls'\n", i, pdm->dmDeviceName); if (pdm->dmDisplayFrequency == pdmDefault->dmDisplayFrequency) { /* Uh oh, even the display frequency matches. */ bModeMatch = TRUE; } } /* Initialize the entry */ pGraphicsDevice->pDevModeList[i].dwFlags = 0; pGraphicsDevice->pDevModeList[i].pdm = pdm; i++; } } /* Lock loader */ EngAcquireSemaphore(ghsemGraphicsDeviceList); /* Insert the device into the global list */ pGraphicsDevice->pNextGraphicsDevice = NULL; if (gpGraphicsDeviceLast) gpGraphicsDeviceLast->pNextGraphicsDevice = pGraphicsDevice; gpGraphicsDeviceLast = pGraphicsDevice; if (!gpGraphicsDeviceFirst) gpGraphicsDeviceFirst = pGraphicsDevice; /* Increment device number */ giDevNum++; /* Unlock loader */ EngReleaseSemaphore(ghsemGraphicsDeviceList); TRACE("Prepared %lu modes for %ls\n", cModes, pGraphicsDevice->pwszDescription); return pGraphicsDevice; }
BOOL DRVFREE( LPVOID pMem ) { #if DBG DWORD cb; LPDWORD pBaseMem; LPDWORD pRetAddr; pBaseMem = (PDWORD)pMem - 2; cb = *pBaseMem; if (*(LPDWORD)((LPBYTE)pMem + cb) != 0xdeadbeef) { DrvDbgPrint( "Corrupt Memory in Rasdd : Base mem is %x, Function to allocate the mem is %x\n",pBaseMem,pBaseMem[1] ); EngDebugBreak(); return FALSE; } EngAcquireSemaphore(hsem); gFreeCount++; EngReleaseSemaphore(hsem); FillMemory(pMem, cb + 2*sizeof( DWORD ), 0xdf); // // Heap manager will overwrite first and second DWORD. // Save the address of the function which allocated this buffer in // 3rd DWORD. The Calling function address will be saved in fourth // DWORD. // pBaseMem[2] = pBaseMem[1]; #if (_MSC_VER >= 1000) pBaseMem[3] = (DWORD)_ReturnAddress(); #else #if i386 // // Save the callers return address for helping debug // pRetAddr = (LPDWORD)&pMem; pRetAddr--; pBaseMem[3] = *pRetAddr; #else // // Put in a bogus value to prevent 0 from being read back. // pBaseMem[3] = 0xf987654f; #endif /* #if i386 */ #endif /* #if (_MSC_VER >= 1000) */ pMem = (LPVOID)pBaseMem; #endif /* #if DBG */ #if NTGDIKM EngFreeMem((PVOID)pMem) ; #else HeapFree( hHeap, 0, (LPVOID)pMem ); #endif // NTGDIKM return TRUE; }
LPVOID DRVALLOC( DWORD cbAlloc ) /*++ Routine Description: This function will allocate local memory. It will possibly allocate extra memory and fill this with debugging information for the debugging version. Arguments: cb - The amount of memory to allocate Return Value: NON-NULL - A pointer to the allocated memory FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { LPDWORD pMem = NULL; #if DBG DWORD cbOld = 0; cbOld = DWORD_ALIGN_UP(cbAlloc); cbAlloc = cbOld + 4 * sizeof(DWORD); #endif #if NTGDIKM pMem = (LPDWORD)EngAllocMem(0, cbAlloc,gulMemID); #else pMem = (LPDWORD)HeapAlloc( hHeap, HEAP_ZERO_MEMORY, cbAlloc ); #endif #if DBG if (!pMem) { EngAcquireSemaphore(hsem); gFailCount++; gbFailAllocs = TRUE; EngReleaseSemaphore(hsem); return (LPVOID)pMem; } else { EngAcquireSemaphore(hsem); gAllocCount++; EngReleaseSemaphore(hsem); pMem[0] = cbOld; #if (_MSC_VER >= 1000) pMem[1] = (DWORD)_ReturnAddress(); #else // // Put in a bogus value to prevent 0 from being read back. // pMem[1] = 0xf987654f; #endif *(LPDWORD)((LPBYTE)&pMem[2] + cbOld)=0xdeadbeef; return (LPVOID)&pMem[2]; } #endif return (LPVOID)pMem; }
VOID NTAPI PDEVOBJ_vRelease(PPDEVOBJ ppdev) { /* Lock loader */ EngAcquireSemaphore(ghsemPDEV); /* Decrease reference count */ --ppdev->cPdevRefs; ASSERT(ppdev->cPdevRefs >= 0) ; /* Check if references are left */ if (ppdev->cPdevRefs == 0) { /* Do we have a surface? */ if(ppdev->pSurface) { /* Release the surface and let the driver free it */ SURFACE_ShareUnlockSurface(ppdev->pSurface); ppdev->pfn.DisableSurface(ppdev->dhpdev); } /* Do we have a palette? */ if(ppdev->ppalSurf) { PALETTE_ShareUnlockPalette(ppdev->ppalSurf); } /* Disable PDEV */ ppdev->pfn.DisablePDEV(ppdev->dhpdev); /* Remove it from list */ if( ppdev == gppdevList ) gppdevList = ppdev->ppdevNext ; else { PPDEVOBJ ppdevCurrent = gppdevList; BOOL found = FALSE ; while (!found && ppdevCurrent->ppdevNext) { if (ppdevCurrent->ppdevNext == ppdev) found = TRUE; else ppdevCurrent = ppdevCurrent->ppdevNext ; } if(found) ppdevCurrent->ppdevNext = ppdev->ppdevNext; } /* Is this the primary one ? */ if (ppdev == gppdevPrimary) gppdevPrimary = NULL; /* Free it */ ExFreePoolWithTag(ppdev, GDITAG_PDEV ); } /* Unlock loader */ EngReleaseSemaphore(ghsemPDEV); }
PPDEVOBJ NTAPI EngpGetPDEV( PUNICODE_STRING pustrDeviceName) { UNICODE_STRING ustrCurrent; PPDEVOBJ ppdev; PGRAPHICS_DEVICE pGraphicsDevice; /* Acquire PDEV lock */ EngAcquireSemaphore(ghsemPDEV); /* If no device name is given, ... */ if (!pustrDeviceName && gppdevPrimary) { /* ... use the primary PDEV */ ppdev = gppdevPrimary; /* Reference the pdev */ InterlockedIncrement(&ppdev->cPdevRefs); goto leave; } /* Loop all present PDEVs */ for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext) { /* Get a pointer to the GRAPHICS_DEVICE */ pGraphicsDevice = ppdev->pGraphicsDevice; /* Compare the name */ RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName); if (RtlEqualUnicodeString(pustrDeviceName, &ustrCurrent, FALSE)) { /* Found! Reference the PDEV */ InterlockedIncrement(&ppdev->cPdevRefs); break; } } /* Did we find one? */ if (!ppdev) { /* No, create a new PDEV */ ppdev = EngpCreatePDEV(pustrDeviceName, NULL); if (ppdev) { /* Insert the PDEV into the list */ ppdev->ppdevNext = gppdevList; gppdevList = ppdev; /* Set as primary PDEV, if we don't have one yet */ if (!gppdevPrimary) { gppdevPrimary = ppdev; ppdev->pGraphicsDevice->StateFlags |= DISPLAY_DEVICE_PRIMARY_DEVICE; } } } leave: /* Release PDEV lock */ EngReleaseSemaphore(ghsemPDEV); return ppdev; }
BOOL NTAPI PDEVOBJ_bSwitchMode( PPDEVOBJ ppdev, PDEVMODEW pdm) { UNICODE_STRING ustrDevice; PPDEVOBJ ppdevTmp; PSURFACE pSurface; BOOL retval = FALSE; /* Lock the PDEV */ EngAcquireSemaphore(ppdev->hsemDevLock); /* And everything else */ EngAcquireSemaphore(ghsemPDEV); DPRINT1("PDEVOBJ_bSwitchMode, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface); // Lookup the GraphicsDevice + select DEVMODE // pdm = PDEVOBJ_pdmMatchDevMode(ppdev, pdm); /* 1. Temporarily disable the current PDEV */ if (!ppdev->pfn.AssertMode(ppdev->dhpdev, FALSE)) { DPRINT1("DrvAssertMode failed\n"); goto leave; } /* 2. Create new PDEV */ RtlInitUnicodeString(&ustrDevice, ppdev->pGraphicsDevice->szWinDeviceName); ppdevTmp = EngpCreatePDEV(&ustrDevice, pdm); if (!ppdevTmp) { DPRINT1("Failed to create a new PDEV\n"); goto leave; } /* 3. Create a new surface */ pSurface = PDEVOBJ_pSurface(ppdevTmp); if (!pSurface) { DPRINT1("DrvEnableSurface failed\n"); goto leave; } /* 4. Get DirectDraw information */ /* 5. Enable DirectDraw Not traced */ /* 6. Copy old PDEV state to new PDEV instance */ /* 7. Switch the PDEVs */ PDEVOBJ_vSwitchPdev(ppdev, ppdevTmp); /* 8. Disable DirectDraw */ PDEVOBJ_vRelease(ppdevTmp); /* Update primary display capabilities */ if(ppdev == gppdevPrimary) { PDEVOBJ_vGetDeviceCaps(ppdev, &GdiHandleTable->DevCaps); } /* Success! */ retval = TRUE; leave: /* Unlock PDEV */ EngReleaseSemaphore(ppdev->hsemDevLock); EngReleaseSemaphore(ghsemPDEV); DPRINT1("leave, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface); return retval; }