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