--- /dev/null
+/* $Id$
+ * reactos ERESOURCE handling by libcaptive
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "config.h"
+
+#include "reactos/ddk/exfuncs.h" /* self */
+#include <glib/gmessages.h>
+#include "reactos/ddk/extypes.h" /* for ERESOURCE */
+#include "captive/macros.h"
+
+
+#define ERESOURCE_OWNING_COUNT_SHARED(Resource) ((Resource)->OwnerThreads[0].a.OwnerCount)
+#define ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource) ((Resource)->OwnerThreads[1].a.OwnerCount)
+
+
+static gboolean PERESOURE_validate(PERESOURCE Resource)
+{
+ g_return_val_if_fail(Resource!=NULL,FALSE);
+
+ g_return_val_if_fail(Resource->ActiveCount
+ ==ERESOURCE_OWNING_COUNT_SHARED(Resource)+ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource),FALSE);
+
+ return TRUE;
+}
+
+
+/**
+ * ExAcquireResourceExclusiveLite:
+ * @Resource: Resource to acquire for exclusive access.
+ * %NULL value is forbidden.
+ * @Wait: %TRUE if the caller may wait to acquire @Resource.
+ *
+ * Acquires a resource exclusively for the calling thread.
+ *
+ * Returns: %TRUE if the resource was acquired.
+ * libcaptive always returns %TRUE.
+ */
+BOOLEAN ExAcquireResourceExclusiveLite(PERESOURCE Resource,BOOLEAN Wait)
+{
+ g_return_val_if_fail(PERESOURE_validate(Resource),FALSE);
+
+ Resource->ActiveCount++;
+ ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource)++;
+
+ g_assert(PERESOURE_validate(Resource));
+ return TRUE;
+}
+
+
+/**
+ * ExAcquireResourceSharedLite:
+ * @Resource: Resource to acquire.
+ * %NULL value is forbidden.
+ * @Wait: %TRUE if the caller may wait to acquire @Resource.
+ *
+ * Shared acquire of resource for the calling thread.
+ *
+ * Returns: %TRUE if the resource was acquired.
+ * libcaptive always returns %TRUE.
+ */
+BOOLEAN ExAcquireResourceSharedLite(PERESOURCE Resource,BOOLEAN Wait)
+{
+ g_return_val_if_fail(PERESOURE_validate(Resource),FALSE);
+
+ Resource->ActiveCount++;
+ ERESOURCE_OWNING_COUNT_SHARED(Resource)++;
+
+ g_assert(PERESOURE_validate(Resource));
+ return TRUE;
+}
+
+
+/**
+ * ExConvertExclusiveToSharedLite:
+ * @Resource: Resource to convert access mode.
+ * %NULL value is forbidden.
+ *
+ * Converts a given resource from acquired for exclusive access to being
+ * acquired for shared access.
+ *
+ * You must already have exclusive access to @Resource before the call.
+ */
+VOID ExConvertExclusiveToSharedLite(PERESOURCE Resource)
+{
+ g_return_if_fail(PERESOURE_validate(Resource));
+ g_return_if_fail(ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource)>0);
+
+ ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource)--;
+ ERESOURCE_OWNING_COUNT_SHARED(Resource)++;
+
+ g_assert(PERESOURE_validate(Resource));
+}
+
+
+/**
+ * ExAcquireSharedStarveExclusive:
+ * @Resource: Resource to acquire for shared access.
+ * %NULL value is forbidden.
+ * @Wait: %TRUE if the caller should wait to acquire @Resource.
+ *
+ * Acquires a given resource for shared access. Current thread has priority
+ * over any threads currently wating for exclusive access to this @Resource.
+ *
+ * libcaptive has the same implementation as ExAcquireResourceSharedLite().
+ *
+ * Returns: %TRUE if the resource was acquired.
+ * libcaptive always returns %TRUE.
+ */
+BOOLEAN ExAcquireSharedStarveExclusive(PERESOURCE Resource,BOOLEAN Wait)
+{
+ g_return_val_if_fail(PERESOURE_validate(Resource),FALSE);
+
+ return ExAcquireResourceSharedLite(Resource,Wait);
+}
+
+
+/**
+ * ExAcquireSharedWaitForExclusive:
+ * @Resource: Resource to acquire for shared access.
+ * %NULL value is forbidden.
+ * @Wait: %TRUE if the caller should wait to acquire @Resource.
+ *
+ * Acquires a given resource for shared access. Any threads currently wating
+ * for exclusive access to this @Resource have priority over the current
+ * thread.
+ *
+ * libcaptive has the same implementation as ExAcquireResourceSharedLite().
+ *
+ * Returns: %TRUE if the resource was acquired.
+ * libcaptive always returns %TRUE.
+ */
+BOOLEAN ExAcquireSharedWaitForExclusive(PERESOURCE Resource,BOOLEAN Wait)
+{
+ g_return_val_if_fail(PERESOURE_validate(Resource),FALSE);
+
+ return ExAcquireResourceSharedLite(Resource,Wait);
+}
+
+
+/**
+ * ExReleaseResourceForThreadLite:
+ * @Resource: Resource to release.
+ * %NULL value is forbidden.
+ * @ResourceThreadId: Thread which currently owns @Resource.
+ * %NULL value is forbidden.
+ * Value ExGetCurrentResourceThread() required by libcaptive.
+ *
+ * Function releases @Resource. @ResourceThreadId must be either exclusive or
+ * shared owner of @Resource.
+ * FIXME: W32 undocumented: Ownership counter is decremented by 1;
+ * @ResourceThreadId may still own @Resource after this function finishes.
+ * FIXME: W32 undocumented: It is expected shared ownership should be released first.
+ * ntfs.sys of NT-5.1sp1 behaviour: Init,AcqExcl,AcqShared,Rel,expectExcl.
+ * Maybe acquire ordering also makes sense?
+ */
+VOID ExReleaseResourceForThreadLite(PERESOURCE Resource,ERESOURCE_THREAD ResourceThreadId)
+{
+ g_return_if_fail(PERESOURE_validate(Resource));
+ g_return_if_fail(ResourceThreadId==ExGetCurrentResourceThread());
+ g_return_if_fail(Resource->ActiveCount>0);
+
+ /**/ if (ERESOURCE_OWNING_COUNT_SHARED(Resource)>0)
+ ERESOURCE_OWNING_COUNT_SHARED(Resource)--;
+ else if (ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource)>0)
+ ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource)--;
+ else g_assert_not_reached();
+
+ Resource->ActiveCount--;
+
+ g_assert(PERESOURE_validate(Resource));
+}
+
+
+/**
+ * ExReleaseResourceForThreadLite:
+ * @Resource: Resource to release.
+ * %NULL value is forbidden.
+ *
+ * Function releases @Resource. Current thread must be either exclusive or
+ * shared owner of @Resource.
+ * FIXME: W32 undocumented: Ownership counter is decremented by 1;
+ * Current thread may still own @Resource after this function finishes.
+ * FIXME: W32 undocumented: It is expected exclusive ownership should be released first.
+ */
+VOID ExReleaseResourceLite(PERESOURCE Resource)
+{
+ g_return_if_fail(PERESOURE_validate(Resource));
+
+ return ExReleaseResourceForThreadLite(Resource,ExGetCurrentResourceThread());
+}
+
+
+/**
+ * ExGetExclusiveWaiterCount:
+ * @Resource: Resource to query.
+ * %NULL value is forbidden.
+ *
+ * Reports the number of waiters for exclusive access.
+ *
+ * Returns: Number of waiters for exclusive access.
+ * This function always returns 0 by libcaptive.
+ */
+ULONG ExGetExclusiveWaiterCount(PERESOURCE Resource)
+{
+ g_return_val_if_fail(PERESOURE_validate(Resource),0);
+
+ return 0;
+}
+
+
+/**
+ * ExGetSharedWaiterCount:
+ * @Resource: Resource to query.
+ * %NULL value is forbidden.
+ *
+ * Reports the number of currently pending waiters for shared access to
+ * @Resource.
+ *
+ * Returns: Number of waiters for shared access.
+ * This function always returns 0 by libcaptive.
+ */
+ULONG ExGetSharedWaiterCount(PERESOURCE Resource)
+{
+ g_return_val_if_fail(PERESOURE_validate(Resource),0);
+
+ return 0;
+}
+
+
+/*
+ * ExIsResourceAcquiredExclusiveLite:
+ * @Resource: Resource to query.
+ * %NULL value is forbidden.
+ *
+ * Query if the calling thread owns exclusive access to @Resource.
+ *
+ * Returns: %TRUE if the caller has exclusive access to @Resource,
+ */
+BOOLEAN ExIsResourceAcquiredExclusiveLite(PERESOURCE Resource)
+{
+ g_return_val_if_fail(PERESOURE_validate(Resource),FALSE);
+
+ return ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource)>0;
+}
+
+
+/*
+ * ExIsResourceAcquiredSharedLite:
+ * @Resource: Resource to query.
+ * %NULL value is forbidden.
+ *
+ * Query if the calling thread owns shared access to @Resource.
+ * Exclusive access is considered equivalent to shared access in this case.
+ *
+ * Returns: Count how many times the caller owns @Resource for any access,
+ * Value 0 is returned if the resource is not owned at all.
+ */
+ULONG ExIsResourceAcquiredSharedLite(PERESOURCE Resource)
+{
+ g_return_val_if_fail(PERESOURE_validate(Resource),0);
+
+ return Resource->ActiveCount;
+}
+
+
+/**
+ * ExInitializeResourceLite:
+ * @Resource: Memory block of size #PERESOURCE to initialize.
+ * %NULL value is forbidden.
+ *
+ * Initializes fields of #PERESOURCE structure.
+ *
+ * Returns: %STATUS_SUCCESS if the resource was initialized successfully.
+ * libcaptive always returns %STATUS_SUCCESS.
+ */
+NTSTATUS ExInitializeResourceLite(PERESOURCE Resource)
+{
+ g_return_val_if_fail(Resource!=NULL,STATUS_INVALID_PARAMETER);
+
+ CAPTIVE_MEMZERO(Resource);
+ KeInitializeSpinLock(&Resource->SpinLock);
+
+ g_assert(PERESOURE_validate(Resource));
+ return STATUS_SUCCESS;
+}
+
+
+/*
+ * ExReinitializeResourceLite:
+ * @Resource: Resource to reinitialize sized as #ERESOURCE.
+ * %NULL value is forbidden.
+ *
+ * Reinitialize data fields of @Resource. @Resource must be already initialized
+ * by ExInitializeResourceLite(). Its state is lost and it becomes a fresh new
+ * #ERESOURCED without any its owners.
+ */
+VOID ExReinitializeResourceLite(PERESOURCE Resource)
+{
+ g_return_if_fail(PERESOURE_validate(Resource));
+
+ ExDeleteResourceLite(Resource); /* errors ignored */
+ ExInitializeResourceLite(Resource); /* errors ignored */
+}
+
+
+/**
+ * ExDeleteResourceLite:
+ * @Resource: Resource to delete.
+ * %NULL value is forbidden.
+ *
+ * Deletes any resources allocated for @Resource. Memory of #ERESOURCE pointer
+ * directly by @Resource is not freed - its storage belongs to the caller.
+ *
+ * This function is a NOP for libcaptive.
+ *
+ * Returns: %STATUS_SUCCESS if the resource was successfully deleted.
+ * libcaptive always returns %STATUS_SUCCESS.
+ */
+NTSTATUS ExDeleteResourceLite(PERESOURCE Resource)
+{
+ g_return_val_if_fail(PERESOURE_validate(Resource),STATUS_INVALID_PARAMETER);
+
+ return STATUS_SUCCESS;
+}