Integrate static packaing into the CVS HEAD; make it even default.
[captive.git] / src / libcaptive / client / init.c
index a2459e4..9e9466c 100644 (file)
@@ -52,6 +52,9 @@
 #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() */
+#include "standalone.h"
 
 
 struct captive_options *captive_options;
@@ -167,14 +170,17 @@ NTSTATUS err;
                *KeNumberProcessorsp=KeNumberProcessors;
                g_assert(*KeNumberProcessorsp==1);
                }
-       /* Apply captive_kernel_patches() AFTER any symbols sanity checks above! */
-       captive_kernel_patches();
+       /* Apply AFTER any symbols sanity checks above! */
+       if (captive_options->debug_messages)
+               captive_kernel_patches_debug();
+       else
+               captive_kernel_patches_nondebug();
 
        _local_unwind2_addr=captive_Module_GetExportAddress("ntoskrnl.exe","_local_unwind2");
 
        /* Initialize 'FsRtlLegalAnsiCharacterArray'.
         * It requires 'ntoskrnl.exe' loaded by 'captive_options->load_module' above;
-        * captive_kernel_patches() should not be needed.
+        * captive_kernel_patches_debug()/captive_kernel_patches_nondebug() should not be needed.
         */
        captive_FsRtlLegalAnsiCharacterArray_init();
 
@@ -322,21 +328,34 @@ gboolean errbool;
                        |G_LOG_LEVEL_DEBUG
                        ));
 
+       g_return_val_if_fail(captive_standalone_init_done==FALSE,FALSE);
        g_return_val_if_fail(active==FALSE,FALSE);
 
        g_return_val_if_fail(captive_options!=NULL,FALSE);
        g_return_val_if_fail(captive_options->image_iochannel!=NULL,FALSE);
 
-       /* Initialize GObject subsystem of GLib. */
-       g_type_init();
+       /* Do not: g_type_init();
+        * as it is done by: captive_standalone_init()
+        */
 
        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,
+       if (captive_options->rwmode==CAPTIVE_OPTION_RWMODE_RW && !captive_options->sandbox)
+               g_error(_("Rejecting --rw --no-sandbox operation as too dangerous - use --blind or --sandbox"));
+
+       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().
@@ -353,7 +372,7 @@ gboolean errbool;
 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;
@@ -363,10 +382,26 @@ FILE_OBJECT *FileObject;
 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);
@@ -411,10 +446,7 @@ WCHAR wzero;
        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);
 
@@ -422,26 +454,40 @@ WCHAR wzero;
                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'.
@@ -455,7 +501,7 @@ WCHAR wzero;
                        }
                g_assert(NT_SUCCESS(Status)
                                || (Status==STATUS_MEDIA_WRITE_PROTECTED && captive_options->rwmode==CAPTIVE_OPTION_RWMODE_RO));
-       }
+               }
 
        ObDereferenceObject(FileObject);
 }
@@ -491,8 +537,14 @@ GIOStatus erriostatus;
         * 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 */
@@ -531,21 +583,13 @@ GIOStatus erriostatus;
 
        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;