19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* win_ce_semaphore.c 29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Copyright (c) 1998, Johnson M. Hart 49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall (with corrections 2001 by Rainer Loritz) 59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Permission is granted for any and all use providing that this 69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall copyright is properly acknowledged. 79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall There are no assurances of suitability for any use whatsoever. 89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall WINDOWS CE: There is a collection of Windows CE functions to simulate 109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall semaphores using only a mutex and an event. As Windows CE events cannot 119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall be named, these simulated semaphores cannot be named either. 129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Implementation notes: 149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1. All required internal data structures are allocated on the process's heap. 159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2. Where appropriate, a new error code is returned (see the header 169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall file), or, if the error is a Win32 error, that code is unchanged. 179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 3. Notice the new handle type "SYNCHHANDLE" that has handles, counters, 189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall and other information. This structure will grow as new objects are added 199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall to this set; some members are specific to only one or two of the objects. 209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 4. Mutexes are used for critical sections. These could be replaced with 219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall CRITICAL_SECTION objects but then this would give up the time out 229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall capability. 239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 5. The implementation shows several interesting aspects of synchronization, some 249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall of which are specific to Win32 and some of which are general. These are pointed 259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall out in the comments as appropriate. 269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 6. The wait function emulates WaitForSingleObject only. An emulation of 279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall WaitForMultipleObjects is much harder to implement outside the kernel, 289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall and it is not clear how to handle a mixture of WCE semaphores and normal 299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall events and mutexes. */ 309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define WIN32_LEAN_AND_MEAN 329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <windows.h> 339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "win_ce_semaphore.h" 359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SYNCHHANDLE CleanUp (SYNCHHANDLE hSynch, DWORD Flags); 379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallSYNCHHANDLE CreateSemaphoreCE ( 399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, /* pointer to security attributes */ 419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall LONG lInitialCount, /* initial count */ 429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall LONG lMaximumCount, /* maximum count */ 439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall LPCTSTR lpName ) 449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Semaphore for use with Windows CE that does not support them directly. 469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Requires a counter, a mutex to protect the counter, and an 479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall autoreset event. 489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Here are the rules that must always hold between the autoreset event 509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall and the mutex (any violation of these rules by the CE semaphore functions 519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall will, in all likelihood, result in a defect): 529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1. No thread can set, pulse, or reset the event, 539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall nor can it access any part of the SYNCHHANDLE structure, 549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall without first gaining ownership of the mutex. 559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall BUT, a thread can wait on the event without owning the mutex 569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall (this is clearly necessary or else the event could never be set). 579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2. The event is in a signaled state if and only if the current semaphore 589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall count ("CurCount") is greater than zero. 599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 3. The semaphore count is always >= 0 and <= the maximum count */ 609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{ 629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall SYNCHHANDLE hSynch = NULL, result = NULL; 639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall __try 659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall { 669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (lInitialCount > lMaximumCount || lMaximumCount < 0 || lInitialCount < 0) 679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall { 689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Bad parameters */ 699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall SetLastError (SYNCH_ERROR); 709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall __leave; 719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall hSynch = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, SYNCH_HANDLE_SIZE); 749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (hSynch == NULL) __leave; 759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall hSynch->MaxCount = lMaximumCount; 779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall hSynch->CurCount = lInitialCount; 789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall hSynch->lpName = lpName; 799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall hSynch->hMutex = CreateMutex (lpSemaphoreAttributes, FALSE, NULL); 819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall WaitForSingleObject (hSynch->hMutex, INFINITE); 839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Create the event. It is initially signaled if and only if the 849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall initial count is > 0 */ 859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall hSynch->hEvent = CreateEvent (lpSemaphoreAttributes, FALSE, 869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall lInitialCount > 0, NULL); 879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall ReleaseMutex (hSynch->hMutex); 889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall hSynch->hSemph = NULL; 899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall __finally 919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall { 929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Return with the handle, or, if there was any error, return 939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall a null after closing any open handles and freeing any allocated memory. */ 949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall result=CleanUp(hSynch, 6 /* An event and a mutex, but no semaphore. */); 959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall return result; 989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall} 999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallBOOL ReleaseSemaphoreCE (SYNCHHANDLE hSemCE, LONG cReleaseCount, LPLONG lpPreviousCount) 1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Windows CE equivalent to ReleaseSemaphore. */ 1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{ 1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall BOOL Result = TRUE; 1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Gain access to the object to assure that the release count 1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall would not cause the total count to exceed the maximum. */ 1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall __try 1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall { 1109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall WaitForSingleObject (hSemCE->hMutex, INFINITE); 1119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* reply only if asked to */ 1129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (lpPreviousCount!=NULL) 1139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *lpPreviousCount = hSemCE->CurCount; 1149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (hSemCE->CurCount + cReleaseCount > hSemCE->MaxCount || cReleaseCount <= 0) 1159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall { 1169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall SetLastError (SYNCH_ERROR); 1179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Result = FALSE; 1189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall __leave; 1199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 1209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall hSemCE->CurCount += cReleaseCount; 1219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Set the autoreset event, releasing exactly one waiting thread, now or 1239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall in the future. */ 1249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall SetEvent (hSemCE->hEvent); 1269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 1279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall __finally 1289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall { 1299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall ReleaseMutex (hSemCE->hMutex); 1309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 1319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall return Result; 1339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall} 1349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallDWORD WaitForSemaphoreCE (SYNCHHANDLE hSemCE, DWORD dwMilliseconds) 1369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Windows CE semaphore equivalent of WaitForSingleObject. */ 1379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{ 1389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall DWORD WaitResult; 1399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds); 1419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) return WaitResult; 1429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall while (hSemCE->CurCount <= 0) 1439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall { 1449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* The count is 0, and the thread must wait on the event (which, by 1469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall the rules, is currently reset) for semaphore resources to become 1479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall available. First, of course, the mutex must be released so that another 1489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall thread will be capable of setting the event. */ 1499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall ReleaseMutex (hSemCE->hMutex); 1519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Wait for the event to be signaled, indicating a semaphore state change. 1539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall The event is autoreset and signaled with a SetEvent (not PulseEvent) 1549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall so exactly one waiting thread (whether or not there is currently 1559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall a waiting thread) is released as a result of the SetEvent. */ 1569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall WaitResult = WaitForSingleObject (hSemCE->hEvent, dwMilliseconds); 1589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (WaitResult != WAIT_OBJECT_0) return WaitResult; 1599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* This is where the properties of setting of an autoreset event is critical 1619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall to assure that, even if the semaphore state changes between the 1629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall preceding Wait and the next, and even if NO threads are waiting 1639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall on the event at the time of the SetEvent, at least one thread 1649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall will be released. 1659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Pulsing a manual reset event would appear to work, but it would have 1669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall a defect which could appear if the semaphore state changed between 1679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall the two waits. */ 1689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds); 1709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) return WaitResult; 1719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 1739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* The count is not zero and this thread owns the mutex. */ 1749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall hSemCE->CurCount--; 1769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* The event is now unsignaled, BUT, the semaphore count may not be 1779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall zero, in which case the event should be signaled again 1789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall before releasing the mutex. */ 1799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (hSemCE->CurCount > 0) SetEvent (hSemCE->hEvent); 1819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall ReleaseMutex (hSemCE->hMutex); 1829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall return WaitResult; 1839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall} 1849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallBOOL CloseSynchHandle (SYNCHHANDLE hSynch) 1869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Close a synchronization handle. 1879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Improvement: Test for a valid handle before dereferencing the handle. */ 1889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{ 1899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall BOOL Result = TRUE; 1909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (hSynch->hEvent != NULL) Result = Result && CloseHandle (hSynch->hEvent); 1919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (hSynch->hMutex != NULL) Result = Result && CloseHandle (hSynch->hMutex); 1929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (hSynch->hSemph != NULL) Result = Result && CloseHandle (hSynch->hSemph); 1939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall HeapFree (GetProcessHeap (), 0, hSynch); 1949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall return (Result); 1959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall} 1969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SYNCHHANDLE CleanUp (SYNCHHANDLE hSynch, DWORD Flags) 1989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{ /* Prepare to return from a create of a synchronization handle. 1999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall If there was any failure, free any allocated resources. 2009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "Flags" indicates which Win32 objects are required in the 2019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall synchronization handle. */ 2029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall BOOL ok = TRUE; 2049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (hSynch == NULL) return NULL; 2069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if ((Flags & 4) == 1 && (hSynch->hEvent == NULL)) ok = FALSE; 2079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if ((Flags & 2) == 1 && (hSynch->hMutex == NULL)) ok = FALSE; 2089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if ((Flags & 1) == 1 && (hSynch->hEvent == NULL)) ok = FALSE; 2099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (!ok) 2109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall { 2119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall CloseSynchHandle (hSynch); 2129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall return NULL; 2139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Everything worked */ 2159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall return hSynch; 2169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall} 217