+Workaround Linux kernel last device block inaccessibility.
[captive.git] / src / libcaptive / client / init.c
index 85dfdbd..7a963a0 100644 (file)
@@ -51,6 +51,8 @@
 #include "lib.h"
 #include <reactos/ddk/obfuncs.h>
 #include <syslog.h>
+#include "captive/macros.h"
+#include "../storage/relastblock.h"    /* for captive_storage_relastblock() */
 
 
 struct captive_options *captive_options;
@@ -73,14 +75,7 @@ static TOP_LEVEL_IRP TopLevelIrp;    /* TODO:thread */
 void *_local_unwind2_addr;
 
 
-/* Acceleration hack for ntoskrnl/dbg/print.c/DbgPrint() */
-gboolean captive_get_debug_messages(void)
-{
-       g_return_val_if_fail(captive_options!=NULL,TRUE);
-
-       return captive_options->debug_messages;
-}
-
+gboolean captive_debug_messages_disabled=FALSE;
 
 static gboolean captive_w32_init(void)
 {
@@ -173,14 +168,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();
 
@@ -204,10 +202,10 @@ NTSTATUS err;
                        captive_utf8_to_UnicodeString_alloca("\\captive\\filesystem")); /* DriverEntry_RegistryPath */
        g_return_val_if_fail(NT_SUCCESS(err),FALSE);
        if (captive_DriverObject_ReinitRoutine) {
-               (*captive_DriverObject_ReinitRoutine)(
+               captive_stdcall_call_12((CaptiveStdCallFunc12)captive_DriverObject_ReinitRoutine,
                                &captive_DriverObject,  /* DriverObject */
                                captive_DriverObject_ReinitRoutine_Context,     /* Context */
-                               1);     /* Count: # of calls of ReinitRoutine incl. the current one */
+                               (gpointer)1);   /* Count: # of calls of ReinitRoutine incl. the current one */
                }
 
        return TRUE;
@@ -256,6 +254,10 @@ void captive_log_init(const struct captive_options *captive_options)
 {
        g_return_if_fail(captive_options!=NULL);
 
+       /* FIXME: Fix sharing of different 'debug_messages' for various sandboxes. */
+       captive_debug_messages_disabled=!captive_options->debug_messages;
+
+       /* FIXME: Fix sharing of different 'debug_messages' for various sandboxes. */
        if (!captive_options->debug_messages) {
                /* FIXME: Save handler_id and destroy it in captive_vfs_close(). */
                g_log_set_handler(
@@ -334,11 +336,19 @@ gboolean errbool;
 
        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().
@@ -377,6 +387,8 @@ WCHAR wzero;
        /* wanted: * IoCreateFile()->ObCreateObject(,,,IoFileObjectType)->
         * ->(IoFileObjectType->Create==IopCreateFile)()->IoMountVolume()
         */
+       CAPTIVE_MEMZERO(&dir_IoStatusBlock);    /* FIXME: Try to pre-clear it - uninitialized otherwise? */
+       dir_IoStatusBlock.Information=FILE_OPENED;      /* FIXME: Try to pre-set it - uninitialized otherwise? */
        err=IoCreateFile(
                        &dir_Handle,    /* FileHandle */
                        GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE|0x80,    /* DesiredAccess; 0xC0100080=GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE|0x80 */
@@ -398,8 +410,8 @@ WCHAR wzero;
                        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(NT_SUCCESS(err)==NT_SUCCESS(dir_IoStatusBlock.Status));
        g_return_if_fail(dir_IoStatusBlock.Information==FILE_OPENED);
 
        Status=ObReferenceObjectByHandle(dir_Handle,FILE_LIST_DIRECTORY,IoFileObjectType,UserMode,(PVOID *)&FileObject,NULL);
@@ -453,7 +465,8 @@ WCHAR wzero;
                        KeWaitForSingleObject(&FileObject->Event,Executive,KernelMode,FALSE,NULL);
                        Status=IoStatusBlock.Status;
                        }
-               g_assert(NT_SUCCESS(Status));
+               g_assert(NT_SUCCESS(Status)
+                               || (Status==STATUS_MEDIA_WRITE_PROTECTED && captive_options->rwmode==CAPTIVE_OPTION_RWMODE_RO));
        }
 
        ObDereferenceObject(FileObject);
@@ -530,21 +543,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;