#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 */