#include "config.h"
-#include "captive/client.h" /* self */
#include "captive/ldr.h"
#include "captive/ldr_exports.h"
#include "captive/unicode.h"
#include <popt.h>
#include <glib/gstrfuncs.h>
#include <glib/glist.h>
-#include <glib/gutils.h> /* for g_atexit() */
+#include "giochannel-blind.h"
+#include <glib-object.h>
+#include "reactos/internal/se.h" /* for SeInit2() */
+#include "captive/leave.h"
+#include "captive/options.h"
+struct captive_options *captive_options;
+
/* Are we initialized? */
static gboolean active;
static PMODULE_OBJECT ModuleObject;
/* Driver in fs module loaded by captive_w32_init() */
-static DRIVER_OBJECT DriverObject;
+DRIVER_OBJECT captive_DriverObject;
+PDRIVER_REINITIALIZE captive_DriverObject_ReinitRoutine;
+PVOID captive_DriverObject_ReinitRoutine_Context;
/* Structure holding the pointer to the toplevel IRP */
static TOP_LEVEL_IRP TopLevelIrp; /* TODO:thread */
-gchar *captive_option_filesystem;
-enum captive_option_rwmode captive_option_rwmode=CAPTIVE_OPTION_RWMODE_BLIND;
-enum captive_option_media captive_option_media=CAPTIVE_OPTION_MEDIA_DISK;
-GIOChannel *captive_image_iochannel;
-guint64 captive_image_size;
-static GList *captive_load_module;
-
-
-static gchar *captive_popt_optarg;
-
-
-static void arg_filesystem(void)
-{
- g_free(captive_option_filesystem);
- captive_option_filesystem=g_strdup(captive_popt_optarg);
-}
-
-static void arg_load_module(void)
-{
- captive_load_module=g_list_append(captive_load_module,g_strdup(captive_popt_optarg));
-}
-
-static void arg_ro(void)
-{
- captive_option_rwmode=CAPTIVE_OPTION_RWMODE_RO;
-}
-static void arg_blind(void)
-{
- captive_option_rwmode=CAPTIVE_OPTION_RWMODE_BLIND;
-}
-static void arg_rw(void)
-{
- captive_option_rwmode=CAPTIVE_OPTION_RWMODE_RW;
-}
-
-static void arg_cdrom(void)
-{
- captive_option_media=CAPTIVE_OPTION_MEDIA_CDROM;
-}
-static void arg_disk(void)
-{
- captive_option_media=CAPTIVE_OPTION_MEDIA_DISK;
-}
+void *_local_unwind2_addr;
-static void captive_popt_callback
- (poptContext con,enum poptCallbackReason reason,const struct poptOption *opt,const char *arg,const void *data);
-
-const struct poptOption captive_popt[]={
- { argInfo:POPT_ARG_INTL_DOMAIN, arg:(void *)PACKAGE },
- { argInfo:POPT_ARG_CALLBACK, arg:(void *)captive_popt_callback },
-#define POPT_OFFSET 2
-#define CAPTIVE_POPT(longname,argInfoP,argP,descripP,argDescripP) \
- { \
- longName: (longname), \
- shortName: 0, \
- argInfo: (argInfoP), \
- arg: (void *)argP, \
- val: 0, \
- descrip: (descripP), \
- argDescrip: (argDescripP), \
- }
-#define CAPTIVE_POPT_STRING(longname,descripP,argDescripP) \
- CAPTIVE_POPT(longname,POPT_ARG_STRING,&captive_popt_optarg,descripP,argDescripP)
-#define CAPTIVE_POPT_NONE(longname,descripP) \
- CAPTIVE_POPT(longname,POPT_ARG_NONE ,NULL ,descripP,NULL )
-
- CAPTIVE_POPT_STRING("filesystem" ,N_("Path to .sys or .so filesystem module file"),N_("pathname")),
- CAPTIVE_POPT_STRING("load-module",N_("Path to any W32 module to load w/o initialization"),N_("pathname")),
- CAPTIVE_POPT_NONE( "ro" ,N_("Read/write mode: Any write access will be forbidden")),
- CAPTIVE_POPT_NONE( "blind" ,N_("Read/write mode: All writes are just simulated in memory (default)")),
- CAPTIVE_POPT_NONE( "rw" ,N_("Read/write mode: Write directly to the image file/device")),
- CAPTIVE_POPT_NONE( "cdrom" ,N_("Media type: CD-ROM")),
- CAPTIVE_POPT_NONE( "disk" ,N_("Media type: Disk (default)")),
-
-#undef CAPTIVE_POPT_NONE
-#undef CAPTIVE_POPT_STRING
-#undef CAPTIVE_POPT
- POPT_TABLEEND
- };
-
-static const struct poptOption captive_popt_standalone[]={
- CAPTIVE_POPT_INCLUDE,
- POPT_AUTOHELP
- POPT_TABLEEND
- };
-
-
-static void (*const popt_func_table[])(void)={
- arg_filesystem,
- arg_load_module,
- arg_ro,
- arg_blind,
- arg_rw,
- arg_cdrom,
- arg_disk,
- };
-
-
-/* poptCallbackType captive_popt_callback */
-static void captive_popt_callback
- (poptContext con,enum poptCallbackReason reason,const struct poptOption *opt,const char *arg,const void *data)
+/* Acceleration hack for ntoskrnl/dbg/print.c/DbgPrint() */
+gboolean captive_get_debug_messages(void)
{
-gint funci;
+ g_return_val_if_fail(captive_options!=NULL,TRUE);
- g_return_if_fail(reason==POPT_CALLBACK_REASON_OPTION);
-
- funci=(opt-(captive_popt+POPT_OFFSET));
- g_return_if_fail(funci>=0);
- g_return_if_fail(funci<(gint)G_N_ELEMENTS(popt_func_table));
- if (popt_func_table[funci])
- (*popt_func_table[funci])();
- free(captive_popt_optarg);
- captive_popt_optarg=NULL; /* sanity, shouldn't be needed */
+ return captive_options->debug_messages;
}
gboolean errbool;
GIOStatus erriostatus;
- g_return_val_if_fail(captive_option_filesystem!=NULL,FALSE);
+ g_return_val_if_fail(captive_options!=NULL,FALSE);
+ g_return_val_if_fail(captive_options->filesystem!=NULL,FALSE);
erriostatus=g_io_channel_set_encoding(captive_image_iochannel,
NULL, /* encoding; force binary data */
captive_image_size=captive_giochannel_size(captive_image_iochannel);
g_return_val_if_fail(captive_image_size>0,FALSE);
- /* Initialize 'FsRtlLegalAnsiCharacterArray'. */
- captive_FsRtlLegalAnsiCharacterArray_init();
-
/* Part of reactos/ntoskrnl/ke/main.c/KiSystemStartup() begins. */
/* ExpInitializeExecutive(); */
/* Part of reactos/ntoskrnl/ke/main.c/ExpInitializeExecutive() begins
/* Part of reactos/ntoskrnl/ldr/loader.c/LdrInit1() ends. */
KeLowerIrql(DISPATCH_LEVEL);
/*...*/
- KeLowerIrql(PASSIVE_LEVEL);
- /*...*/
/* create default nls tables */
RtlpInitNlsTables();
/*...*/
+ /* KeInit2() */
+ /*...*/
+ KeInitializeDispatcher();
+ /*...*/
+ KeLowerIrql(PASSIVE_LEVEL);
+ errbool=SeInit1();
+ g_assert(errbool==TRUE);
ObInit();
- /*...*/
+ errbool=SeInit2();
+ g_assert(errbool==TRUE);
/* PiInitProcessManager(); */
/* Part of reactos/ntoskrnl/ps/psmgr.c/PiInitProcessManager() begins. */
PsInitProcessManagment();
InitializeListHead(&ModuleListHead);
KeInitializeSpinLock(&ModuleListLock);
/* Part of reactos/ntoskrnl/ldr/loader.c/LdrInitModuleManagement ends. */
+ /*...*/
+ /* Ntinit(); */
+ NtInitializeEventImplementation();
+ /*...*/
/* Part of reactos/ntoskrnl/ke/main.c/ExpInitializeExecutive() ends. */
/* Part of reactos/ntoskrnl/ke/main.c/KiSystemStartup() ends. */
errbool=captive_disk_init();
g_return_val_if_fail(errbool==TRUE,FALSE);
- while (captive_load_module) {
-gchar *modulename=captive_load_module->data;
+ while (captive_options->load_module) {
+gchar *modulename=captive_options->load_module->data;
PMODULE_OBJECT ModuleObject_tmp;
NTSTATUS err;
&ModuleObject_tmp); /* ModuleObjectp */
g_return_val_if_fail(NT_SUCCESS(err),FALSE);
- captive_load_module=g_list_remove(captive_load_module,modulename);
+ captive_options->load_module=g_list_remove(captive_options->load_module,modulename);
}
- /* Patch 'ntoskrnl.exe' loaded by 'captive_load_module' above. */
+ /* Patch 'ntoskrnl.exe' loaded by 'captive_options->load_module' above. */
+ {
+ CHAR *KeNumberProcessorsp=captive_Module_GetExportAddress("ntoskrnl.exe","KeNumberProcessors");
+
+ g_assert(*KeNumberProcessorsp==0);
+ *KeNumberProcessorsp=KeNumberProcessors;
+ g_assert(*KeNumberProcessorsp==1);
+ }
+ /* Apply captive_kernel_patches() AFTER any symbols sanity checks above! */
captive_kernel_patches();
+ _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_FsRtlLegalAnsiCharacterArray_init();
+
/* set TopLevelIrp() - FIXME: where is it set by native reactos? */
PsGetCurrentThread()->TopLevelIrp=&TopLevelIrp; /* otherwise Io{Get,Set}TopLevelIrp() would SIGSEGV */
/* You must have already captive_signal_init() passed here as the module may
* call some functions from W32 ntoskrnl.exe.
*/
+ captive_DriverObject_ReinitRoutine=NULL;
err=captive_LdrpLoadAndCallImage(
&ModuleObject, /* ModuleObjectp */
- captive_utf8_to_UnicodeString_alloca(captive_option_filesystem), /* ModuleName */
- &DriverObject, /* DriverEntry_DriverObject */
+ captive_utf8_to_UnicodeString_alloca(captive_options->filesystem), /* ModuleName */
+ &captive_DriverObject, /* DriverEntry_DriverObject */
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_DriverObject, /* DriverObject */
+ captive_DriverObject_ReinitRoutine_Context, /* Context */
+ 1); /* Count: # of calls of ReinitRoutine incl. the current one */
+ }
return TRUE;
}
-static void captive_shutdown_atexit(void);
+static void log_discard_func(const gchar *log_domain,GLogLevelFlags log_level,const gchar *message,gpointer user_data)
+{
+ /* NOP */
+}
/**
* captive_init:
- * @captive_args: String with possible options to parse by popt.
- * %NULL value is permitted.
- * @image_iochannel: Host OS file of the disk image to mount.
- * %NULL value is permitted (initialization would not apply in such case).
*
- * Initializes %libcaptive and loads the specified filesystem.
- * You can supply %NULL value for @image_iochannel - in such case no library
- * initialization is done; only passed @captive_args are parsed. Function
- * will return you %FALSE value as it is not yet initializied.
+ * Expects #captive_options: Parsed by captive_options_parse().
+ * %NULL value is forbidden. Field #image_iochannel %NULL value is forbidden.
*
- * You should supply only @captive_args with %NULL @image_iochannel if you
- * need to parse+examine the arguments to properly initialize @image_iochannel.
+ * Initializes %libcaptive and loads the specified filesystem.
*
* Returns: %TRUE if successfuly initialized.
*/
-gboolean captive_init(const gchar *captive_args,GIOChannel *image_iochannel)
+gboolean captive_init(void)
{
gboolean errbool;
-int errint;
#ifdef MAINTAINER_MODE
g_log_set_always_fatal(~(0
g_return_val_if_fail(active==FALSE,FALSE);
- /* (optionally) parse the given 'captive_args' string */
- if (captive_args) {
-int captive_args_argc;
-const char **captive_args_argv=NULL;
-poptContext context;
-gboolean r=FALSE;
-
- errint=poptParseArgvString(captive_args,&captive_args_argc,&captive_args_argv);
- if (errint!=0) {
- g_assert_not_reached(); /* argument parsing args_error */
- goto args_err;
- }
- context=poptGetContext(
- PACKAGE, /* name */
- captive_args_argc,captive_args_argv, /* argc,argv */
- captive_popt_standalone, /* options */
- POPT_CONTEXT_KEEP_FIRST);
- if (context==NULL) {
- g_assert_not_reached(); /* argument recognization args_error */
- goto args_err_argv;
- }
- errint=poptReadDefaultConfig(context,
- TRUE); /* useEnv */
- if (errint!=0) {
- g_assert_not_reached(); /* argument recognization args_error */
- goto args_err_context;
- }
- errint=poptGetNextOpt(context);
- if (errint!=-1) {
- g_assert_not_reached(); /* some non-callbacked argument reached */
- goto args_err_context;
- }
- /* FIXME: reject non-"--"-prefixed arguments; how to detected them? */
- r=TRUE; /* success */
-args_err_context:
- poptFreeContext(context);
-args_err_argv:
- free(captive_args_argv); /* may be NULL here */
-args_err:
- if (!r) {
- puts("FIXME: HELP HERE");
- g_return_val_if_reached(r);
- }
+ 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();
+
+ if (!captive_options->debug_messages) {
+ g_log_set_handler(
+ G_LOG_DOMAIN, /* log_domain; "Captive" */
+ 0 /* log_levels */
+ | G_LOG_FLAG_RECURSION
+ | G_LOG_FLAG_FATAL
+ /* The same mask is in libcaptive/sandbox/server-GlibLogFunc.c ! */
+ | G_LOG_LEVEL_MESSAGE
+ | G_LOG_LEVEL_INFO
+ | G_LOG_LEVEL_DEBUG,
+ log_discard_func, /* log_func */
+ NULL); /* user_data */
}
- /* If we were just requested to parse the arguments. */
- if (!image_iochannel)
- return FALSE;
-
- g_return_val_if_fail(image_iochannel!=NULL,FALSE);
+ if (captive_options->rwmode==CAPTIVE_OPTION_RWMODE_BLIND)
+ captive_image_iochannel=(GIOChannel *)captive_giochannel_blind_new(captive_options->image_iochannel);
+ else
+ captive_image_iochannel=captive_options->image_iochannel;
- captive_image_iochannel=image_iochannel;
/* Do not initialize 'captive_image_size' by captive_giochannel_size() here
* as we yet need to do g_io_channel_set_encoding().
*/
errbool=captive_w32_init();
g_return_val_if_fail(errbool==TRUE,FALSE);
- g_atexit(captive_shutdown_atexit);
-
active=TRUE;
return TRUE;
}
+BOOLEAN captive_cc_FileObject_delete(FILE_OBJECT *FileObject);
+void captive_cc_flush(void);
+
/**
* captive_shutdown:
*
* Closes down %libcaptive. It should flush all pending buffers and successfuly
- * close the filesystem. Variable #captive_image_iochannel will be set to %NULL,
+ * close the filesystem. Variable #captive_options->image_iochannel will not be set to %NULL,
* you should close such channel yourself.
*
* Returns: %TRUE if successfuly shutdown.
*/
gboolean captive_shutdown(void)
{
+GIOStatus erriostatus;
+
g_return_val_if_fail(active==TRUE,FALSE);
g_return_val_if_fail(captive_image_iochannel!=NULL,FALSE);
+ g_return_val_if_fail(captive_options->image_iochannel!=NULL,FALSE);
+
+ /* 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().
+ */
+ 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().
+ */
+ captive_cc_FileObject_delete(
+ NULL); /* FileObject */
+
IoShutdownRegisteredDevices();
+ /* libcaptive is not authorized to shutdown 'captive_image_channel'. */
+ 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);
+ }
+
captive_image_iochannel=NULL;
active=FALSE;
return TRUE;
}
-
-
-static void captive_shutdown_atexit(void)
-{
- if (active)
- captive_shutdown();
-}