#include "reactos/internal/se.h" /* for SeInit2() */
#include "captive/leave.h"
#include "captive/options.h"
+#include <libgnomevfs/gnome-vfs-result.h>
+#include "lib.h"
+#include <reactos/ddk/obfuncs.h>
struct captive_options *captive_options;
}
if (captive_options->rwmode==CAPTIVE_OPTION_RWMODE_BLIND)
- captive_image_iochannel=(GIOChannel *)captive_giochannel_blind_new(captive_options->image_iochannel);
+ captive_image_iochannel=(GIOChannel *)captive_giochannel_blind_new(captive_options->image_iochannel,
+ TRUE); /* writeable */
else
captive_image_iochannel=captive_options->image_iochannel;
}
+static void dismount_volume(void)
+{
+IO_STATUS_BLOCK IoStatusBlock;
+PIO_STACK_LOCATION StackPtr;
+PIRP Irp;
+NTSTATUS Status;
+DEVICE_OBJECT *DeviceObject=captive_DriverObject.DeviceObject;
+OBJECT_ATTRIBUTES dir_ObjectAttributes;
+HANDLE dir_Handle;
+FILE_OBJECT *FileObject;
+GnomeVFSResult errvfsresult;
+NTSTATUS err;
+IO_STATUS_BLOCK dir_IoStatusBlock;
+
+ errvfsresult=captive_ObjectAttributes_init("/!Captive!del",&dir_ObjectAttributes);
+ g_return_if_fail(errvfsresult==GNOME_VFS_OK);
+
+ /* wanted: * IoCreateFile()->ObCreateObject(,,,IoFileObjectType)->
+ * ->(IoFileObjectType->Create==IopCreateFile)()->IoMountVolume()
+ */
+ err=IoCreateFile(
+ &dir_Handle, /* FileHandle */
+ GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE|0x80, /* DesiredAccess; 0xC0100080=GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE|0x80 */
+ &dir_ObjectAttributes, /* ObjectAttributes */
+ &dir_IoStatusBlock, /* IoStatusBlock */
+ NULL, /* AllocationSize; ignored for open */
+ FILE_ATTRIBUTE_NORMAL, /* FileAttributes; ignored for open */
+ (FILE_SHARE_READ | FILE_SHARE_WRITE), /* ShareAccess; 0 means exclusive */
+ FILE_OPEN, /* CreateDisposition */
+ /* FILE_SYNCHRONOUS_IO_{,NON}ALERT: We need to allow W32 filesystem
+ * any waits to not to let it return STATUS_CANT_WAIT us.
+ * Alertability should have only effect on asynchronous events
+ * from KeWaitForSingleObject() by setting/clearing its parameter 'Alertable'.
+ */
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, /* CreateOptions; FILE_DIRECTORY_FILE is forbidden */
+ NULL, /* EaBuffer */
+ 0, /* EaLength */
+ CreateFileTypeNone, /* CreateFileType */
+ NULL, /* ExtraCreateParameters */
+ 0); /* Options */
+ g_free(dir_ObjectAttributes.ObjectName); /* left from captive_gnomevfs_uri_parent_init() */
+ g_return_if_fail(NT_SUCCESS(err)==NT_SUCCESS(dir_IoStatusBlock.Status));
+ g_return_if_fail(NT_SUCCESS(err));
+ g_return_if_fail(dir_IoStatusBlock.Information==FILE_OPENED);
+
+ Status=ObReferenceObjectByHandle(dir_Handle,FILE_LIST_DIRECTORY,IoFileObjectType,UserMode,(PVOID *)&FileObject,NULL);
+ g_assert(NT_SUCCESS(Status));
+
+ Irp=IoAllocateIrp(DeviceObject->StackSize,TRUE);
+ g_return_if_fail(Irp!=NULL);
+
+ Irp->UserIosb=&IoStatusBlock;
+ Irp->UserEvent=&FileObject->Event;
+ Irp->Tail.Overlay.Thread=PsGetCurrentThread();
+
+ StackPtr=IoGetNextIrpStackLocation(Irp);
+ StackPtr->MajorFunction=IRP_MJ_FILE_SYSTEM_CONTROL;
+ StackPtr->MinorFunction=IRP_MN_USER_FS_REQUEST;
+ StackPtr->Flags=0;
+ StackPtr->Control=0;
+ StackPtr->DeviceObject=DeviceObject; /* FIXME: FileObject->Vpb->DeviceObject ? */
+ StackPtr->FileObject=FileObject;
+ StackPtr->CompletionRoutine=NULL;
+
+ StackPtr->Parameters.FileSystemControl.OutputBufferLength=0;
+ StackPtr->Parameters.FileSystemControl.InputBufferLength=0;
+ StackPtr->Parameters.FileSystemControl.FsControlCode=FSCTL_DISMOUNT_VOLUME;
+ StackPtr->Parameters.FileSystemControl.Type3InputBuffer=NULL;
+
+ /* IoCallDriver() will do one ObDereferenceObject(FileObject)
+ * in its IoSecondStageCompletion().
+ * Do not leave to dereference it itself as we need its 'FileObject->Event'.
+ */
+ ObReferenceObject(FileObject);
+
+ Status=IoCallDriver(DeviceObject,Irp);
+ if (Status==STATUS_PENDING) {
+ KeWaitForSingleObject(&FileObject->Event,Executive,KernelMode,FALSE,NULL);
+ Status=IoStatusBlock.Status;
+ }
+ g_assert(NT_SUCCESS(Status));
+
+ ObDereferenceObject(FileObject);
+}
+
+
BOOLEAN captive_cc_FileObject_delete(FILE_OBJECT *FileObject);
void captive_cc_flush(void);
FALSE)) /* may_block */
g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: g_main_context_iteration() proceeded",G_STRLOC);
+ captive_cc_flush(); /* based on captive_leave(), not g_main idle */
+
+ dismount_volume();
+
+ /* Invoke all pending idle functions just to not to forget for anything... */
+ while (g_main_context_iteration(
+ NULL, /* context; NULL means default one */
+ FALSE)) /* may_block */
+ g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: g_main_context_iteration() proceeded",G_STRLOC);
+
captive_PoQueueShutdownWorkItem_hooklist_invoke();
- captive_cc_flush();
-
- /* During IoShutdownRegisteredFileSystems() - IRP_MJ_SHUTDOWN to be specific
- * some buffers will be written but after the IofCallDriver() it will be
- * no longer possible to flush such buffers to their DeviceVolumeFile.
- * Therefore we must flush such buffers on the fly although such behaviour
- * would crash us in regular case as filesystems access BCBs even after their
- * CcUnpinData().
+
+ /* Do not: captive_cc_flush();
+ * as the dirty blocks should have been already commited by dismount_volume(),
+ * any further commits would get us just STATUS_VOLUME_DISMOUNTED.
+ */
+
+ /* Do not: captive_cc_unmounting=TRUE;
+ * Without dismount_volume() it was:
+ * During IoShutdownRegisteredFileSystems() - IRP_MJ_SHUTDOWN to be specific
+ * some buffers will be written but after the IofCallDriver() it will be
+ * no longer possible to flush such buffers to their DeviceVolumeFile.
+ * Therefore we must flush such buffers on the fly although such behaviour
+ * would crash us in regular case as filesystems access BCBs even after their
+ * CcUnpinData().
+ * Currently the dirty blocks should have been already commited by dismount_volume(),
*/
- captive_cc_unmounting=TRUE;
/* FIXME: ntoskrnl/ex/power.c/NtShutdownSystem() does
* IoShutdownRegistered{Devices,FileSystems} order; is it correct?
*/
IoShutdownRegisteredFileSystems();
- /* Just a sanity check as all the dirty data should
- * get already flushed during IoShutdownRegisteredFileSystems().
+ /* Do not: captive_cc_FileObject_delete(NULL);
+ * as the dirty blocks should have been already commited by dismount_volume(),
+ * any further commits would get us just STATUS_VOLUME_DISMOUNTED.
*/
- captive_cc_FileObject_delete(
- NULL); /* FileObject */
IoShutdownRegisteredDevices();