implemented LsarClose()
Modified: trunk/reactos/lib/lsasrv/lsarpc.c

Modified: trunk/reactos/lib/lsasrv/lsarpc.c
--- trunk/reactos/lib/lsasrv/lsarpc.c	2006-01-15 13:44:14 UTC (rev 20892)
+++ trunk/reactos/lib/lsasrv/lsarpc.c	2006-01-15 14:18:43 UTC (rev 20893)
@@ -11,19 +11,85 @@
 #define NDEBUG
 #include <debug.h>
 
+#define POLICY_DELETE (RTL_HANDLE_VALID << 1)
+typedef struct _LSAR_POLICY_HANDLE
+{
+    ULONG Flags;
+    LONG RefCount;
+    ACCESS_MASK AccessGranted;
+} LSAR_POLICY_HANDLE, *PLSAR_POLICY_HANDLE;
 
-/* GLOBALS *****************************************************************/
+static RTL_CRITICAL_SECTION PolicyHandleTableLock;
+static RTL_HANDLE_TABLE PolicyHandleTable;
 
-/* VARIABLES ***************************************************************/
+/* FUNCTIONS ***************************************************************/
 
+static NTSTATUS
+ReferencePolicyHandle(IN LSA_HANDLE ObjectHandle,
+                      IN ACCESS_MASK DesiredAccess,
+                      OUT PLSAR_POLICY_HANDLE *Policy)
+{
+    PLSAR_POLICY_HANDLE ReferencedPolicy;
+    NTSTATUS Status = STATUS_SUCCESS;
 
-/* FUNCTIONS ***************************************************************/
+    RtlEnterCriticalSection(&PolicyHandleTableLock);
 
+    if (RtlIsValidIndexHandle(&PolicyHandleTable,
+                              (ULONG)ObjectHandle,
+                              (PRTL_HANDLE_TABLE_ENTRY*)&ReferencedPolicy) &&
+        !(ReferencedPolicy->Flags & POLICY_DELETE))
+    {
+        if (RtlAreAllAccessesGranted(ReferencedPolicy->AccessGranted,
+                                     DesiredAccess))
+        {
+            ReferencedPolicy->RefCount++;
+            *Policy = ReferencedPolicy;
+        }
+        else
+            Status = STATUS_ACCESS_DENIED;
+    }
+    else
+        Status = STATUS_INVALID_HANDLE;
+
+    RtlLeaveCriticalSection(&PolicyHandleTableLock);
+
+    return Status;
+}
+
+static VOID
+DereferencePolicyHandle(IN OUT PLSAR_POLICY_HANDLE Policy,
+                        IN BOOLEAN Delete)
+{
+    RtlEnterCriticalSection(&PolicyHandleTableLock);
+
+    if (Delete)
+    {
+        Policy->Flags |= POLICY_DELETE;
+        Policy->RefCount--;
+
+        ASSERT(Policy->RefCount != 0);
+    }
+
+    if (--Policy->RefCount == 0)
+    {
+        ASSERT(Policy->Flags & POLICY_DELETE);
+        RtlFreeHandle(&PolicyHandleTable,
+                      (PRTL_HANDLE_TABLE_ENTRY)Policy);
+    }
+
+    RtlLeaveCriticalSection(&PolicyHandleTableLock);
+}
+
 VOID
 LsarStartRpcServer(VOID)
 {
     RPC_STATUS Status;
 
+    RtlInitializeCriticalSection(&PolicyHandleTableLock);
+    RtlInitializeHandleTable(0x1000,
+                             sizeof(LSAR_POLICY_HANDLE),
+                             &PolicyHandleTable);
+
     DPRINT("LsarStartRpcServer() called");
 
     Status = RpcServerUseProtseqEpW(L"ncacn_np",
@@ -60,8 +126,22 @@
 LsarClose(IN handle_t BindingHandle,
           IN unsigned long ObjectHandle)
 {
+    PLSAR_POLICY_HANDLE Policy = NULL;
+    NTSTATUS Status;
+
     DPRINT1("LsarClose(0x%p) called!\n", ObjectHandle);
-    return STATUS_INVALID_HANDLE;
+
+    Status = ReferencePolicyHandle((LSA_HANDLE)ObjectHandle,
+                                   0,
+                                   &Policy);
+    if (NT_SUCCESS(Status))
+    {
+        /* delete the handle */
+        DereferencePolicyHandle(Policy,
+                                TRUE);
+    }
+
+    return Status;
 }
 
 /* EOF */