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/client.h" /* self */
23 #include "captive/ldr.h"
24 #include "captive/ldr_exports.h"
25 #include "captive/unicode.h"
26 #include "captive/rtl-file.h"
27 #include <glib/gtypes.h>
28 #include <glib/gmessages.h>
29 #include "reactos/internal/ldr.h"
30 #include "reactos/napi/types.h"
31 #include "reactos/internal/kd.h" /* for KDB_LOADDRIVER_HOOK */
33 #include <sys/mman.h> /* for PROT_READ, MAP_SHARED */
34 #include "reactos/ddk/kefuncs.h" /* for KeInitializeSpinLock() */
35 #include "reactos/internal/ntoskrnl.h" /* for RtlpInitNlsTables() and IoInit() */
36 #include "reactos/internal/ps.h" /* for PsInitProcessManagment() and PsInitThreadManagment() */
37 #include "reactos/ddk/iofuncs.h" /* for IoCreateFile() */
38 #include "captive/storage.h"
39 #include "captive/signal.h" /* for captive_signal_init() */
40 #include "reactos/ddk/psfuncs.h" /* for PsGetCurrentThread() */
42 #include "reactos/internal/ex.h" /* for ExpInitLookasideLists() */
44 #include <glib/gstrfuncs.h>
47 /* Are we initialized? */
48 static gboolean active;
50 /* Module of fs module itself loaded by captive_w32_init() */
51 static PMODULE_OBJECT ModuleObject;
53 /* Driver in fs module loaded by captive_w32_init() */
54 static DRIVER_OBJECT DriverObject;
56 /* Structure holding the pointer to the toplevel IRP */
57 static TOP_LEVEL_IRP TopLevelIrp; /* TODO:thread */
60 gchar *captive_option_filesystem;
61 enum captive_option_rwmode captive_option_rwmode=CAPTIVE_OPTION_RWMODE_BLIND;
62 enum captive_option_media captive_option_media=CAPTIVE_OPTION_MEDIA_DISK;
63 GIOChannel *captive_image_iochannel;
64 guint64 captive_image_size;
67 static gchar *captive_popt_optarg;
70 static void arg_filesystem(void)
72 g_free(captive_option_filesystem);
73 captive_option_filesystem=g_strdup(captive_popt_optarg);
76 static void arg_ro(void)
78 captive_option_rwmode=CAPTIVE_OPTION_RWMODE_RO;
80 static void arg_blind(void)
82 captive_option_rwmode=CAPTIVE_OPTION_RWMODE_BLIND;
84 static void arg_rw(void)
86 captive_option_rwmode=CAPTIVE_OPTION_RWMODE_RW;
89 static void arg_cdrom(void)
91 captive_option_media=CAPTIVE_OPTION_MEDIA_CDROM;
93 static void arg_disk(void)
95 captive_option_media=CAPTIVE_OPTION_MEDIA_DISK;
99 static void captive_popt_callback
100 (poptContext con,enum poptCallbackReason reason,const struct poptOption *opt,const char *arg,const void *data);
102 const struct poptOption captive_popt[]={
103 { argInfo:POPT_ARG_INTL_DOMAIN, arg:(void *)PACKAGE },
104 { argInfo:POPT_ARG_CALLBACK, arg:(void *)captive_popt_callback },
105 #define POPT_OFFSET 2
106 #define CAPTIVE_POPT(longname,argInfoP,argP,descripP,argDescripP) \
108 longName: (longname), \
110 argInfo: (argInfoP), \
113 descrip: (descripP), \
114 argDescrip: (argDescripP), \
116 #define CAPTIVE_POPT_STRING(longname,descripP,argDescripP) \
117 CAPTIVE_POPT(longname,POPT_ARG_STRING,&captive_popt_optarg,descripP,argDescripP)
118 #define CAPTIVE_POPT_NONE(longname,descripP) \
119 CAPTIVE_POPT(longname,POPT_ARG_NONE ,NULL ,descripP,NULL )
121 CAPTIVE_POPT_STRING("filesystem",N_("Path to .sys or .so filesystem module file"),N_("pathname")),
122 CAPTIVE_POPT_NONE( "ro" ,N_("Read/write mode: Any write access will be forbidden")),
123 CAPTIVE_POPT_NONE( "blind" ,N_("Read/write mode: All writes are just simulated in memory (default)")),
124 CAPTIVE_POPT_NONE( "rw" ,N_("Read/write mode: Write directly to the image file/device")),
125 CAPTIVE_POPT_NONE( "cdrom" ,N_("Media type: CD-ROM")),
126 CAPTIVE_POPT_NONE( "disk" ,N_("Media type: Disk (default)")),
128 #undef CAPTIVE_POPT_NONE
129 #undef CAPTIVE_POPT_STRING
134 static const struct poptOption captive_popt_standalone[]={
135 CAPTIVE_POPT_INCLUDE,
141 static void (*const popt_func_table[])(void)={
151 /* poptCallbackType captive_popt_callback */
152 static void captive_popt_callback
153 (poptContext con,enum poptCallbackReason reason,const struct poptOption *opt,const char *arg,const void *data)
157 g_return_if_fail(reason==POPT_CALLBACK_REASON_OPTION);
159 funci=(opt-(captive_popt+POPT_OFFSET));
160 g_return_if_fail(funci>=0);
161 g_return_if_fail(funci<(gint)G_N_ELEMENTS(popt_func_table));
162 if (popt_func_table[funci])
163 (*popt_func_table[funci])();
164 free(captive_popt_optarg);
165 captive_popt_optarg=NULL; /* sanity, shouldn't be needed */
169 static gboolean captive_w32_init(void)
173 GIOStatus erriostatus;
175 g_return_val_if_fail(captive_option_filesystem!=NULL,FALSE);
177 erriostatus=g_io_channel_set_encoding(captive_image_iochannel,
178 NULL, /* encoding; force binary data */
180 g_assert(erriostatus==G_IO_STATUS_NORMAL);
182 /* captive_giochannel_size() only _after_ g_io_channel_set_encoding() ! */
183 captive_image_size=captive_giochannel_size(captive_image_iochannel);
184 g_return_val_if_fail(captive_image_size>0,FALSE);
186 /* Initialize 'FsRtlLegalAnsiCharacterArray'. */
187 captive_FsRtlLegalAnsiCharacterArray_init();
189 /* Part of reactos/ntoskrnl/ke/main.c/KiSystemStartup() begins. */
190 /* ExpInitializeExecutive(); */
191 /* Part of reactos/ntoskrnl/ke/main.c/ExpInitializeExecutive() begins
192 * here as the rest of the function does a lot of hardware initializations.
195 /* Part of reactos/ntoskrnl/ldr/loader.c/LdrInit1() begins. */
196 InitializeListHead(&ModuleTextListHead);
197 /* Part of reactos/ntoskrnl/ldr/loader.c/LdrInit1() ends. */
198 KeLowerIrql(DISPATCH_LEVEL);
200 KeLowerIrql(PASSIVE_LEVEL);
202 /* create default nls tables */
207 /* PiInitProcessManager(); */
208 /* Part of reactos/ntoskrnl/ps/psmgr.c/PiInitProcessManager() begins. */
209 PsInitProcessManagment();
210 PsInitThreadManagment();
211 /* Part of reactos/ntoskrnl/ps/psmgr.c/PiInitProcessManager() ends. */
215 /* Part of reactos/ntoskrnl/ex/init.c/Exinit() begins. */
216 ExpInitLookasideLists();
217 /* Part of reactos/ntoskrnl/ex/init.c/Exinit() ends. */
219 /* LdrInitModuleManagement(); */
220 /* Part of reactos/ntoskrnl/ldr/loader.c/LdrInitModuleManagement() begins
221 * here as the rest "Create module object for {NTOSKRNL,HAL}"
222 * is dependent on {NTOSKRNL,HAL} PE image headers not provided by libcaptive.
224 /* Initialize the module list and spinlock */
225 InitializeListHead(&ModuleListHead);
226 KeInitializeSpinLock(&ModuleListLock);
227 /* Part of reactos/ntoskrnl/ldr/loader.c/LdrInitModuleManagement ends. */
228 /* Part of reactos/ntoskrnl/ke/main.c/ExpInitializeExecutive() ends. */
229 /* Part of reactos/ntoskrnl/ke/main.c/KiSystemStartup() ends. */
231 /* Simulate our PE headers and export the symbols of {NTOSKRNL,HAL} */
232 captive_kernel_exports();
234 errbool=captive_cdrom_init();
235 g_return_val_if_fail(errbool==TRUE,FALSE);
236 errbool=captive_disk_init();
237 g_return_val_if_fail(errbool==TRUE,FALSE);
239 err=captive_LdrpLoadAndCallImage(
240 &ModuleObject, /* ModuleObjectp */
241 captive_utf8_to_UnicodeString_alloca(captive_option_filesystem), /* ModuleName */
242 &DriverObject, /* DriverEntry_DriverObject */
243 captive_utf8_to_UnicodeString_alloca("\\captive\\filesystem")); /* DriverEntry_RegistryPath */
244 g_return_val_if_fail(NT_SUCCESS(err),FALSE);
246 /* set TopLevelIrp() - FIXME: where is it set by native reactos? */
247 PsGetCurrentThread()->TopLevelIrp=&TopLevelIrp; /* otherwise Io{Get,Set}TopLevelIrp() would SIGSEGV */
249 /* Begin possible handling of foreign W32 binary code here */
250 /* If you want to disable SIGSEGV handler if not needed:
251 * if (ModuleObject->Flags & MODULE_FLAG_PE)
253 captive_signal_init();
261 * @captive_args: String with possible options to parse by popt.
262 * %NULL value is permitted.
263 * @image_iochannel: Host OS file of the disk image to mount.
264 * %NULL value is forbidden.
266 * Initializes %libcaptive and loads the specified filesystem.
270 * Returns: %TRUE if successfuly loaded.
272 gboolean captive_init(const gchar *captive_args,GIOChannel *image_iochannel)
277 #ifdef MAINTAINER_MODE
278 g_log_set_always_fatal(~(0
285 g_return_val_if_fail(active==FALSE,FALSE);
287 /* (optionally) parse the given 'captive_args' string */
289 int captive_args_argc;
290 const char **captive_args_argv=NULL;
294 errint=poptParseArgvString(captive_args,&captive_args_argc,&captive_args_argv);
296 g_assert_not_reached(); /* argument parsing args_error */
299 context=poptGetContext(
301 captive_args_argc,captive_args_argv, /* argc,argv */
302 captive_popt_standalone, /* options */
303 POPT_CONTEXT_KEEP_FIRST);
305 g_assert_not_reached(); /* argument recognization args_error */
308 errint=poptReadDefaultConfig(context,
311 g_assert_not_reached(); /* argument recognization args_error */
312 goto args_err_context;
314 errint=poptGetNextOpt(context);
316 g_assert_not_reached(); /* some non-callbacked argument reached */
317 goto args_err_context;
319 /* FIXME: reject non-"--"-prefixed arguments; how to detected them? */
320 r=TRUE; /* success */
322 poptFreeContext(context);
324 free(captive_args_argv); /* may be NULL here */
327 puts("FIXME: HELP HERE");
328 g_return_val_if_reached(r);
332 g_return_val_if_fail(image_iochannel!=NULL,FALSE);
334 captive_image_iochannel=image_iochannel;
335 /* Do not initialize 'captive_image_size' by captive_giochannel_size() here
336 * as we yet need to do g_io_channel_set_encoding().
339 errbool=captive_w32_init();
340 g_return_val_if_fail(errbool==TRUE,FALSE);