Windows: Use MountRoot for Absolute Symlinks
[openafs.git] / src / WINNT / afsrdr / kernel / fs / AFSInit.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSInit.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 #ifndef AMD64
42 extern "C"
43 {
44 extern void                   *KeServiceDescriptorTable;
45 };
46 #endif
47
48 typedef NTSTATUS (*PsSetCreateProcessNotifyRoutineEx_t)( PCREATE_PROCESS_NOTIFY_ROUTINE_EX NotifyRoutine, BOOLEAN Remove);
49
50 //
51 // DriverEntry
52 //
53 // This is the initial entry point for the driver.
54 //
55 // Inputs:
56 //  DriverObject        Pointer to Driver Object created by I/O manager
57 //  RegistryPath        Pointer to registry path representing this Driver
58 //
59 // Returns:
60 //  Success             To indicate Driver's inituaialization processing
61 //                      was successful
62 //  NT ERROR STATUS     Otherwise -- Driver does not remain loaded
63 //
64
65 NTSTATUS
66 DriverEntry( PDRIVER_OBJECT DriverObject,
67              PUNICODE_STRING RegistryPath)
68 {
69
70     NTSTATUS ntStatus = STATUS_SUCCESS;
71     AFSDeviceExt    *pDeviceExt;
72     ULONG ulTimeIncrement = 0;
73     UNICODE_STRING uniSymLinkName;
74     UNICODE_STRING uniDeviceName;
75     ULONG ulIndex = 0;
76     ULONG ulValue = 0;
77     UNICODE_STRING uniValueName;
78     BOOLEAN bExit = FALSE;
79     UNICODE_STRING uniRoutine;
80     RTL_OSVERSIONINFOW sysVersion;
81     UNICODE_STRING uniPsSetCreateProcessNotifyRoutineEx;
82     PsSetCreateProcessNotifyRoutineEx_t pPsSetCreateProcessNotifyRoutineEx = NULL;
83
84     __try
85     {
86
87         DbgPrint("AFSRedirFs DriverEntry Initialization build %s:%s\n", __DATE__, __TIME__);
88
89         //
90         // Initialize some local variables for easier processing
91         //
92
93         uniSymLinkName.Buffer = NULL;
94
95         AFSDumpFileLocation.Length = 0;
96         AFSDumpFileLocation.MaximumLength = 0;
97         AFSDumpFileLocation.Buffer = NULL;
98
99         AFSDumpFileName.Length = 0;
100         AFSDumpFileName.Buffer = NULL;
101         AFSDumpFileName.MaximumLength = 0;
102
103         ExInitializeResourceLite( &AFSDbgLogLock);
104
105         //
106         // Initialize the server name
107         //
108
109         AFSReadServerName();
110
111         AFSReadMountRootName();
112
113         RtlZeroMemory( &sysVersion,
114                        sizeof( RTL_OSVERSIONINFOW));
115
116         sysVersion.dwOSVersionInfoSize = sizeof( RTL_OSVERSIONINFOW);
117
118         RtlGetVersion( &sysVersion);
119
120         RtlInitUnicodeString( &uniRoutine,
121                               L"ZwSetInformationToken");
122
123         AFSSetInformationToken = (PAFSSetInformationToken)MmGetSystemRoutineAddress( &uniRoutine);
124
125         if( AFSSetInformationToken == NULL)
126         {
127 #ifndef AMD64
128             AFSSrvcTableEntry *pServiceTable = NULL;
129
130             pServiceTable = (AFSSrvcTableEntry *)KeServiceDescriptorTable;
131
132             //
133             // Only perform this lookup for Windows XP.
134             //
135
136             if( pServiceTable != NULL &&
137                 sysVersion.dwMajorVersion == 5 &&
138                 sysVersion.dwMinorVersion == 1)
139             {
140                 AFSSetInformationToken = (PAFSSetInformationToken)pServiceTable->ServiceTable[ 0xE6];
141             }
142 #endif
143         }
144
145         //
146         // And the global root share name
147         //
148
149         RtlInitUnicodeString( &AFSGlobalRootName,
150                               AFS_GLOBAL_ROOT_SHARE_NAME);
151
152         RtlZeroMemory( &AFSNoPAGAuthGroup,
153                        sizeof( GUID));
154
155         //
156         // Our backdoor to not let the driver load
157         //
158
159         if( bExit)
160         {
161             try_return( ntStatus);
162         }
163
164         //
165         // Perform some initialization
166         //
167
168         AFSDriverObject = DriverObject;
169
170         ntStatus = AFSReadRegistry( RegistryPath);
171
172         if( !NT_SUCCESS( ntStatus))
173         {
174
175             DbgPrint("AFS DriverEntry: Failed to read registry Status %08lX\n", ntStatus);
176
177             ntStatus = STATUS_SUCCESS;
178         }
179
180         //
181         // Initialize the debug log and dump file interface
182         //
183
184         AFSInitializeDbgLog();
185
186         AFSInitializeDumpFile();
187
188 #if DBG
189
190         if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_BREAK_ON_ENTRY))
191         {
192
193             DbgPrint("AFSRedirFs DriverEntry - Break on entry\n");
194
195             AFSBreakPoint();
196
197             if ( bExit)
198             {
199                 //
200                 // Just as above
201                 //
202                 try_return( ntStatus = STATUS_UNSUCCESSFUL);
203             }
204         }
205 #endif
206
207         if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_REQUIRE_CLEAN_SHUTDOWN) &&
208             !BooleanFlagOn( AFSDebugFlags, AFS_DBG_CLEAN_SHUTDOWN))
209         {
210
211             AFSPrint("AFS DriverEntry: Failed to shutdown clean, exiting\n");
212
213             try_return( ntStatus = STATUS_UNSUCCESSFUL);
214         }
215
216         //
217         // Setup the registry string
218         //
219
220         AFSRegistryPath.MaximumLength = RegistryPath->MaximumLength;
221         AFSRegistryPath.Length        = RegistryPath->Length;
222
223         AFSRegistryPath.Buffer = (PWSTR)ExAllocatePoolWithTag( PagedPool,
224                                                                AFSRegistryPath.Length,
225                                                                AFS_GENERIC_MEMORY_18_TAG);
226
227         if( AFSRegistryPath.Buffer == NULL)
228         {
229
230             DbgPrint("AFSRedirFs DriverEntry Failed to allocate registry path buffer\n");
231
232             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
233         }
234
235         RtlCopyMemory( AFSRegistryPath.Buffer,
236                        RegistryPath->Buffer,
237                        RegistryPath->Length);
238
239         if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_REQUIRE_CLEAN_SHUTDOWN))
240         {
241
242             //
243             // Update the shutdown flag
244             //
245
246             ulValue = (ULONG)-1;
247
248             RtlInitUnicodeString( &uniValueName,
249                                   AFS_REG_SHUTDOWN_STATUS);
250
251             AFSUpdateRegistryParameter( &uniValueName,
252                                         REG_DWORD,
253                                         &ulValue,
254                                         sizeof( ULONG));
255         }
256
257         RtlInitUnicodeString( &uniDeviceName,
258                               AFS_CONTROL_DEVICE_NAME);
259
260         ntStatus = IoCreateDeviceSecure( DriverObject,
261                                          sizeof( AFSDeviceExt),
262                                          &uniDeviceName,
263                                          FILE_DEVICE_NETWORK_FILE_SYSTEM,
264                                          0,
265                                          FALSE,
266                                          &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX,
267                                          (LPCGUID)&GUID_SD_AFS_REDIRECTOR_CONTROL_OBJECT,
268                                          &AFSDeviceObject);
269
270         if( !NT_SUCCESS( ntStatus))
271         {
272
273             DbgPrint("AFS DriverEntry - Failed to allocate device control object Status %08lX\n", ntStatus);
274
275             try_return( ntStatus);
276         }
277
278         //
279         // Setup the device extension
280         //
281
282         pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
283
284         InitializeListHead( &pDeviceExt->Specific.Control.DirNotifyList);
285         FsRtlNotifyInitializeSync( &pDeviceExt->Specific.Control.NotifySync);
286
287         //
288         // Now initialize the control device
289         //
290
291         ntStatus = AFSInitializeControlDevice();
292
293         if( !NT_SUCCESS( ntStatus))
294         {
295
296             try_return( ntStatus);
297         }
298
299         //
300         // Allocate our symbolic link for service communication
301         //
302
303         RtlInitUnicodeString( &uniSymLinkName,
304                               AFS_SYMLINK_NAME);
305
306         ntStatus = IoCreateSymbolicLink( &uniSymLinkName,
307                                          &uniDeviceName);
308
309         if( !NT_SUCCESS( ntStatus))
310         {
311
312             DbgPrint("AFS DriverEntry - Failed to create symbolic link Status %08lX\n", ntStatus);
313
314             //
315             // OK, no one can communicate with us so fail
316             //
317
318             try_return( ntStatus);
319         }
320
321         //
322         // Fill in the dispatch table
323         //
324
325         for( ulIndex = 0; ulIndex <= IRP_MJ_MAXIMUM_FUNCTION; ulIndex++)
326         {
327
328             DriverObject->MajorFunction[ ulIndex] = AFSDefaultDispatch;
329         }
330
331         DriverObject->MajorFunction[IRP_MJ_CREATE] =                    AFSCreate;
332         DriverObject->MajorFunction[IRP_MJ_CLOSE] =                     AFSClose;
333         DriverObject->MajorFunction[IRP_MJ_READ] =                      AFSRead;
334         DriverObject->MajorFunction[IRP_MJ_WRITE] =                     AFSWrite;
335         DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =         AFSQueryFileInfo;
336         DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =           AFSSetFileInfo;
337         DriverObject->MajorFunction[IRP_MJ_QUERY_EA] =                  AFSQueryEA;
338         DriverObject->MajorFunction[IRP_MJ_SET_EA] =                    AFSSetEA;
339         DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] =             AFSFlushBuffers;
340         DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =  AFSQueryVolumeInfo;
341         DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] =    AFSSetVolumeInfo;
342         DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =         AFSDirControl;
343         DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =       AFSFSControl;
344         DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =            AFSDevControl;
345         DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =   AFSInternalDevControl;
346         DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] =                  AFSShutdown;
347         DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] =              AFSLockControl;
348         DriverObject->MajorFunction[IRP_MJ_CLEANUP] =                   AFSCleanup;
349         DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] =            AFSQuerySecurity;
350         DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] =              AFSSetSecurity;
351         DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] =            AFSSystemControl;
352         //DriverObject->MajorFunction[IRP_MJ_QUERY_QUOTA] =               AFSQueryQuota;
353         //DriverObject->MajorFunction[IRP_MJ_SET_QUOTA] =                 AFSSetQuota;
354
355         //
356         // Since we are not a true FSD then we are not controlling a device and hence these will not be needed
357         //
358
359 #ifdef FSD_NOT_USED
360
361         DriverObject->MajorFunction[IRP_MJ_POWER] =                     AFSPower;
362         DriverObject->MajorFunction[IRP_MJ_PNP] =                       AFSPnP;
363
364 #endif
365
366         //
367         // Fast IO Dispatch table
368         //
369
370         DriverObject->FastIoDispatch = &AFSFastIoDispatch;
371
372         RtlZeroMemory( &AFSFastIoDispatch,
373                        sizeof( AFSFastIoDispatch));
374
375         //
376         // Again, since we are not a registered FSD many of these are not going to be called. They are here
377         // for completeness.
378         //
379
380         AFSFastIoDispatch.SizeOfFastIoDispatch         = sizeof(FAST_IO_DISPATCH);
381         AFSFastIoDispatch.FastIoCheckIfPossible        = AFSFastIoCheckIfPossible;  //  CheckForFastIo
382         AFSFastIoDispatch.FastIoRead                   = AFSFastIoRead;             //  Read
383         AFSFastIoDispatch.FastIoWrite                  = AFSFastIoWrite;            //  Write
384         AFSFastIoDispatch.FastIoQueryBasicInfo         = AFSFastIoQueryBasicInfo;     //  QueryBasicInfo
385         AFSFastIoDispatch.FastIoQueryStandardInfo      = AFSFastIoQueryStandardInfo;       //  QueryStandardInfo
386         AFSFastIoDispatch.FastIoLock                   = AFSFastIoLock;               //  Lock
387         AFSFastIoDispatch.FastIoUnlockSingle           = AFSFastIoUnlockSingle;       //  UnlockSingle
388         AFSFastIoDispatch.FastIoUnlockAll              = AFSFastIoUnlockAll;          //  UnlockAll
389         AFSFastIoDispatch.FastIoUnlockAllByKey         = AFSFastIoUnlockAllByKey;     //  UnlockAllByKey
390         AFSFastIoDispatch.FastIoQueryNetworkOpenInfo   = AFSFastIoQueryNetworkOpenInfo;
391         AFSFastIoDispatch.AcquireForCcFlush            = AFSFastIoAcquireForCCFlush;
392         AFSFastIoDispatch.ReleaseForCcFlush            = AFSFastIoReleaseForCCFlush;
393         AFSFastIoDispatch.FastIoDeviceControl          = AFSFastIoDevCtrl;
394         AFSFastIoDispatch.AcquireFileForNtCreateSection = AFSFastIoAcquireFile;
395         AFSFastIoDispatch.ReleaseFileForNtCreateSection = AFSFastIoReleaseFile;
396         AFSFastIoDispatch.FastIoDetachDevice           = AFSFastIoDetachDevice;
397         //AFSFastIoDispatch.AcquireForModWrite           = AFSFastIoAcquireForModWrite;
398         //AFSFastIoDispatch.ReleaseForModWrite           = AFSFastIoReleaseForModWrite;
399         AFSFastIoDispatch.MdlRead                      = AFSFastIoMdlRead;
400         AFSFastIoDispatch.MdlReadComplete              = AFSFastIoMdlReadComplete;
401         AFSFastIoDispatch.PrepareMdlWrite              = AFSFastIoPrepareMdlWrite;
402         AFSFastIoDispatch.MdlWriteComplete             = AFSFastIoMdlWriteComplete;
403         AFSFastIoDispatch.FastIoReadCompressed         = AFSFastIoReadCompressed;
404         AFSFastIoDispatch.FastIoWriteCompressed        = AFSFastIoWriteCompressed;
405         AFSFastIoDispatch.MdlReadCompleteCompressed    = AFSFastIoMdlReadCompleteCompressed;
406         AFSFastIoDispatch.MdlWriteCompleteCompressed   = AFSFastIoMdlWriteCompleteCompressed;
407         AFSFastIoDispatch.FastIoQueryOpen              = AFSFastIoQueryOpen;
408
409         //
410         //  Cache manager callback routines.
411         //
412
413         AFSCacheManagerCallbacks.AcquireForLazyWrite  = &AFSAcquireFcbForLazyWrite;
414         AFSCacheManagerCallbacks.ReleaseFromLazyWrite = &AFSReleaseFcbFromLazyWrite;
415         AFSCacheManagerCallbacks.AcquireForReadAhead  = &AFSAcquireFcbForReadAhead;
416         AFSCacheManagerCallbacks.ReleaseFromReadAhead = &AFSReleaseFcbFromReadAhead;
417
418         //
419         //  System process.
420         //
421
422         AFSSysProcess = PsGetCurrentProcessId();
423
424         //
425         // Register for shutdown notification
426         //
427
428         IoRegisterShutdownNotification( AFSDeviceObject);
429
430         //
431         // Initialize the system process cb
432         //
433
434         AFSInitializeProcessCB( 0,
435                                 (ULONGLONG)AFSSysProcess);
436
437         //
438         // Initialize the redirector device
439         //
440
441         ntStatus = AFSInitRDRDevice();
442
443         if( !NT_SUCCESS( ntStatus))
444         {
445
446             DbgPrint("AFS DriverEntry Failed to initialize redirector device Status %08lX\n");
447
448             try_return( ntStatus);
449         }
450
451         //
452         // Initialize some server name based strings
453         //
454
455         AFSInitServerStrings();
456
457         //
458         // Register the call back for process creation and tear down.
459         // On Vista SP1 and above, PsSetCreateProcessNotifyRoutineEx
460         // will be used.  This function returns STATUS_ACCESS_DENIED
461         // if there is a signing error.  In that case, the AFSProcessNotifyEx
462         // routine has not been registered and we can fallback to the
463         // Windows 2000 interface and AFSProcessNotify.
464         //
465
466         RtlInitUnicodeString( &uniPsSetCreateProcessNotifyRoutineEx,
467                               L"PsSetCreateProcessNotifyRoutineEx");
468
469         pPsSetCreateProcessNotifyRoutineEx = (PsSetCreateProcessNotifyRoutineEx_t)MmGetSystemRoutineAddress(&uniPsSetCreateProcessNotifyRoutineEx);
470
471         ntStatus = STATUS_ACCESS_DENIED;
472
473         if ( pPsSetCreateProcessNotifyRoutineEx)
474         {
475
476             ntStatus = pPsSetCreateProcessNotifyRoutineEx( AFSProcessNotifyEx,
477                                                            FALSE);
478         }
479
480         if ( ntStatus == STATUS_ACCESS_DENIED)
481         {
482
483             ntStatus = PsSetCreateProcessNotifyRoutine( AFSProcessNotify,
484                                                         FALSE);
485         }
486
487         ntStatus = STATUS_SUCCESS;
488
489 try_exit:
490
491         if( !NT_SUCCESS( ntStatus))
492         {
493
494             DbgPrint("AFSRedirFs DriverEntry failed to initialize %08lX\n", ntStatus);
495
496             if( AFSRegistryPath.Buffer != NULL)
497             {
498
499                 ExFreePool( AFSRegistryPath.Buffer);
500             }
501
502             if( uniSymLinkName.Buffer != NULL)
503             {
504
505                 IoDeleteSymbolicLink( &uniSymLinkName);
506             }
507
508             if( AFSDeviceObject != NULL)
509             {
510
511                 AFSRemoveControlDevice();
512
513                 FsRtlNotifyUninitializeSync( &pDeviceExt->Specific.Control.NotifySync);
514
515                 IoUnregisterShutdownNotification( AFSDeviceObject);
516
517                 IoDeleteDevice( AFSDeviceObject);
518             }
519
520             AFSTearDownDbgLog();
521
522             ExDeleteResourceLite( &AFSDbgLogLock);
523         }
524     }
525     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
526     {
527
528         AFSDbgLogMsg( 0,
529                       0,
530                       "EXCEPTION - AFSRedirFs DriverEntry\n");
531
532         AFSDumpTraceFilesFnc();
533     }
534
535     return ntStatus;
536 }