2 * Init and cleanup code of libcaptive to be called by client application
3 * Copyright (C) 2002 Jan Kratochvil <project-captive@jankratochvil.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; exactly version 2 of June 1991 is required
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "captive/ldr.h"
23 #include "captive/ldr_exports.h"
24 #include "captive/unicode.h"
25 #include "captive/rtl-file.h"
26 #include <glib/gtypes.h>
27 #include <glib/gmessages.h>
28 #include "reactos/internal/ldr.h"
29 #include "reactos/napi/types.h"
30 #include "reactos/internal/kd.h" /* for KDB_LOADDRIVER_HOOK */
32 #include <sys/mman.h> /* for PROT_READ, MAP_SHARED */
33 #include "reactos/ddk/kefuncs.h" /* for KeInitializeSpinLock() */
34 #include "reactos/internal/ntoskrnl.h" /* for RtlpInitNlsTables() and IoInit() */
35 #include "reactos/internal/ps.h" /* for PsInitProcessManagment() and PsInitThreadManagment() */
36 #include "reactos/ddk/iofuncs.h" /* for IoCreateFile() */
37 #include "captive/storage.h"
38 #include "captive/signal.h" /* for captive_signal_init() */
39 #include "reactos/ddk/psfuncs.h" /* for PsGetCurrentThread() */
42 #include <glib/gstrfuncs.h>
43 #include <glib/glist.h>
44 #include "giochannel-blind.h"
45 #include <glib-object.h>
46 #include "reactos/internal/se.h" /* for SeInit2() */
47 #include "captive/leave.h"
48 #include "captive/options.h"
51 struct captive_options *captive_options;
53 /* Are we initialized? */
54 static gboolean active;
56 /* Module of fs module itself loaded by captive_w32_init() */
57 static PMODULE_OBJECT ModuleObject;
59 /* Driver in fs module loaded by captive_w32_init() */
60 DRIVER_OBJECT captive_DriverObject;
61 PDRIVER_REINITIALIZE captive_DriverObject_ReinitRoutine;
62 PVOID captive_DriverObject_ReinitRoutine_Context;
64 /* Structure holding the pointer to the toplevel IRP */
65 static TOP_LEVEL_IRP TopLevelIrp; /* TODO:thread */
68 void *_local_unwind2_addr;
71 /* Acceleration hack for ntoskrnl/dbg/print.c/DbgPrint() */
72 gboolean captive_get_debug_messages(void)
74 g_return_val_if_fail(captive_options!=NULL,TRUE);
76 return captive_options->debug_messages;
80 static gboolean captive_w32_init(void)
84 GIOStatus erriostatus;
86 g_return_val_if_fail(captive_options!=NULL,FALSE);
87 g_return_val_if_fail(captive_options->filesystem.type!=CAPTIVE_OPTIONS_MODULE_TYPE_EMPTY,FALSE);
89 erriostatus=g_io_channel_set_encoding(captive_image_iochannel,
90 NULL, /* encoding; force binary data */
92 g_assert(erriostatus==G_IO_STATUS_NORMAL);
94 /* captive_giochannel_size() only _after_ g_io_channel_set_encoding() ! */
95 captive_image_size=captive_giochannel_size(captive_image_iochannel);
96 g_return_val_if_fail(captive_image_size>0,FALSE);
98 /* Part of reactos/ntoskrnl/ke/main.c/KiSystemStartup() begins. */
99 /* ExpInitializeExecutive(); */
100 /* Part of reactos/ntoskrnl/ke/main.c/ExpInitializeExecutive() begins
101 * here as the rest of the function does a lot of hardware initializations.
104 /* Part of reactos/ntoskrnl/ldr/loader.c/LdrInit1() begins. */
105 InitializeListHead(&ModuleTextListHead);
106 /* Part of reactos/ntoskrnl/ldr/loader.c/LdrInit1() ends. */
107 KeLowerIrql(DISPATCH_LEVEL);
109 /* create default nls tables */
114 KeInitializeDispatcher();
116 KeLowerIrql(PASSIVE_LEVEL);
118 g_assert(errbool==TRUE);
121 g_assert(errbool==TRUE);
122 /* PiInitProcessManager(); */
123 /* Part of reactos/ntoskrnl/ps/psmgr.c/PiInitProcessManager() begins. */
124 PsInitProcessManagment();
125 PsInitThreadManagment();
126 /* Part of reactos/ntoskrnl/ps/psmgr.c/PiInitProcessManager() ends. */
130 /* LdrInitModuleManagement(); */
131 /* Part of reactos/ntoskrnl/ldr/loader.c/LdrInitModuleManagement() begins
132 * here as the rest "Create module object for {NTOSKRNL,HAL}"
133 * is dependent on {NTOSKRNL,HAL} PE image headers not provided by libcaptive.
135 /* Initialize the module list and spinlock */
136 InitializeListHead(&ModuleListHead);
137 KeInitializeSpinLock(&ModuleListLock);
138 /* Part of reactos/ntoskrnl/ldr/loader.c/LdrInitModuleManagement ends. */
141 NtInitializeEventImplementation();
143 /* Part of reactos/ntoskrnl/ke/main.c/ExpInitializeExecutive() ends. */
144 /* Part of reactos/ntoskrnl/ke/main.c/KiSystemStartup() ends. */
146 /* Simulate our PE headers and export the symbols of our complete libraries */
147 captive_kernel_exports();
149 errbool=captive_cdrom_init();
150 g_return_val_if_fail(errbool==TRUE,FALSE);
151 errbool=captive_disk_init();
152 g_return_val_if_fail(errbool==TRUE,FALSE);
154 while (captive_options->load_module) {
155 PMODULE_OBJECT ModuleObject_tmp;
158 /* load the module */
159 err=captive_LdrLoadModule(
160 captive_options->load_module->data,
161 &ModuleObject_tmp); /* ModuleObjectp */
162 g_return_val_if_fail(NT_SUCCESS(err),FALSE);
164 captive_options_module_free(captive_options->load_module->data);
165 /* also frees 'options->load_module->data' */
166 captive_options->load_module=g_list_delete_link(captive_options->load_module,captive_options->load_module);
169 /* Patch 'ntoskrnl.exe' loaded by 'captive_options->load_module' above. */
171 CHAR *KeNumberProcessorsp=captive_Module_GetExportAddress("ntoskrnl.exe","KeNumberProcessors");
173 g_assert(*KeNumberProcessorsp==0);
174 *KeNumberProcessorsp=KeNumberProcessors;
175 g_assert(*KeNumberProcessorsp==1);
177 /* Apply captive_kernel_patches() AFTER any symbols sanity checks above! */
178 captive_kernel_patches();
180 _local_unwind2_addr=captive_Module_GetExportAddress("ntoskrnl.exe","_local_unwind2");
182 /* Initialize 'FsRtlLegalAnsiCharacterArray'.
183 * It requires 'ntoskrnl.exe' loaded by 'captive_options->load_module' above;
184 * captive_kernel_patches() should not be needed.
186 captive_FsRtlLegalAnsiCharacterArray_init();
188 /* set TopLevelIrp() - FIXME: where is it set by native reactos? */
189 PsGetCurrentThread()->TopLevelIrp=&TopLevelIrp; /* otherwise Io{Get,Set}TopLevelIrp() would SIGSEGV */
191 /* Begin possible handling of foreign W32 binary code here */
192 /* If you want to disable SIGSEGV handler if not needed:
193 * if (ModuleObject->Flags & MODULE_FLAG_PE)
195 captive_signal_init();
197 /* You must have already captive_signal_init() passed here as the module may
198 * call some functions from W32 ntoskrnl.exe.
200 captive_DriverObject_ReinitRoutine=NULL;
201 err=captive_LdrpLoadAndCallImage(
202 &ModuleObject, /* ModuleObjectp */
203 &captive_options->filesystem, /* options_module */
204 &captive_DriverObject, /* DriverEntry_DriverObject */
205 captive_utf8_to_UnicodeString_alloca("\\captive\\filesystem")); /* DriverEntry_RegistryPath */
206 g_return_val_if_fail(NT_SUCCESS(err),FALSE);
207 if (captive_DriverObject_ReinitRoutine) {
208 (*captive_DriverObject_ReinitRoutine)(
209 &captive_DriverObject, /* DriverObject */
210 captive_DriverObject_ReinitRoutine_Context, /* Context */
211 1); /* Count: # of calls of ReinitRoutine incl. the current one */
218 static void log_discard_func(const gchar *log_domain,GLogLevelFlags log_level,const gchar *message,gpointer user_data)
227 * Expects #captive_options: Parsed by captive_options_parse().
228 * %NULL value is forbidden. Field #image_iochannel %NULL value is forbidden.
230 * Initializes %libcaptive and loads the specified filesystem.
232 * Returns: %TRUE if successfuly initialized.
234 gboolean captive_init(void)
238 #ifdef MAINTAINER_MODE
239 g_log_set_always_fatal(~(0
246 g_return_val_if_fail(active==FALSE,FALSE);
248 g_return_val_if_fail(captive_options!=NULL,FALSE);
249 g_return_val_if_fail(captive_options->image_iochannel!=NULL,FALSE);
251 /* Initialize GObject subsystem of GLib. */
254 if (!captive_options->debug_messages) {
256 G_LOG_DOMAIN, /* log_domain; "Captive" */
258 | G_LOG_FLAG_RECURSION
260 /* The same mask is in libcaptive/sandbox/server-GlibLogFunc.c ! */
261 | G_LOG_LEVEL_MESSAGE
264 log_discard_func, /* log_func */
265 NULL); /* user_data */
268 if (captive_options->rwmode==CAPTIVE_OPTION_RWMODE_BLIND)
269 captive_image_iochannel=(GIOChannel *)captive_giochannel_blind_new(captive_options->image_iochannel);
271 captive_image_iochannel=captive_options->image_iochannel;
273 /* Do not initialize 'captive_image_size' by captive_giochannel_size() here
274 * as we yet need to do g_io_channel_set_encoding().
277 errbool=captive_w32_init();
278 g_return_val_if_fail(errbool==TRUE,FALSE);
285 BOOLEAN captive_cc_FileObject_delete(FILE_OBJECT *FileObject);
286 void captive_cc_flush(void);
291 * Closes down %libcaptive. It should flush all pending buffers and successfuly
292 * close the filesystem. Variable #captive_options->image_iochannel will not be set to %NULL,
293 * you should close such channel yourself.
295 * Returns: %TRUE if successfuly shutdown.
297 gboolean captive_shutdown(void)
299 GIOStatus erriostatus;
301 g_return_val_if_fail(active==TRUE,FALSE);
302 g_return_val_if_fail(captive_image_iochannel!=NULL,FALSE);
303 g_return_val_if_fail(captive_options->image_iochannel!=NULL,FALSE);
305 /* Invoke all pending idle functions just to not to forget for anything... */
306 while (g_main_context_iteration(
307 NULL, /* context; NULL means default one */
308 FALSE)) /* may_block */
309 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: g_main_context_iteration() proceeded",G_STRLOC);
311 captive_PoQueueShutdownWorkItem_hooklist_invoke();
314 /* During IoShutdownRegisteredFileSystems() - IRP_MJ_SHUTDOWN to be specific
315 * some buffers will be written but after the IofCallDriver() it will be
316 * no longer possible to flush such buffers to their DeviceVolumeFile.
317 * Therefore we must flush such buffers on the fly although such behaviour
318 * would crash us in regular case as filesystems access BCBs even after their
321 captive_cc_unmounting=TRUE;
323 /* FIXME: ntoskrnl/ex/power.c/NtShutdownSystem() does
324 * IoShutdownRegistered{Devices,FileSystems} order; is it correct?
326 IoShutdownRegisteredFileSystems();
328 /* Just a sanity check as all the dirty data should
329 * get already flushed during IoShutdownRegisteredFileSystems().
331 captive_cc_FileObject_delete(
332 NULL); /* FileObject */
334 IoShutdownRegisteredDevices();
336 /* libcaptive is not authorized to shutdown 'captive_image_channel'. */
337 erriostatus=g_io_channel_flush(
338 captive_image_iochannel, /* channel */
340 g_assert(erriostatus==G_IO_STATUS_NORMAL);
342 /* 'captive_image_iochannel' may be blinded wrapper of 'captive_options->image_iochannel'. */
343 if (captive_image_iochannel!=captive_options->image_iochannel) {
344 erriostatus=g_io_channel_flush(
345 captive_options->image_iochannel, /* channel */
347 g_assert(erriostatus==G_IO_STATUS_NORMAL);
348 g_io_channel_unref(captive_image_iochannel);
351 captive_image_iochannel=NULL;