+(disabled) option to not to use custom SIGSEGV handler for .so filesystem format
[captive.git] / src / libcaptive / client / init.c
1 /* $Id$
2  * Init and cleanup code of libcaptive to be called by client application
3  * Copyright (C) 2002 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
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
8  * 
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.
13  * 
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
17  */
18
19
20 #include "config.h"
21
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/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 */
32 #include <fcntl.h>
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() */
41
42
43 /* Are we initialized? */
44 static gboolean active;
45
46 /* Module of fs module itself loaded by captive_init(fs_path) */
47 static PMODULE_OBJECT ModuleObject;
48
49 /* Driver in fs module loaded by captive_init(fs_path) */
50 static DRIVER_OBJECT DriverObject;
51
52 /* Handle for the root directory of the mounted volume */
53 static HANDLE root_Handle;
54
55 /* Structure holding the pointer to the toplevel IRP */
56 static TOP_LEVEL_IRP TopLevelIrp;       /* TODO:thread */
57
58
59 /**
60  * captive_init:
61  * @fs_path: Host OS file #utf8 pathname of the filesystem module to load.
62  * %NULL value is forbidden.
63  * @image_pathname: Host OS file #utf8 pathname of the disk image to mount.
64  * %NULL value is forbidden.
65  *
66  * Initializes %libcaptive and loads the specified filesystem.
67  *
68  * Returns: %TRUE if successfuly loaded.
69  */
70 gboolean captive_init(const gchar *fs_path,const gchar *image_pathname)
71 {
72 NTSTATUS err;
73 gboolean errbool;
74 OBJECT_ATTRIBUTES root_ObjectAttributes;
75 IO_STATUS_BLOCK root_IoStatusBlock;
76 #if 0
77 FILE_ID_BOTH_DIR_INFORMATION *FileIdBothDirInformation;
78 #endif
79 char QueryDirectory_buf[0x10000];
80
81 #ifdef MAINTAINER_MODE
82         g_log_set_always_fatal(~(0
83                         |G_LOG_LEVEL_MESSAGE
84                         |G_LOG_LEVEL_INFO
85                         |G_LOG_LEVEL_DEBUG
86                         ));
87 #endif
88
89         g_return_val_if_fail(fs_path!=NULL,FALSE);
90         g_return_val_if_fail(image_pathname!=NULL,FALSE);
91         g_return_val_if_fail(active==FALSE,FALSE);
92
93         /* Part of reactos/ntoskrnl/ke/main.c/KiSystemStartup() begins. */
94         /* ExpInitializeExecutive(); */
95                 /* Part of reactos/ntoskrnl/ke/main.c/ExpInitializeExecutive() begins
96                  * here as the rest of the function does a lot of hardware initializations.
97                  */
98                 /* LdrInit1(); */
99                         /* Part of reactos/ntoskrnl/ldr/loader.c/LdrInit1() begins. */
100                         InitializeListHead(&ModuleTextListHead);
101                         /* Part of reactos/ntoskrnl/ldr/loader.c/LdrInit1() ends. */
102                 /*...*/
103                 /* create default nls tables */
104                 RtlpInitNlsTables();
105                 /*...*/
106                 ObInit();
107                 /*...*/
108                 /* PiInitProcessManager(); */
109                         /* Part of reactos/ntoskrnl/ps/psmgr.c/PiInitProcessManager() begins. */
110                         PsInitProcessManagment();
111                         PsInitThreadManagment();
112                         /* Part of reactos/ntoskrnl/ps/psmgr.c/PiInitProcessManager() ends. */
113                 /*...*/
114                 IoInit();
115                 /*...*/
116                 /* LdrInitModuleManagement(); */
117                         /* Part of reactos/ntoskrnl/ldr/loader.c/LdrInitModuleManagement() begins
118                          * here as the rest "Create module object for {NTOSKRNL,HAL}"
119                          * is dependent on {NTOSKRNL,HAL} PE image headers not provided by libcaptive.
120                          */
121                         /* Initialize the module list and spinlock */
122                         InitializeListHead(&ModuleListHead);
123                         KeInitializeSpinLock(&ModuleListLock);
124                         /* Part of reactos/ntoskrnl/ldr/loader.c/LdrInitModuleManagement ends. */
125                 /* Part of reactos/ntoskrnl/ke/main.c/ExpInitializeExecutive() ends. */
126         /* Part of reactos/ntoskrnl/ke/main.c/KiSystemStartup() ends. */
127
128         /* Simulate our PE headers and export the symbols of {NTOSKRNL,HAL} */
129         captive_kernel_exports();
130
131         errbool=captive_cdrom_init(image_pathname);
132         g_return_val_if_fail(errbool==TRUE,FALSE);
133
134         err=captive_LdrpLoadAndCallImage(
135                         &ModuleObject,  /* ModuleObjectp */
136                         captive_utf8_to_UnicodeString_alloca(fs_path),  /* ModuleName */
137                         &DriverObject,  /* DriverEntry_DriverObject */
138                         captive_utf8_to_UnicodeString_alloca("\\captive\\filesystem")); /* DriverEntry_RegistryPath */
139         g_return_val_if_fail(NT_SUCCESS(err),FALSE);
140
141         /* set TopLevelIrp() - FIXME: where is it set by native reactos? */
142         PsGetCurrentThread()->TopLevelIrp=&TopLevelIrp; /* otherwise Io{Get,Set}TopLevelIrp() would SIGSEGV */
143
144         /* Begin possible handling of foreign W32 binary code here */
145         /* If you want to disable SIGSEGV handler if not needed:
146          *      if (ModuleObject->Flags & MODULE_FLAG_PE)
147          */
148         captive_signal_init();
149
150         /* Do not open "\Cdfs"(anything) as it is just the filesystem implementation.
151          * ntoskrnl/io/fs.c/IoMountVolume() will map
152          *      FILE_DEVICE_CD_ROM -> FILE_DEVICE_CD_ROM_FILE_SYSTEM
153          * for us automatically when opening the device itself.
154          * Also you must put some trailing content there as otherwise
155          *      IoCreateFile()->ObCreateObject()->ObFindObject()
156          * would leave 'ObCreateObject::RemainingPath' as NULL
157          * and later IopCreateFile() would consider it FO_DIRECT_DEVICE_OPEN (e.g. w/o any mount!)
158          */
159         InitializeObjectAttributes(
160                         &root_ObjectAttributes, /* InitializedAttributes */
161                         captive_utf8_to_UnicodeString_alloca("\\Device\\CdRom0\\."),    /* ObjectName */
162                         0,      /* Attributes; I hope no OBJ_KERNEL_HANDLE as we are 'system process' */
163                         NULL,   /* RootDirectory */
164                         NULL);  /* SecurityDescriptor; ignored */
165
166         /* wanted: * IoCreateFile()->ObCreateObject(,,,IoFileObjectType)->
167          * ->(IoFileObjectType->Create==IopCreateFile)()->IoMountVolume()
168          */
169         err=IoCreateFile(
170                         &root_Handle,   /* FileHandle */
171                         FILE_LIST_DIRECTORY,    /* DesiredAccess */
172                         &root_ObjectAttributes, /* ObjectAttributes */
173                         &root_IoStatusBlock,    /* IoStatusBlock */
174                         NULL,   /* AllocationSize; ignored for open */
175                         FILE_ATTRIBUTE_NORMAL,  /* FileAttributes; ignored for open */
176                         0,      /* ShareAccess; 0 means exclusive */
177                         FILE_OPEN,      /* CreateDisposition */
178                         /* FILE_SYNCHRONOUS_IO_{,NON}ALERT: We need to allow W32 filesystem
179                          * any waits to not to let it return STATUS_CANT_WAIT us.
180                          * Alertability should have only effect on asynchronous events
181                          * from KeWaitForSingleObject() by setting/clearing its parameter 'Alertable'.
182                          */
183                         FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_ALERT,  /* CreateOptions */
184                         NULL,   /* EaBuffer */
185                         0,      /* EaLength */
186                         CreateFileTypeNone,     /* CreateFileType */
187                         NULL,   /* ExtraCreateParameters */
188                         0);     /* Options */
189         g_return_val_if_fail(NT_SUCCESS(err),FALSE);
190         g_return_val_if_fail(NT_SUCCESS(root_IoStatusBlock.Status),FALSE);
191         g_return_val_if_fail(root_IoStatusBlock.Information==FILE_OPENED,FALSE);
192
193
194         err=NtQueryDirectoryFile(
195                         root_Handle,    /* FileHandle */
196       NULL,     /* PEvent; completion signalling; optional */
197                         NULL,   /* ApcRoutine; optional */
198                         NULL,   /* ApcContext; optional */
199                         &root_IoStatusBlock,    /* IoStatusBlock */
200                         (gpointer)QueryDirectory_buf,   /* FileInformation */
201                         sizeof(QueryDirectory_buf),     /* Length */
202                         FileIdBothDirectoryInformation, /* FileInformationClass; =>FILE_ID_BOTH_DIR_INFORMATION */
203                         FALSE,  /* ReturnSingleEntry */
204                         NULL,   /* FileName; wildcards possible; optional */
205                         TRUE);  /* RestartScan */
206         g_return_val_if_fail(NT_SUCCESS(err),FALSE);
207         g_return_val_if_fail(NT_SUCCESS(root_IoStatusBlock.Status),FALSE);
208
209
210         active=TRUE;
211         return TRUE;
212 }
213
214
215 /**
216  * captive_cleanup:
217  *
218  * Closes #libcaptive. Frees any used system resources. You are forbidden
219  * to touch any #libcaptive data or funtions before a new captive_init()
220  * is done. Forbidden to call it before successful captive_init() is done.
221  *
222  * Currently this function IS NOT IMPLEMENTED.
223  *
224  * Returns: %TRUE if the successful resource cleanup was done during the call.
225  */
226 gboolean captive_cleanup(void)
227 {
228 NTSTATUS err;
229
230         g_return_val_if_fail(active==TRUE,FALSE);
231
232         err=LdrUnloadModule(ModuleObject);
233         g_assert(NT_SUCCESS(err));
234
235         /* captive_cleanup() NOT IMPLEMENTED */
236         g_return_val_if_reached(FALSE);
237
238         active=FALSE;
239         return TRUE;
240 }