+
+ return(TRUE);
+}
+
+static void namedsema_signal (gpointer handle)
+{
+ ReleaseSemaphore (handle, 1, NULL);
+}
+
+/* NB, always called with the shared handle lock held */
+static gboolean namedsema_own (gpointer handle)
+{
+ struct _WapiHandle_namedsem *namedsem_handle;
+ gboolean ok;
+
+ DEBUG ("%s: owning named sem handle %p", __func__, handle);
+
+ ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDSEM,
+ (gpointer *)&namedsem_handle);
+ if (ok == FALSE) {
+ g_warning ("%s: error looking up named sem handle %p",
+ __func__, handle);
+ return (FALSE);
+ }
+
+ namedsem_handle->val--;
+
+ DEBUG ("%s: named sem %p val now %d", __func__, handle,
+ namedsem_handle->val);
+
+ if (namedsem_handle->val == 0) {
+ _wapi_shared_handle_set_signal_state (handle, FALSE);
+ }
+
+ return (TRUE);
+}
+static gpointer sem_create (WapiSecurityAttributes *security G_GNUC_UNUSED,
+ gint32 initial, gint32 max)
+{
+ struct _WapiHandle_sem sem_handle = {0};
+ gpointer handle;
+ int thr_ret;
+
+ /* Need to blow away any old errors here, because code tests
+ * for ERROR_ALREADY_EXISTS on success (!) to see if a
+ * semaphore was freshly created
+ */
+ SetLastError (ERROR_SUCCESS);
+
+ sem_handle.val = initial;
+ sem_handle.max = max;
+
+ handle = _wapi_handle_new (WAPI_HANDLE_SEM, &sem_handle);
+ if (handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating semaphore handle", __func__);
+ SetLastError (ERROR_GEN_FAILURE);
+ return(NULL);
+ }
+
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ if (initial != 0) {
+ _wapi_handle_set_signal_state (handle, TRUE, FALSE);
+ }
+
+ DEBUG ("%s: Created semaphore handle %p initial %d max %d",
+ __func__, handle, initial, max);
+
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+ return(handle);
+}
+
+static gpointer namedsem_create (WapiSecurityAttributes *security G_GNUC_UNUSED, gint32 initial, gint32 max, const gunichar2 *name G_GNUC_UNUSED)
+{
+ struct _WapiHandle_namedsem namedsem_handle = {{{0}}, 0};
+ gpointer handle;
+ gchar *utf8_name;
+ int thr_ret;
+ gpointer ret = NULL;
+ guint32 namelen;
+ gint32 offset;
+
+ /* w32 seems to guarantee that opening named objects can't
+ * race each other
+ */
+ thr_ret = _wapi_namespace_lock ();
+ g_assert (thr_ret == 0);
+
+ /* Need to blow away any old errors here, because code tests
+ * for ERROR_ALREADY_EXISTS on success (!) to see if a
+ * semaphore was freshly created
+ */
+ SetLastError (ERROR_SUCCESS);
+
+ utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
+
+ DEBUG ("%s: Creating named sem [%s]", __func__, utf8_name);
+
+ offset = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDSEM,
+ utf8_name);
+ if (offset == -1) {
+ /* The name has already been used for a different
+ * object.
+ */
+ SetLastError (ERROR_INVALID_HANDLE);
+ goto cleanup;
+ } else if (offset != 0) {
+ /* Not an error, but this is how the caller is
+ * informed that the semaphore wasn't freshly created
+ */
+ SetLastError (ERROR_ALREADY_EXISTS);
+ }
+ /* Fall through to create the semaphore handle */
+
+ if (offset == 0) {
+ /* A new named semaphore, so create both the private
+ * and shared parts
+ */
+ if (strlen (utf8_name) < MAX_PATH) {
+ namelen = strlen (utf8_name);
+ } else {
+ namelen = MAX_PATH;
+ }
+
+ memcpy (&namedsem_handle.sharedns.name, utf8_name, namelen);
+
+ namedsem_handle.val = initial;
+ namedsem_handle.max = max;
+
+ handle = _wapi_handle_new (WAPI_HANDLE_NAMEDSEM,
+ &namedsem_handle);
+ } else {
+ /* A new reference to an existing named semaphore, so
+ * just create the private part
+ */
+ handle = _wapi_handle_new_from_offset (WAPI_HANDLE_NAMEDSEM,
+ offset, TRUE);
+ }
+
+ if (handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating named sem handle", __func__);
+ SetLastError (ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+ ret = handle;
+
+ if (offset == 0) {
+ /* Set the initial state, as this is a completely new
+ * handle
+ */
+ thr_ret = _wapi_handle_lock_shared_handles ();
+ g_assert (thr_ret == 0);
+
+ if (initial != 0) {
+ _wapi_shared_handle_set_signal_state (handle, TRUE);
+ }
+
+ _wapi_handle_unlock_shared_handles ();
+ }
+
+ DEBUG ("%s: returning named sem handle %p", __func__, handle);
+
+cleanup:
+ g_free (utf8_name);
+
+ _wapi_namespace_unlock (NULL);
+
+ return (ret);