Synchronize with trunk's revision r57652.
[reactos.git] / drivers / filters / mountmgr / database.c
index d9507fb..634bd2f 100644 (file)
@@ -175,7 +175,9 @@ GetRemoteDatabaseEntry(IN HANDLE Database,
                         &ByteOffset,
                         NULL);
     /* If it fails or returns inconsistent data, drop it (= truncate) */
-    if (!NT_SUCCESS(Status) || IoStatusBlock.Information != EntrySize || EntrySize < sizeof(DATABASE_ENTRY))
+    if (!NT_SUCCESS(Status) ||
+        (IoStatusBlock.Information != EntrySize) ||
+        (EntrySize < sizeof(DATABASE_ENTRY)) )
     {
         TruncateRemoteDatabase(Database, StartingOffset);
         FreePool(Entry);
@@ -184,7 +186,7 @@ GetRemoteDatabaseEntry(IN HANDLE Database,
 
     /* Validate entry */
     if (MAX(Entry->SymbolicNameOffset + Entry->SymbolicNameLength,
-            Entry->UniqueIdOffset + Entry->UniqueIdLength) > EntrySize)
+            Entry->UniqueIdOffset + Entry->UniqueIdLength) > (LONG)EntrySize)
     {
         TruncateRemoteDatabase(Database, StartingOffset);
         FreePool(Entry);
@@ -194,11 +196,92 @@ GetRemoteDatabaseEntry(IN HANDLE Database,
     return Entry;
 }
 
+/*
+ * @implemented
+ */
 NTSTATUS
 DeleteRemoteDatabaseEntry(IN HANDLE Database,
                           IN LONG StartingOffset)
 {
-    return STATUS_NOT_IMPLEMENTED;
+    ULONG EndSize;
+    PVOID TmpBuffer;
+    NTSTATUS Status;
+    ULONG DatabaseSize;
+    PDATABASE_ENTRY Entry;
+    IO_STATUS_BLOCK IoStatusBlock;
+    LARGE_INTEGER EndEntriesOffset;
+
+    /* First, get database size */
+    DatabaseSize = GetRemoteDatabaseSize(Database);
+    if (!DatabaseSize)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Then, get the entry to remove */
+    Entry = GetRemoteDatabaseEntry(Database, StartingOffset);
+    if (!Entry)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Validate parameters: ensure we won't get negative size */
+    if (Entry->EntrySize + StartingOffset > DatabaseSize)
+    {
+        /* If we get invalid parameters, truncate the whole database
+         * starting the wrong entry. We can't rely on the rest
+         */
+        FreePool(Entry);
+        return TruncateRemoteDatabase(Database, StartingOffset);
+    }
+
+    /* Now, get the size of the remaining entries (those after the one to remove) */
+    EndSize = DatabaseSize - Entry->EntrySize - StartingOffset;
+    /* Allocate a buffer big enough to hold them */
+    TmpBuffer = AllocatePool(EndSize);
+    if (!TmpBuffer)
+    {
+        FreePool(Entry);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Get the offset of the entry right after the one to delete */
+    EndEntriesOffset.QuadPart = Entry->EntrySize + StartingOffset;
+    /* We don't need the entry any more */
+    FreePool(Entry);
+
+    /* Read the ending entries */
+    Status = ZwReadFile(Database, NULL, NULL, NULL, &IoStatusBlock,
+                        TmpBuffer, EndSize, &EndEntriesOffset, NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        FreePool(TmpBuffer);
+        return Status;
+    }
+
+    /* Ensure nothing went wrong - we don't want to corrupt the DB */
+    if (IoStatusBlock.Information != EndSize)
+    {
+        FreePool(TmpBuffer);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Remove the entry */
+    Status = TruncateRemoteDatabase(Database, StartingOffset + EndSize);
+    if (!NT_SUCCESS(Status))
+    {
+        FreePool(TmpBuffer);
+        return Status;
+    }
+
+    /* Now, shift the ending entries to erase the entry */
+    EndEntriesOffset.QuadPart = StartingOffset;
+    Status = ZwWriteFile(Database, NULL, NULL, NULL, &IoStatusBlock,
+                         TmpBuffer, EndSize, &EndEntriesOffset, NULL);
+
+    FreePool(TmpBuffer);
+
+    return Status;
 }
 
 /*
@@ -342,7 +425,8 @@ WorkerThread(IN PDEVICE_OBJECT DeviceObject,
     /* Acquire workers lock */
     KeWaitForSingleObject(&(DeviceExtension->WorkerSemaphore), Executive, KernelMode, FALSE, NULL);
 
-    OldIrql = KfAcquireSpinLock(&(DeviceExtension->WorkerLock));
+    KeAcquireSpinLock(&(DeviceExtension->WorkerLock), &OldIrql);
+
     /* Ensure there are workers */
     while (!IsListEmpty(&(DeviceExtension->WorkerQueueListHead)))
     {
@@ -352,7 +436,7 @@ WorkerThread(IN PDEVICE_OBJECT DeviceObject,
                                      RECONCILE_WORK_ITEM,
                                      WorkerQueueListEntry);
 
-        KfReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
+        KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
 
         /* Call it */
         WorkItem->WorkerRoutine(WorkItem->Context);
@@ -366,9 +450,9 @@ WorkerThread(IN PDEVICE_OBJECT DeviceObject,
         }
 
         KeWaitForSingleObject(&(DeviceExtension->WorkerSemaphore), Executive, KernelMode, FALSE, NULL);
-        OldIrql = KfAcquireSpinLock(&(DeviceExtension->WorkerLock));
+        KeAcquireSpinLock(&(DeviceExtension->WorkerLock), &OldIrql);
     }
-    KfReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
+    KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
 
     InterlockedDecrement(&(DeviceExtension->WorkerReferences));
 
@@ -397,10 +481,10 @@ QueueWorkItem(IN PDEVICE_EXTENSION DeviceExtension,
     }
 
     /* Otherwise queue worker for delayed execution */
-    OldIrql = KfAcquireSpinLock(&(DeviceExtension->WorkerLock));
+    KeAcquireSpinLock(&(DeviceExtension->WorkerLock), &OldIrql);
     InsertTailList(&(DeviceExtension->WorkerQueueListHead),
                    &(WorkItem->WorkerQueueListEntry));
-    KfReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
+    KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
 
     KeReleaseSemaphore(&(DeviceExtension->WorkerSemaphore), IO_NO_INCREMENT, 1, FALSE);
 
@@ -557,8 +641,8 @@ QueryVolumeName(IN HANDLE RootDirectory,
     }
 
     /* Return the volume name */
-    VolumeName->Length = FileNameInfo->FileNameLength;
-    VolumeName->MaximumLength = FileNameInfo->FileNameLength + sizeof(WCHAR);
+    VolumeName->Length = (USHORT)FileNameInfo->FileNameLength;
+    VolumeName->MaximumLength = (USHORT)FileNameInfo->FileNameLength + sizeof(WCHAR);
     VolumeName->Buffer = AllocatePool(VolumeName->MaximumLength);
     if (!VolumeName->Buffer)
     {
@@ -912,7 +996,7 @@ MigrateRemoteDatabaseWorker(IN PDEVICE_OBJECT DeviceObject,
     }
     if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
     {
-        Status == STATUS_SUCCESS;
+        Status = STATUS_SUCCESS;
         Complete = TRUE;
     }
     if (!NT_SUCCESS(Status) || Complete)
@@ -941,7 +1025,7 @@ MigrateRemoteDatabaseWorker(IN PDEVICE_OBJECT DeviceObject,
         }
 
         /* And write them into new database */
-        Length = IoStatusBlock.Information;
+        Length = (ULONG)IoStatusBlock.Information;
         Status = ZwWriteFile(Database,
                              NULL,
                              NULL,
@@ -1147,7 +1231,7 @@ QueryUniqueIdQueryRoutine(IN PWSTR ValueName,
     if (IntUniqueId)
     {
         /* Copy data & return */
-        IntUniqueId->UniqueIdLength = ValueLength;
+        IntUniqueId->UniqueIdLength = (USHORT)ValueLength;
         RtlCopyMemory(&(IntUniqueId->UniqueId), ValueData, ValueLength);
 
         UniqueId = Context;