#include #define NDEBUG #include /* * @implemented */ HSEMAPHORE APIENTRY EngCreateSemaphore(VOID) { // www.osr.com/ddk/graphics/gdifncs_95lz.htm PERESOURCE psem = ExAllocatePoolWithTag(NonPagedPool, sizeof(ERESOURCE), GDITAG_SEMAPHORE); if (!psem) return NULL; if (!NT_SUCCESS(ExInitializeResourceLite(psem))) { ExFreePoolWithTag ( psem, GDITAG_SEMAPHORE ); return NULL; } return (HSEMAPHORE)psem; } VOID FASTCALL IntGdiAcquireSemaphore(HSEMAPHORE hsem) { KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite ((PERESOURCE)hsem, TRUE); } /* * @implemented */ VOID APIENTRY EngAcquireSemaphore(IN HSEMAPHORE hsem) { // www.osr.com/ddk/graphics/gdifncs_14br.htm PTHREADINFO W32Thread; ASSERT(hsem); IntGdiAcquireSemaphore(hsem); W32Thread = PsGetThreadWin32Thread(PsGetCurrentThread()); if (W32Thread) W32Thread->dwEngAcquireCount++; } VOID FASTCALL IntGdiReleaseSemaphore ( HSEMAPHORE hsem ) { ExReleaseResourceLite((PERESOURCE)hsem); KeLeaveCriticalRegion(); } /* * @implemented */ VOID APIENTRY EngReleaseSemaphore ( IN HSEMAPHORE hsem ) { // www.osr.com/ddk/graphics/gdifncs_5u3r.htm PTHREADINFO W32Thread; ASSERT(hsem); W32Thread = PsGetThreadWin32Thread(PsGetCurrentThread()); if (W32Thread) --W32Thread->dwEngAcquireCount; IntGdiReleaseSemaphore(hsem); } VOID NTAPI EngAcquireSemaphoreShared( IN HSEMAPHORE hsem) { PTHREADINFO pti; ASSERT(hsem); ExEnterCriticalRegionAndAcquireResourceShared((PERESOURCE)hsem); pti = PsGetThreadWin32Thread(PsGetCurrentThread()); if (pti) ++pti->dwEngAcquireCount; } /* * @implemented */ VOID APIENTRY EngDeleteSemaphore ( IN HSEMAPHORE hsem ) { // www.osr.com/ddk/graphics/gdifncs_13c7.htm ASSERT(hsem); ExDeleteResourceLite((PERESOURCE)hsem); ExFreePoolWithTag((PVOID)hsem, GDITAG_SEMAPHORE); } /* * @implemented */ BOOL APIENTRY EngIsSemaphoreOwned ( IN HSEMAPHORE hsem ) { // www.osr.com/ddk/graphics/gdifncs_6wmf.htm ASSERT(hsem); return (((PERESOURCE)hsem)->ActiveCount > 0); } /* * @implemented */ BOOL APIENTRY EngIsSemaphoreOwnedByCurrentThread ( IN HSEMAPHORE hsem ) { // www.osr.com/ddk/graphics/gdifncs_9yxz.htm ASSERT(hsem); return ExIsResourceAcquiredExclusiveLite((PERESOURCE)hsem); } /* * @implemented */ BOOL APIENTRY EngInitializeSafeSemaphore( OUT ENGSAFESEMAPHORE *Semaphore) { HSEMAPHORE hSem; if (InterlockedIncrement(&Semaphore->lCount) == 1) { /* Create the semaphore */ hSem = EngCreateSemaphore(); if (hSem == 0) { InterlockedDecrement(&Semaphore->lCount); return FALSE; } /* FIXME: Not thread-safe! Check result of InterlockedCompareExchangePointer and delete semaphore if already initialized! */ (void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, hSem); } else { /* Wait for the other thread to create the semaphore */ ASSERT(Semaphore->lCount > 1); ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL); while (Semaphore->hsem == NULL); } return TRUE; } /* * @implemented */ VOID APIENTRY EngDeleteSafeSemaphore( IN OUT ENGSAFESEMAPHORE *Semaphore) { if (InterlockedDecrement(&Semaphore->lCount) == 0) { /* FIXME: Not thread-safe! Use result of InterlockedCompareExchangePointer! */ EngDeleteSemaphore(Semaphore->hsem); (void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, NULL); } } /* EOF */