[EXT2]
[reactos.git] / reactos / drivers / filesystems / ext2 / src / ext2init.c
1 /*************************************************************************
2 *
3 * File: ext2init.c
4 *
5 * Module: Ext2 File System Driver (Kernel mode execution only)
6 *
7 * Description:
8 * This file contains the initialization code for the kernel mode
9 * Ext2 FSD module. The DriverEntry() routine is called by the I/O
10 * sub-system to initialize the FSD.
11 *
12 * Author: Manoj Paul Joseph
13 *
14 *************************************************************************/
15
16
17 #include "ext2fsd.h"
18
19 // define the file specific bug-check id
20 #define EXT2_BUG_CHECK_ID EXT2_FILE_INIT
21 #define DEBUG_LEVEL (DEBUG_TRACE_INIT)
22
23 #define EXT2_FS_NAME L"\\Ext2fs" // Must match others!
24
25 // global variables are declared here
26 Ext2Data Ext2GlobalData;
27
28
29 /*************************************************************************
30 *
31 * Function: DriverEntry()
32 *
33 * Description:
34 * This routine is the standard entry point for all kernel mode drivers.
35 * The routine is invoked at IRQL PASSIVE_LEVEL in the context of a
36 * system worker thread.
37 * All FSD specific data structures etc. are initialized here.
38 *
39 * Expected Interrupt Level (for execution) :
40 *
41 * IRQL_PASSIVE_LEVEL
42 *
43 * Return Value: STATUS_SUCCESS/Error (will cause driver to be unloaded).
44 *
45 *************************************************************************/
46 NTSTATUS NTAPI DriverEntry(
47 PDRIVER_OBJECT DriverObject, // created by the I/O sub-system
48 PUNICODE_STRING RegistryPath) // path to the registry key
49 {
50 NTSTATUS RC = STATUS_SUCCESS;
51 UNICODE_STRING DriverDeviceName;
52
53 #if 0
54 Ext2BreakPoint();
55 #endif
56
57 try
58 {
59 try
60 {
61
62 DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Ext2 File System Driver Entry <<<<<<<", 0);
63 // initialize the global data structure
64 RtlZeroMemory(&Ext2GlobalData, sizeof(Ext2GlobalData));
65
66 // initialize some required fields
67 Ext2GlobalData.NodeIdentifier.NodeType = EXT2_NODE_TYPE_GLOBAL_DATA;
68 Ext2GlobalData.NodeIdentifier.NodeSize = sizeof(Ext2GlobalData);
69
70 // initialize the global data resource and remember the fact that
71 // the resource has been initialized
72 RC = ExInitializeResourceLite(&(Ext2GlobalData.GlobalDataResource));
73 ASSERT(NT_SUCCESS(RC));
74 Ext2SetFlag(Ext2GlobalData.Ext2Flags, EXT2_DATA_FLAGS_RESOURCE_INITIALIZED);
75
76 // keep a ptr to the driver object sent to us by the I/O Mgr
77 Ext2GlobalData.Ext2DriverObject = DriverObject;
78
79 // initialize the mounted logical volume list head
80 InitializeListHead( &( Ext2GlobalData.NextVCB ) );
81
82 // before we proceed with any more initialization, read in
83 // user supplied configurable values ...
84 // if (!NT_SUCCESS(RC = Ext2ObtainRegistryValues(RegistryPath))) {
85 // in your commercial driver implementation, it would be
86 // advisable for your driver to print an appropriate error
87 // message to the system error log before leaving
88 // try_return();
89 // }
90
91 // we should have the registry data (if any), allocate zone memory ...
92 // This is an example of when FSD implementations try to pre-allocate
93 // some fixed amount of memory to avoid internal fragmentation and/or waiting
94 // later during run-time ...
95
96 #ifdef USE_ZONES
97
98 if (!NT_SUCCESS(RC = Ext2InitializeZones()))
99 {
100 // we failed, print a message and leave ...
101 try_return();
102 }
103 #endif
104
105 //
106 // Initialize the Thread queue structure...
107 //
108 KeInitializeEvent(
109 &Ext2GlobalData.ThreadQueue.QueueEvent,
110 SynchronizationEvent,
111 FALSE
112 );
113 KeInitializeSpinLock( &Ext2GlobalData.ThreadQueue.SpinLock );
114 InitializeListHead( &Ext2GlobalData.ThreadQueue.ThreadQueueListHead );
115
116 //
117 // Done Initializing...
118 // Now Creating a worker thread to handle Worker threads...
119 //
120 PsCreateSystemThread(
121 &Ext2GlobalData.ThreadQueue.QueueHandlerThread, (ACCESS_MASK) 0L,
122 NULL, NULL, NULL, Ext2QueueHandlerThread, NULL );
123
124 // initialize the IRP major function table, and the fast I/O table
125 Ext2FsdInitializeFunctionPointers(DriverObject);
126
127 // create a device object representing the driver itself
128 // so that requests can be targeted to the driver ...
129 // e.g. for a disk-based FSD, "mount" requests will be sent to
130 // this device object by the I/O Manager.
131 // For a redirector/server, you may have applications
132 // send "special" IOCTL's using this device object ...
133 RtlInitUnicodeString(&DriverDeviceName, EXT2_FS_NAME);
134 if (!NT_SUCCESS(RC = IoCreateDevice(
135 DriverObject, // our driver object
136 0, // don't need an extension for this object
137 &DriverDeviceName,// name - can be used to "open" the driver
138 // see the book for alternate choices
139 FILE_DEVICE_DISK_FILE_SYSTEM,
140 0, // no special characteristics
141 // do not want this as an exclusive device, though you might
142 FALSE,
143 &(Ext2GlobalData.Ext2DeviceObject))))
144 {
145 // failed to create a device object, leave ...
146 try_return();
147 }
148
149
150
151 // register the driver with the I/O Manager, pretend as if this is
152 // a physical disk based FSD (or in order words, this FSD manages
153 // logical volumes residing on physical disk drives)
154 IoRegisterFileSystem(Ext2GlobalData.Ext2DeviceObject);
155
156 {
157 TIME_FIELDS TimeFields;
158
159 TimeFields.Day = 1;
160 TimeFields.Hour = 0;
161 TimeFields.Milliseconds = 0;
162 TimeFields.Minute = 0;
163 TimeFields.Month = 1;
164 TimeFields.Second = 0;
165 TimeFields.Weekday = 0;
166 TimeFields.Year = 1970;
167 RtlTimeFieldsToTime( &TimeFields, &Ext2GlobalData.TimeDiff );
168
169 /*
170 Ext2GlobalData.TimeDiff.QuadPart = 0;
171 RtlTimeToTimeFields( &Ext2GlobalData.TimeDiff,&TimeFields );
172 TimeFields.Year = 2002;
173 RtlTimeFieldsToTime( &TimeFields, &Ext2GlobalData.TimeDiff );
174 */
175
176 }
177 }
178 except (EXCEPTION_EXECUTE_HANDLER)
179 {
180 // we encountered an exception somewhere, eat it up
181 RC = GetExceptionCode();
182 }
183
184 try_exit: NOTHING;
185 }
186 finally
187 {
188 // start unwinding if we were unsuccessful
189 if (!NT_SUCCESS(RC))
190 {
191
192 // Now, delete any device objects, etc. we may have created
193 if (Ext2GlobalData.Ext2DeviceObject)
194 {
195 IoDeleteDevice(Ext2GlobalData.Ext2DeviceObject);
196 Ext2GlobalData.Ext2DeviceObject = NULL;
197 }
198
199 // free up any memory we might have reserved for zones/lookaside
200 // lists
201 if (Ext2GlobalData.Ext2Flags & EXT2_DATA_FLAGS_ZONES_INITIALIZED)
202 {
203 Ext2DestroyZones();
204 }
205
206 // delete the resource we may have initialized
207 if (Ext2GlobalData.Ext2Flags & EXT2_DATA_FLAGS_RESOURCE_INITIALIZED)
208 {
209 // un-initialize this resource
210 ExDeleteResourceLite(&(Ext2GlobalData.GlobalDataResource));
211 Ext2ClearFlag(Ext2GlobalData.Ext2Flags, EXT2_DATA_FLAGS_RESOURCE_INITIALIZED);
212 }
213 }
214 }
215
216 return(RC);
217 }
218
219 /*************************************************************************
220 *
221 * Function: Ext2FsdInitializeFunctionPointers()
222 *
223 * Description:
224 * Initialize the IRP... function pointer array in the driver object
225 * structure. Also initialize the fast-io function ptr array ...
226 *
227 * Expected Interrupt Level (for execution) :
228 *
229 * IRQL_PASSIVE_LEVEL
230 *
231 * Return Value: None
232 *
233 *************************************************************************/
234 void NTAPI Ext2FsdInitializeFunctionPointers(
235 PDRIVER_OBJECT DriverObject) // created by the I/O sub-system
236 {
237 PFAST_IO_DISPATCH PtrFastIoDispatch = NULL;
238
239 // initialize the function pointers for the IRP major
240 // functions that this FSD is prepared to handle ...
241 // NT Version 4.0 has 28 possible functions that a
242 // kernel mode driver can handle.
243 // NT Version 3.51 and before has only 22 such functions,
244 // of which 18 are typically interesting to most FSD's.
245
246 // The only interesting new functions that a FSD might
247 // want to respond to beginning with Version 4.0 are the
248 // IRP_MJ_QUERY_QUOTA and the IRP_MJ_SET_QUOTA requests.
249
250 // The code below does not handle quota manipulation, neither
251 // does the NT Version 4.0 operating system (or I/O Manager).
252 // However, you should be on the lookout for any such new
253 // functionality that your FSD might have to implement in
254 // the near future.
255
256 DriverObject->MajorFunction[IRP_MJ_CREATE] = Ext2Create;
257 DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ext2Close;
258 DriverObject->MajorFunction[IRP_MJ_READ] = Ext2Read;
259 DriverObject->MajorFunction[IRP_MJ_WRITE] = Ext2Write;
260
261 DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = Ext2FileInfo;
262 DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = Ext2FileInfo;
263
264 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = Ext2Flush;
265 // To implement support for querying and modifying volume attributes
266 // (volume information query/set operations), enable initialization
267 // of the following two function pointers and then implement the supporting
268 // functions. Use Chapter 11 in the text to assist you in your efforts.
269 DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = Ext2QueryVolInfo;
270 DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = Ext2SetVolInfo;
271 DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = Ext2DirControl;
272 // To implement support for file system IOCTL calls, enable initialization
273 // of the following function pointer and implement appropriate support. Use
274 // Chapter 11 in the text to assist you in your efforts.
275 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = Ext2FileSystemControl;
276 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Ext2DeviceControl;
277 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = Ext2Shutdown;
278 // For byte-range lock support, enable initialization of the following
279 // function pointer and implement appropriate support. Use Chapter 10
280 // in the text to assist you in your efforts.
281 // DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = Ext2LockControl;
282 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Ext2Cleanup;
283 // If your FSD supports security attributes, you should provide appropriate
284 // dispatch entry points and initialize the function pointers as given below.
285 // DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = Ext2Security;
286 // DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = Ext2Security;
287 // If you support extended attributes, you should provide appropriate
288 // dispatch entry points and initialize the function pointers as given below.
289 // DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = Ext2ExtendedAttr;
290 // DriverObject->MajorFunction[IRP_MJ_SET_EA] = Ext2ExtendedAttr;
291
292 // Now, it is time to initialize the fast-io stuff ...
293 /*
294 DriverObject->FastIoDispatch = NULL;
295
296 */
297 PtrFastIoDispatch = DriverObject->FastIoDispatch = &(Ext2GlobalData.Ext2FastIoDispatch);
298
299 // initialize the global fast-io structure
300 // NOTE: The fast-io structure has undergone a substantial revision
301 // in Windows NT Version 4.0. The structure has been extensively expanded.
302 // Therefore, if your driver needs to work on both V3.51 and V4.0+,
303 // you will have to be able to distinguish between the two versions at compile time.
304 PtrFastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
305 PtrFastIoDispatch->FastIoCheckIfPossible = Ext2FastIoCheckIfPossible;
306 PtrFastIoDispatch->FastIoRead = Ext2FastIoRead;
307 PtrFastIoDispatch->FastIoWrite = Ext2FastIoWrite;
308 PtrFastIoDispatch->FastIoQueryBasicInfo = Ext2FastIoQueryBasicInfo;
309 PtrFastIoDispatch->FastIoQueryStandardInfo = Ext2FastIoQueryStdInfo;
310 PtrFastIoDispatch->FastIoLock = Ext2FastIoLock;
311 PtrFastIoDispatch->FastIoUnlockSingle = Ext2FastIoUnlockSingle;
312 PtrFastIoDispatch->FastIoUnlockAll = Ext2FastIoUnlockAll;
313 PtrFastIoDispatch->FastIoUnlockAllByKey = Ext2FastIoUnlockAllByKey;
314 PtrFastIoDispatch->AcquireFileForNtCreateSection = Ext2FastIoAcqCreateSec;
315 PtrFastIoDispatch->ReleaseFileForNtCreateSection = Ext2FastIoRelCreateSec;
316
317 // the remaining are only valid under NT Version 4.0 and later
318 #if(_WIN32_WINNT >= 0x0400)
319 PtrFastIoDispatch->FastIoQueryNetworkOpenInfo = Ext2FastIoQueryNetInfo;
320 PtrFastIoDispatch->AcquireForModWrite = Ext2FastIoAcqModWrite;
321 PtrFastIoDispatch->ReleaseForModWrite = Ext2FastIoRelModWrite;
322 PtrFastIoDispatch->AcquireForCcFlush = Ext2FastIoAcqCcFlush;
323 PtrFastIoDispatch->ReleaseForCcFlush = Ext2FastIoRelCcFlush;
324
325 // MDL functionality
326 PtrFastIoDispatch->MdlRead = Ext2FastIoMdlRead;
327 PtrFastIoDispatch->MdlReadComplete = Ext2FastIoMdlReadComplete;
328 PtrFastIoDispatch->PrepareMdlWrite = Ext2FastIoPrepareMdlWrite;
329 PtrFastIoDispatch->MdlWriteComplete = Ext2FastIoMdlWriteComplete;
330
331 // although this FSD does not support compressed read/write functionality,
332 // NTFS does, and if you design a FSD that can provide such functionality,
333 // you should consider initializing the fast io entry points for reading
334 // and/or writing compressed data ...
335 #endif // (_WIN32_WINNT >= 0x0400)
336
337
338 // last but not least, initialize the Cache Manager callback functions
339 // which are used in CcInitializeCacheMap()
340 Ext2GlobalData.CacheMgrCallBacks.AcquireForLazyWrite = Ext2AcqLazyWrite;
341 Ext2GlobalData.CacheMgrCallBacks.ReleaseFromLazyWrite = Ext2RelLazyWrite;
342 Ext2GlobalData.CacheMgrCallBacks.AcquireForReadAhead = Ext2AcqReadAhead;
343 Ext2GlobalData.CacheMgrCallBacks.ReleaseFromReadAhead = Ext2RelReadAhead;
344
345 return;
346 }
347
348
349 VOID NTAPI Ext2QueueHandlerThread(
350 IN PVOID StartContext )
351 {
352
353 DebugTrace(DEBUG_TRACE_MISC, "Ext2QueueHandlerThread!!!", 0);
354
355 while( 1 )
356 {
357 KeWaitForSingleObject( &Ext2GlobalData.ThreadQueue.QueueEvent,
358 Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
359
360 DebugTrace(DEBUG_TRACE_MISC, "Ext2QueueHandlerThread Alerted!!!", 0);
361
362 while( !IsListEmpty( &Ext2GlobalData.ThreadQueue.ThreadQueueListHead ) )
363 {
364 HANDLE ThreadHandle;
365 PLIST_ENTRY PtrEntry = NULL;
366 PtrExt2IrpContext PtrIrpContext = NULL;
367
368
369 PtrEntry = ExInterlockedRemoveHeadList(
370 &Ext2GlobalData.ThreadQueue.ThreadQueueListHead,
371 &Ext2GlobalData.ThreadQueue.SpinLock );
372 ASSERT( PtrEntry );
373 PtrIrpContext = CONTAINING_RECORD( PtrEntry, Ext2IrpContext, ThreadQueueListEntry );
374
375 PsCreateSystemThread(
376 &ThreadHandle, (ACCESS_MASK) 0L,
377 NULL, NULL, NULL, Ext2CommonDispatch, PtrIrpContext );
378 }
379 }
380 }