#include <reactos/ddk/obfuncs.h>
#include <syslog.h>
#include "captive/macros.h"
+#include "../storage/relastblock.h" /* for captive_storage_relastblock() */
+#include "../cc/sharedcachemap.h" /* for captive_shared_cache_map_flush_all() */
struct captive_options *captive_options;
captive_log_init(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=captive_options->image_iochannel;
+ g_io_channel_ref(captive_image_iochannel);
+
+ captive_image_iochannel=captive_storage_relastblock(captive_image_iochannel);
+
+ if (captive_options->rwmode==CAPTIVE_OPTION_RWMODE_BLIND) {
+ GIOChannel *captive_image_iochannel_orig;
+
+ captive_image_iochannel_orig=captive_image_iochannel;
+ captive_image_iochannel=(GIOChannel *)captive_giochannel_blind_new(captive_image_iochannel,
TRUE); /* writeable */
- else
- captive_image_iochannel=captive_options->image_iochannel;
+ g_io_channel_unref(captive_image_iochannel_orig); /* reffed by captive_giochannel_blind_new() */
+ }
/* Do not initialize 'captive_image_size' by captive_giochannel_size() here
* as we yet need to do g_io_channel_set_encoding().
static void dismount_volume(void)
{
IO_STATUS_BLOCK IoStatusBlock;
-PIO_STACK_LOCATION StackPtr;
+PEXTENDED_IO_STACK_LOCATION StackPtr;
PIRP Irp;
NTSTATUS Status;
DEVICE_OBJECT *DeviceObject=captive_DriverObject.DeviceObject;
GnomeVFSResult errvfsresult;
NTSTATUS err;
IO_STATUS_BLOCK dir_IoStatusBlock;
+/*
+ * TraceFS reported only IRP_MJ_FLUSH_BUFFERS
+ * and IRP_MJ_SHUTDOWN.
+ * Apparently it is not enough, FSCTL_DISMOUNT_VOLUME is needed,
+ * otherwise NT-5.1 autochkdsks the disk and W2000 may give BSOD during boot.
+ */
+enum step {
+ /* First item value assumed to be 0. */
+ STEP_IRP_MJ_FLUSH_BUFFERS_PRE,
#if 0
-static const ULONG fsctls[2]={ FSCTL_LOCK_VOLUME,FSCTL_DISMOUNT_VOLUME };
-int fsctlsi;
+ /* DISABLED: STATUS_ACCESS_DENIED; FIXME: Why?
+ * The official way of device modification is: LOCK,DISMOUNT
+ * but LOCK fails for Captive if any file was written (and closed).
+ */
+ STEP_FSCTL_LOCK_VOLUME,
#endif
+ STEP_FSCTL_DISMOUNT_VOLUME,
+ STEP_IRP_MJ_FLUSH_BUFFERS_POST,
+ STEP_MAX=3,
+ } stepi;
WCHAR wzero;
errvfsresult=captive_ObjectAttributes_init("/!Captive!del",&dir_ObjectAttributes);
FileObject->FileName.MaximumLength=2;
FileObject->FileName.Buffer=&wzero;
-#if 0
- for (fsctlsi=0;fsctlsi<2;fsctlsi++)
-#endif
- {
+ for (stepi=0;stepi<STEP_MAX;stepi++) {
Irp=IoAllocateIrp(DeviceObject->StackSize,TRUE);
g_return_if_fail(Irp!=NULL);
Irp->UserEvent=&FileObject->Event;
Irp->Tail.Overlay.Thread=PsGetCurrentThread();
- StackPtr=IoGetNextIrpStackLocation(Irp);
-#if 0
- StackPtr->MajorFunction=IRP_MJ_FILE_SYSTEM_CONTROL;
- StackPtr->MinorFunction=IRP_MN_USER_FS_REQUEST;
-#else
- StackPtr->MajorFunction=IRP_MJ_FLUSH_BUFFERS;
+ StackPtr=(EXTENDED_IO_STACK_LOCATION *)IoGetNextIrpStackLocation(Irp);
+ switch (stepi) {
+ case STEP_IRP_MJ_FLUSH_BUFFERS_PRE:
+ StackPtr->MajorFunction=IRP_MJ_FLUSH_BUFFERS;
+ break;
+#if 0 /* Disabled, see 'STEP_FSCTL_LOCK_VOLUME'. */
+ case STEP_FSCTL_LOCK_VOLUME:
+ StackPtr->MajorFunction=IRP_MJ_FILE_SYSTEM_CONTROL;
+ StackPtr->MinorFunction=IRP_MN_USER_FS_REQUEST;
+ StackPtr->Parameters.FileSystemControl.OutputBufferLength=0;
+ StackPtr->Parameters.FileSystemControl.InputBufferLength=0;
+ StackPtr->Parameters.FileSystemControl.FsControlCode=FSCTL_LOCK_VOLUME;
+ StackPtr->Parameters.FileSystemControl.Type3InputBuffer=NULL;
+ break;
#endif
+ case STEP_FSCTL_DISMOUNT_VOLUME:
+ StackPtr->MajorFunction=IRP_MJ_FILE_SYSTEM_CONTROL;
+ StackPtr->MinorFunction=IRP_MN_USER_FS_REQUEST;
+ StackPtr->Parameters.FileSystemControl.OutputBufferLength=0;
+ StackPtr->Parameters.FileSystemControl.InputBufferLength=0;
+ StackPtr->Parameters.FileSystemControl.FsControlCode=FSCTL_DISMOUNT_VOLUME;
+ StackPtr->Parameters.FileSystemControl.Type3InputBuffer=NULL;
+ break;
+ case STEP_IRP_MJ_FLUSH_BUFFERS_POST:
+ StackPtr->MajorFunction=IRP_MJ_FLUSH_BUFFERS;
+ break;
+ default: g_assert_not_reached();
+ }
StackPtr->Flags=0;
StackPtr->Control=0;
StackPtr->DeviceObject=DeviceObject; /* FIXME: FileObject->Vpb->DeviceObject ? */
StackPtr->FileObject=FileObject;
StackPtr->CompletionRoutine=NULL;
-#if 0
- StackPtr->Parameters.FileSystemControl.OutputBufferLength=0;
- StackPtr->Parameters.FileSystemControl.InputBufferLength=0;
- StackPtr->Parameters.FileSystemControl.FsControlCode=fsctls[fsctlsi];
- StackPtr->Parameters.FileSystemControl.Type3InputBuffer=NULL;
-#endif
-
/* IoCallDriver() will do one ObDereferenceObject(FileObject)
* in its IoSecondStageCompletion().
* Do not leave to dereference it itself as we need its 'FileObject->Event'.
}
g_assert(NT_SUCCESS(Status)
|| (Status==STATUS_MEDIA_WRITE_PROTECTED && captive_options->rwmode==CAPTIVE_OPTION_RWMODE_RO));
- }
+ }
ObDereferenceObject(FileObject);
}
* replaced by IRP_MJ_FLUSH_BUFFERS.
*/
+ /* Probably not needed: captive_shared_cache_map_flush_all();
+ */
+
dismount_volume();
+ /* Probably not needed: captive_shared_cache_map_flush_all();
+ */
+
/* Invoke all pending idle functions just to not to forget for anything... */
while (g_main_context_iteration(
NULL, /* context; NULL means default one */
IoShutdownRegisteredDevices();
- /* libcaptive is not authorized to shutdown 'captive_image_channel'. */
+ /* Just a sanity if 'captive_image_iochannel' is already reffed a bit more... */
erriostatus=g_io_channel_flush(
captive_image_iochannel, /* channel */
NULL); /* error */
g_assert(erriostatus==G_IO_STATUS_NORMAL);
- /* 'captive_image_iochannel' may be blinded wrapper of 'captive_options->image_iochannel'. */
- if (captive_image_iochannel!=captive_options->image_iochannel) {
- erriostatus=g_io_channel_flush(
- captive_options->image_iochannel, /* channel */
- NULL); /* error */
- g_assert(erriostatus==G_IO_STATUS_NORMAL);
- g_io_channel_unref(captive_image_iochannel);
- }
-
+ g_io_channel_unref(captive_image_iochannel);
captive_image_iochannel=NULL;
active=FALSE;