1 #include <win32k.h> 2 3 #define NDEBUG 4 #include <debug.h> 5 6 /* 7 * @implemented 8 */ 9 __drv_allocatesMem(Mem) 10 _Post_writable_byte_size_(sizeof(ERESOURCE)) 11 HSEMAPHORE 12 APIENTRY 13 EngCreateSemaphore( 14 VOID) 15 { 16 // www.osr.com/ddk/graphics/gdifncs_95lz.htm 17 PERESOURCE psem = ExAllocatePoolWithTag(NonPagedPool, 18 sizeof(ERESOURCE), 19 GDITAG_SEMAPHORE); 20 if (!psem) 21 return NULL; 22 23 if (!NT_SUCCESS(ExInitializeResourceLite(psem))) 24 { 25 ExFreePoolWithTag(psem, GDITAG_SEMAPHORE ); 26 return NULL; 27 } 28 29 return (HSEMAPHORE)psem; 30 } 31 32 /* 33 * @implemented 34 */ 35 _Requires_lock_not_held_(*hsem) 36 _Acquires_exclusive_lock_(*hsem) 37 _Acquires_lock_(_Global_critical_region_) 38 VOID 39 APIENTRY 40 EngAcquireSemaphore( 41 _Inout_ HSEMAPHORE hsem) 42 { 43 // www.osr.com/ddk/graphics/gdifncs_14br.htm 44 PTHREADINFO W32Thread; 45 46 /* On Windows a NULL hsem is ignored */ 47 if (hsem == NULL) 48 { 49 DPRINT1("EngAcquireSemaphore called with hsem == NULL!\n"); 50 return; 51 } 52 53 ExEnterCriticalRegionAndAcquireResourceExclusive((PERESOURCE)hsem); 54 W32Thread = PsGetThreadWin32Thread(PsGetCurrentThread()); 55 if (W32Thread) W32Thread->dwEngAcquireCount++; 56 } 57 58 /* 59 * @implemented 60 */ 61 _Requires_lock_held_(*hsem) 62 _Releases_lock_(*hsem) 63 _Releases_lock_(_Global_critical_region_) 64 VOID 65 APIENTRY 66 EngReleaseSemaphore( 67 _Inout_ HSEMAPHORE hsem) 68 { 69 // www.osr.com/ddk/graphics/gdifncs_5u3r.htm 70 PTHREADINFO W32Thread; 71 72 /* On Windows a NULL hsem is ignored */ 73 if (hsem == NULL) 74 { 75 DPRINT1("EngReleaseSemaphore called with hsem == NULL!\n"); 76 return; 77 } 78 79 W32Thread = PsGetThreadWin32Thread(PsGetCurrentThread()); 80 if (W32Thread) --W32Thread->dwEngAcquireCount; 81 ExReleaseResourceAndLeaveCriticalRegion((PERESOURCE)hsem); 82 } 83 84 _Acquires_lock_(_Global_critical_region_) 85 _Requires_lock_not_held_(*hsem) 86 _Acquires_shared_lock_(*hsem) 87 VOID 88 NTAPI 89 EngAcquireSemaphoreShared( 90 _Inout_ HSEMAPHORE hsem) 91 { 92 PTHREADINFO pti; 93 94 ASSERT(hsem); 95 ExEnterCriticalRegionAndAcquireResourceShared((PERESOURCE)hsem); 96 pti = PsGetThreadWin32Thread(PsGetCurrentThread()); 97 if (pti) ++pti->dwEngAcquireCount; 98 } 99 100 /* 101 * @implemented 102 */ 103 _Requires_lock_not_held_(*hsem) 104 VOID 105 APIENTRY 106 EngDeleteSemaphore( 107 _Inout_ __drv_freesMem(Mem) HSEMAPHORE hsem) 108 { 109 // www.osr.com/ddk/graphics/gdifncs_13c7.htm 110 ASSERT(hsem); 111 112 ExDeleteResourceLite((PERESOURCE)hsem); 113 ExFreePoolWithTag((PVOID)hsem, GDITAG_SEMAPHORE); 114 } 115 116 /* 117 * @implemented 118 */ 119 BOOL 120 APIENTRY 121 EngIsSemaphoreOwned( 122 _In_ HSEMAPHORE hsem) 123 { 124 // www.osr.com/ddk/graphics/gdifncs_6wmf.htm 125 ASSERT(hsem); 126 return (((PERESOURCE)hsem)->ActiveCount > 0); 127 } 128 129 /* 130 * @implemented 131 */ 132 BOOL 133 APIENTRY 134 EngIsSemaphoreOwnedByCurrentThread( 135 _In_ HSEMAPHORE hsem) 136 { 137 // www.osr.com/ddk/graphics/gdifncs_9yxz.htm 138 ASSERT(hsem); 139 return ExIsResourceAcquiredExclusiveLite((PERESOURCE)hsem); 140 } 141 142 /* 143 * @implemented 144 */ 145 BOOL 146 APIENTRY 147 EngInitializeSafeSemaphore( 148 _Out_ ENGSAFESEMAPHORE *Semaphore) 149 { 150 HSEMAPHORE hSem; 151 152 if (InterlockedIncrement(&Semaphore->lCount) == 1) 153 { 154 /* Create the semaphore */ 155 hSem = EngCreateSemaphore(); 156 if (hSem == 0) 157 { 158 InterlockedDecrement(&Semaphore->lCount); 159 return FALSE; 160 } 161 /* FIXME: Not thread-safe! Check result of InterlockedCompareExchangePointer 162 and delete semaphore if already initialized! */ 163 (void)InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, hSem); 164 } 165 else 166 { 167 /* Wait for the other thread to create the semaphore */ 168 ASSERT(Semaphore->lCount > 1); 169 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL); 170 while (Semaphore->hsem == NULL); 171 } 172 173 return TRUE; 174 } 175 176 /* 177 * @implemented 178 */ 179 VOID 180 APIENTRY 181 EngDeleteSafeSemaphore( 182 _Inout_ _Post_invalid_ ENGSAFESEMAPHORE *pssem) 183 { 184 if (InterlockedDecrement(&pssem->lCount) == 0) 185 { 186 /* FIXME: Not thread-safe! Use result of InterlockedCompareExchangePointer! */ 187 EngDeleteSemaphore(pssem->hsem); 188 (void)InterlockedExchangePointer((volatile PVOID *)&pssem->hsem, NULL); 189 } 190 } 191 192 /* EOF */ 193