Windows: Redirector opens must set a valid FsContext
[openafs.git] / src / WINNT / afsrdr / kernel / fs / AFSRDRSupport.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: AFSRDRSupport.cpp
37 //
38 #include "AFSCommon.h"
39
40 typedef NTSTATUS  (*FsRtlRegisterUncProviderEx_t)( PHANDLE  MupHandle, PUNICODE_STRING  RedirDevName, PDEVICE_OBJECT  DeviceObject, ULONG  Flags);
41
42 NTSTATUS
43 AFSInitRDRDevice()
44 {
45
46     NTSTATUS       ntStatus = STATUS_SUCCESS;
47     UNICODE_STRING uniDeviceName;
48     ULONG          ulIndex = 0;
49     AFSDeviceExt  *pDeviceExt = NULL;
50     AFSFileID      stRootFid;
51     UNICODE_STRING uniFsRtlRegisterUncProviderEx;
52     FsRtlRegisterUncProviderEx_t pFsRtlRegisterUncProviderEx = NULL;
53
54     __Enter
55     {
56
57         RtlInitUnicodeString( &uniDeviceName,
58                               AFS_RDR_DEVICE_NAME);
59
60         RtlInitUnicodeString( &uniFsRtlRegisterUncProviderEx,
61                               L"FsRtlRegisterUncProviderEx");
62
63         pFsRtlRegisterUncProviderEx = (FsRtlRegisterUncProviderEx_t)MmGetSystemRoutineAddress(&uniFsRtlRegisterUncProviderEx);
64
65         ntStatus = IoCreateDevice( AFSDriverObject,
66                                    sizeof( AFSDeviceExt),
67                                    pFsRtlRegisterUncProviderEx ? NULL : &uniDeviceName,
68                                    FILE_DEVICE_NETWORK_FILE_SYSTEM,
69                                    FILE_REMOTE_DEVICE,
70                                    FALSE,
71                                    &AFSRDRDeviceObject);
72
73         if( !NT_SUCCESS( ntStatus))
74         {
75
76             AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
77                           AFS_TRACE_LEVEL_ERROR,
78                           "AFSInitRDRDevice IoCreateDevice failure %08lX\n",
79                           ntStatus);
80
81             try_return( ntStatus);
82         }
83
84         pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
85
86         RtlZeroMemory( pDeviceExt,
87                        sizeof( AFSDeviceExt));
88
89         //
90         // Initialize resources
91         //
92
93         pDeviceExt->Specific.RDR.VolumeTree.TreeLock = &pDeviceExt->Specific.RDR.VolumeTreeLock;
94
95         ExInitializeResourceLite( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
96
97         pDeviceExt->Specific.RDR.VolumeTree.TreeHead = NULL;
98
99         ExInitializeResourceLite( &pDeviceExt->Specific.RDR.VolumeListLock);
100
101         pDeviceExt->Specific.RDR.VolumeListHead = NULL;
102
103         pDeviceExt->Specific.RDR.VolumeListTail = NULL;
104
105         KeInitializeEvent( &pDeviceExt->Specific.RDR.QueuedReleaseExtentEvent,
106                            NotificationEvent,
107                            TRUE);
108
109         ExInitializeResourceLite( &pDeviceExt->Specific.RDR.RootCellTreeLock);
110
111         pDeviceExt->Specific.RDR.RootCellTree.TreeLock = &pDeviceExt->Specific.RDR.RootCellTreeLock;
112
113         pDeviceExt->Specific.RDR.RootCellTree.TreeHead = NULL;
114
115         ExInitializeResourceLite( &pDeviceExt->Specific.RDR.ProviderListLock);
116
117         ntStatus = AFSInitRdrFcb( &pDeviceExt->Fcb);
118
119         if ( !NT_SUCCESS(ntStatus))
120         {
121
122             AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
123                           AFS_TRACE_LEVEL_ERROR,
124                           "AFSInitRDRDevice AFSInitRdrFcb failure %08lX\n",
125                           ntStatus);
126
127             try_return( ntStatus);
128         }
129
130         //
131         // Clear the initializing bit
132         //
133
134         AFSRDRDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
135
136         //
137         // Register this device with MUP with FilterMgr if Vista or above
138         //
139
140         if( pFsRtlRegisterUncProviderEx)
141         {
142
143             ntStatus = pFsRtlRegisterUncProviderEx( &AFSMUPHandle,
144                                                     &uniDeviceName,
145                                                     AFSRDRDeviceObject,
146                                                     0);
147             if ( !NT_SUCCESS( ntStatus))
148             {
149                 AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
150                               AFS_TRACE_LEVEL_ERROR,
151                               "AFSInitRDRDevice FsRtlRegisterUncProvider failure %08lX\n",
152                               ntStatus);
153             }
154         }
155         else
156         {
157
158             ntStatus = FsRtlRegisterUncProvider( &AFSMUPHandle,
159                                                  &uniDeviceName,
160                                                  FALSE);
161
162             if ( NT_SUCCESS( ntStatus))
163             {
164
165                 IoRegisterFileSystem( AFSRDRDeviceObject);
166             }
167             else
168             {
169                 AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
170                               AFS_TRACE_LEVEL_ERROR,
171                               "AFSInitRDRDevice FsRtlRegisterUncProvider failure %08lX\n",
172                               ntStatus);
173             }
174         }
175
176         //
177         // Good to go, all registered and ready to start receiving requests
178         //
179
180 try_exit:
181
182         if( !NT_SUCCESS( ntStatus))
183         {
184
185             //
186             // Delete our device and bail
187             //
188
189             ExDeleteResourceLite( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
190
191             ExDeleteResourceLite( &pDeviceExt->Specific.RDR.VolumeListLock);
192
193             ExDeleteResourceLite( &pDeviceExt->Specific.RDR.RootCellTreeLock);
194
195             ExDeleteResourceLite( &pDeviceExt->Specific.RDR.ProviderListLock);
196
197             IoDeleteDevice( AFSRDRDeviceObject);
198
199             AFSRDRDeviceObject = NULL;
200
201             try_return( ntStatus);
202         }
203     }
204
205     return ntStatus;
206 }
207
208 NTSTATUS
209 AFSRDRDeviceControl( IN PDEVICE_OBJECT DeviceObject,
210                      IN PIRP Irp)
211 {
212
213     NTSTATUS           ntStatus = STATUS_SUCCESS;
214     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
215     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
216     BOOLEAN            bCompleteIrp = TRUE;
217
218     __Enter
219     {
220
221         switch( pIrpSp->Parameters.DeviceIoControl.IoControlCode)
222         {
223
224             case IOCTL_REDIR_QUERY_PATH:
225             {
226
227                 QUERY_PATH_REQUEST *pPathRequest = (QUERY_PATH_REQUEST *)pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
228                 QUERY_PATH_RESPONSE *pPathResponse = (QUERY_PATH_RESPONSE *)Irp->UserBuffer;
229                 UNICODE_STRING uniPathName;
230
231                 ntStatus = STATUS_BAD_NETWORK_PATH;
232
233                 uniPathName.Length = (USHORT)pPathRequest->PathNameLength;
234                 uniPathName.MaximumLength = uniPathName.Length;
235
236                 uniPathName.Buffer = pPathRequest->FilePathName;
237
238                 if( uniPathName.Length >= AFSServerName.Length + sizeof( WCHAR))
239                 {
240
241                     USHORT usLength = uniPathName.Length;
242
243                     uniPathName.Length = AFSServerName.Length;
244
245                     //
246                     // Skip over the first slash in the name
247                     //
248
249                     uniPathName.Buffer = &uniPathName.Buffer[ 1];
250
251
252                     //
253                     // Check to see if the first (or only) component
254                     // of the path matches the server name
255                     //
256
257                     if( RtlCompareUnicodeString( &AFSServerName,
258                                                  &uniPathName,
259                                                  TRUE) == 0 &&
260                         ( usLength == AFSServerName.Length + sizeof( WCHAR) ||
261                           uniPathName.Buffer[ AFSServerName.Length / sizeof( WCHAR)] == '\\'))
262                     {
263
264                         ntStatus = STATUS_SUCCESS;
265
266                         pPathResponse->LengthAccepted = AFSServerName.Length + sizeof( WCHAR);
267                     }
268                 }
269
270                 break;
271             }
272
273             case IOCTL_REDIR_QUERY_PATH_EX:
274             {
275
276                 QUERY_PATH_REQUEST_EX *pPathRequest = (QUERY_PATH_REQUEST_EX *)pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
277                 QUERY_PATH_RESPONSE *pPathResponse = (QUERY_PATH_RESPONSE *)Irp->UserBuffer;
278                 UNICODE_STRING uniPathName;
279
280                 ntStatus = STATUS_BAD_NETWORK_PATH;
281
282                 uniPathName.Length = pPathRequest->PathName.Length;
283                 uniPathName.MaximumLength = uniPathName.Length;
284
285                 uniPathName.Buffer = pPathRequest->PathName.Buffer;
286
287                 if( uniPathName.Length >= AFSServerName.Length + sizeof( WCHAR))
288                 {
289
290                     USHORT usLength = uniPathName.Length;
291
292                     uniPathName.Length = AFSServerName.Length;
293
294                     //
295                     // Skip over the first slash in the name
296                     //
297
298                     uniPathName.Buffer = &uniPathName.Buffer[ 1];
299
300
301                     //
302                     // Check to see if the first (or only) component
303                     // of the path matches the server name
304                     //
305
306                     if( RtlCompareUnicodeString( &AFSServerName,
307                                                  &uniPathName,
308                                                  TRUE) == 0 &&
309                         ( usLength == AFSServerName.Length + sizeof( WCHAR) ||
310                           uniPathName.Buffer[ AFSServerName.Length / sizeof( WCHAR)] == '\\'))
311                     {
312
313                         ntStatus = STATUS_SUCCESS;
314
315                         pPathResponse->LengthAccepted = AFSServerName.Length + sizeof( WCHAR);
316                     }
317                 }
318
319                 break;
320             }
321
322             default:
323
324                 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
325
326                 break;
327         }
328
329         if (bCompleteIrp)
330         {
331             //
332             // Complete the request
333             //
334
335             AFSCompleteRequest( Irp,
336                                 ntStatus);
337         }
338     }
339
340     return ntStatus;
341 }
342
343 NTSTATUS
344 AFSInitializeRedirector( IN AFSRedirectorInitInfo *RedirInitInfo)
345 {
346
347     NTSTATUS ntStatus = STATUS_SUCCESS;
348     LARGE_INTEGER cacheSizeBytes;
349     AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
350     AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
351     OBJECT_ATTRIBUTES   stObjectAttribs;
352     IO_STATUS_BLOCK stIoStatus;
353     UNICODE_STRING uniServiceName;
354
355     __Enter
356     {
357
358         //
359         // First this is to load the library
360         //
361
362         RtlInitUnicodeString( &uniServiceName,
363                               AFS_REDIR_LIBRARY_SERVICE_ENTRY);
364
365         ntStatus = AFSLoadLibrary( 0,
366                                    &uniServiceName);
367
368         if( !NT_SUCCESS( ntStatus))
369         {
370
371             AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
372                           AFS_TRACE_LEVEL_ERROR,
373                           "AFSInitializeRedirector AFSLoadLibrary failure %08lX\n",
374                           ntStatus);
375
376             try_return( ntStatus);
377         }
378
379         //
380         // Save off the cache file information
381         //
382
383         pDevExt->Specific.RDR.CacheBlockSize = RedirInitInfo->CacheBlockSize;
384
385         pDevExt->Specific.RDR.CacheBlockCount = RedirInitInfo->ExtentCount;
386
387         pDevExt->Specific.RDR.MaximumRPCLength = RedirInitInfo->MaximumChunkLength;
388
389         cacheSizeBytes = RedirInitInfo->ExtentCount;
390         cacheSizeBytes.QuadPart *= RedirInitInfo->CacheBlockSize;
391
392         AFSDumpFileLocation.Length = 0;
393
394         AFSDumpFileLocation.MaximumLength = (USHORT)RedirInitInfo->DumpFileLocationLength + (4 * sizeof( WCHAR));
395
396         AFSDumpFileLocation.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
397                                                                         AFSDumpFileLocation.MaximumLength,
398                                                                         AFS_GENERIC_MEMORY_23_TAG);
399
400         if( AFSDumpFileLocation.Buffer == NULL)
401         {
402
403             AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
404                           AFS_TRACE_LEVEL_ERROR,
405                           "AFSInitializeRedirector AFS_GENERIC_MEMORY_23_TAG allocation error\n");
406
407             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
408         }
409
410         RtlCopyMemory( AFSDumpFileLocation.Buffer,
411                        L"\\??\\",
412                        4 * sizeof( WCHAR));
413
414         AFSDumpFileLocation.Length = 4 * sizeof( WCHAR);
415
416         RtlCopyMemory( &AFSDumpFileLocation.Buffer[ AFSDumpFileLocation.Length/sizeof( WCHAR)],
417                        (void *)((char *)RedirInitInfo + RedirInitInfo->DumpFileLocationOffset),
418                        RedirInitInfo->DumpFileLocationLength);
419
420         AFSDumpFileLocation.Length += (USHORT)RedirInitInfo->DumpFileLocationLength;
421
422         //
423         // Be sure the shutdown flag is not set
424         //
425
426         ClearFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN);
427
428         //
429         // Set up the Throttles.
430         //
431         // Max IO is 10% of the cache, or the value in the registry,
432         // with a minimum of 5Mb (and a maximum of 50% cache size)
433         //
434         if( AFSMaxDirectIo)
435         {
436             //
437             // collect what the user
438             //
439             pDevExt->Specific.RDR.MaxIo.QuadPart = AFSMaxDirectIo;
440             pDevExt->Specific.RDR.MaxIo.QuadPart *= (1024 * 1024);
441
442         }
443         else
444         {
445
446             pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2;
447         }
448
449         if (pDevExt->Specific.RDR.MaxIo.QuadPart < (5 * 1024 * 1204))
450         {
451
452             pDevExt->Specific.RDR.MaxIo.QuadPart = 5 * 1024 * 1204;
453
454         }
455
456         //
457         // For small cache configurations ...
458         //
459
460         if (pDevExt->Specific.RDR.MaxIo.QuadPart > cacheSizeBytes.QuadPart / 2)
461         {
462
463             pDevExt->Specific.RDR.MaxIo.QuadPart  = cacheSizeBytes.QuadPart / 2;
464         }
465
466         //
467         // Maximum Dirty is 50% of the cache, or the value in the
468         // registry.  No minimum, maximum of 90% of cache size.
469         //
470         if (AFSMaxDirtyFile)
471         {
472
473             pDevExt->Specific.RDR.MaxDirty.QuadPart = AFSMaxDirtyFile;
474             pDevExt->Specific.RDR.MaxDirty.QuadPart *= (1024 * 1024);
475
476         }
477         else
478         {
479
480             pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart/2;
481
482         }
483
484         cacheSizeBytes.QuadPart *= 9;
485         cacheSizeBytes.QuadPart  = cacheSizeBytes.QuadPart / 10;
486
487         if (pDevExt->Specific.RDR.MaxDirty.QuadPart > cacheSizeBytes.QuadPart)
488         {
489             pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart;
490         }
491
492         //
493         // Store off any flags for the file system
494         //
495
496         if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES))
497         {
498
499             //
500             // Hide files which begin with .
501             //
502
503             SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES);
504         }
505
506         if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 &&
507             RedirInitInfo->MemoryCacheLength.QuadPart != 0)
508         {
509
510             ntStatus = STATUS_INSUFFICIENT_RESOURCES;
511
512 #ifdef AMD64
513             pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
514                                                           (void *)RedirInitInfo->MemoryCacheOffset.QuadPart,
515                                                           RedirInitInfo->MemoryCacheLength.QuadPart);
516 #else
517             pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
518                                                           (void *)RedirInitInfo->MemoryCacheOffset.LowPart,
519                                                           RedirInitInfo->MemoryCacheLength.LowPart);
520 #endif
521
522             if( pDevExt->Specific.RDR.CacheMdl != NULL)
523             {
524
525                 __try
526                 {
527
528                     MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl,
529                                          KernelMode,
530                                          IoModifyAccess);
531
532                     pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl,
533                                                                                            NormalPagePriority);
534                 }
535                 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
536                 {
537                     IoFreeMdl( pDevExt->Specific.RDR.CacheMdl);
538                     pDevExt->Specific.RDR.CacheMdl = NULL;
539                 }
540
541                 if( pDevExt->Specific.RDR.CacheMdl != NULL)
542                 {
543                     pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength;
544                     ntStatus = STATUS_SUCCESS;
545                 }
546
547             }
548         }
549
550         if( !NT_SUCCESS( ntStatus) &&
551             RedirInitInfo->CacheFileNameLength == 0)
552         {
553
554             AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
555                           AFS_TRACE_LEVEL_ERROR,
556                           "AFSInitializeRedirector Unable to initialize cache file %08lX\n",
557                           ntStatus);
558
559             try_return( ntStatus);
560         }
561
562         if( pDevExt->Specific.RDR.CacheMdl == NULL)
563         {
564
565             if( RedirInitInfo->CacheFileNameLength == 0)
566             {
567
568                 AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
569                               AFS_TRACE_LEVEL_ERROR,
570                               "AFSInitializeRedirector CacheMdl == NULL\n");
571
572                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
573             }
574
575             //
576             // Go open the cache file
577             //
578
579             pDevExt->Specific.RDR.CacheFile.Length = 0;
580             pDevExt->Specific.RDR.CacheFile.MaximumLength = (USHORT)RedirInitInfo->CacheFileNameLength + (4 * sizeof( WCHAR));
581
582             pDevExt->Specific.RDR.CacheFile.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
583                                                                                         pDevExt->Specific.RDR.CacheFile.MaximumLength,
584                                                                                         AFS_GENERIC_MEMORY_24_TAG);
585
586             if( pDevExt->Specific.RDR.CacheFile.Buffer == NULL)
587             {
588
589                 AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
590                               AFS_TRACE_LEVEL_ERROR,
591                               "AFSInitializeRedirector AFS_GENERIC_MEMORY_24_TAG allocation failure\n");
592
593                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
594             }
595
596             RtlCopyMemory( pDevExt->Specific.RDR.CacheFile.Buffer,
597                            L"\\??\\",
598                            4 * sizeof( WCHAR));
599
600             pDevExt->Specific.RDR.CacheFile.Length = 4 * sizeof( WCHAR);
601
602             RtlCopyMemory( &pDevExt->Specific.RDR.CacheFile.Buffer[ pDevExt->Specific.RDR.CacheFile.Length/sizeof( WCHAR)],
603                            RedirInitInfo->CacheFileName,
604                            RedirInitInfo->CacheFileNameLength);
605
606             pDevExt->Specific.RDR.CacheFile.Length += (USHORT)RedirInitInfo->CacheFileNameLength;
607
608             InitializeObjectAttributes( &stObjectAttribs,
609                                         &pDevExt->Specific.RDR.CacheFile,
610                                         OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
611                                         NULL,
612                                         NULL);
613
614             ntStatus = ZwOpenFile( &pDevExt->Specific.RDR.CacheFileHandle,
615                                    GENERIC_READ | GENERIC_WRITE,
616                                    &stObjectAttribs,
617                                    &stIoStatus,
618                                    FILE_SHARE_READ | FILE_SHARE_WRITE,
619                                    FILE_WRITE_THROUGH | FILE_RANDOM_ACCESS);
620
621             if( !NT_SUCCESS( ntStatus))
622             {
623
624                 AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
625                               AFS_TRACE_LEVEL_ERROR,
626                               "AFSInitializeRedirector ZwOpenFile failure %08lX\n",
627                               ntStatus);
628
629                 try_return( ntStatus);
630             }
631
632             //
633             // Map to the fileobject
634             //
635
636             ntStatus = ObReferenceObjectByHandle( pDevExt->Specific.RDR.CacheFileHandle,
637                                                   SYNCHRONIZE,
638                                                   NULL,
639                                                   KernelMode,
640                                                   (void **)&pDevExt->Specific.RDR.CacheFileObject,
641                                                   NULL);
642
643             if( !NT_SUCCESS( ntStatus))
644             {
645
646                 AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
647                               AFS_TRACE_LEVEL_ERROR,
648                               "AFSInitializeRedirector ObReferenceObjectByHandle failure %08lX\n",
649                               ntStatus);
650
651                 try_return( ntStatus);
652             }
653         }
654
655         pDevExt->Specific.RDR.MaxLinkCount = RedirInitInfo->MaxPathLinkCount;
656
657         pDevExt->Specific.RDR.NameArrayLength = RedirInitInfo->NameArrayLength;
658
659         //
660         // Intialize the library
661         //
662
663         ntStatus = AFSInitializeLibrary( &RedirInitInfo->GlobalFileId,
664                                          TRUE);
665
666         if ( !NT_SUCCESS( ntStatus))
667         {
668             AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
669                           AFS_TRACE_LEVEL_ERROR,
670                           "AFSInitializeRedirector AFSInitializeLibrary failure %08lX\n",
671                           ntStatus);
672         }
673
674 try_exit:
675
676         if( !NT_SUCCESS( ntStatus))
677         {
678
679             if( pDevExt->Specific.RDR.CacheMdl != NULL)
680             {
681
682                 MmUnmapLockedPages( pDevExt->Specific.RDR.CacheBaseAddress,
683                                     pDevExt->Specific.RDR.CacheMdl);
684
685                 MmUnlockPages( pDevExt->Specific.RDR.CacheMdl);
686
687                 ExFreePool( pDevExt->Specific.RDR.CacheMdl);
688
689                 pDevExt->Specific.RDR.CacheMdl = NULL;
690                 pDevExt->Specific.RDR.CacheBaseAddress = NULL;
691                 pDevExt->Specific.RDR.CacheLength.QuadPart = 0;
692             }
693
694             if( pDevExt->Specific.RDR.CacheFileHandle != NULL)
695             {
696
697                 ZwClose( pDevExt->Specific.RDR.CacheFileHandle);
698
699                 pDevExt->Specific.RDR.CacheFileHandle = NULL;
700             }
701
702             if( pDevExt->Specific.RDR.CacheFileObject != NULL)
703             {
704
705                 ObDereferenceObject( pDevExt->Specific.RDR.CacheFileObject);
706
707                 pDevExt->Specific.RDR.CacheFileObject = NULL;
708             }
709
710             if( pDevExt->Specific.RDR.CacheFile.Buffer != NULL)
711             {
712
713                 ExFreePool( pDevExt->Specific.RDR.CacheFile.Buffer);
714
715                 pDevExt->Specific.RDR.CacheFile.Buffer = NULL;
716             }
717
718             if( AFSDumpFileLocation.Buffer != NULL)
719             {
720                 ExFreePool( AFSDumpFileLocation.Buffer);
721
722                 AFSDumpFileLocation.Buffer = NULL;
723             }
724
725             if ( pDevExt->Fcb != NULL)
726             {
727
728                 AFSRemoveRdrFcb( &pDevExt->Fcb);
729
730                 pDevExt = NULL;
731             }
732
733             AFSUnloadLibrary( TRUE);
734         }
735     }
736
737     return ntStatus;
738 }
739
740 NTSTATUS
741 AFSCloseRedirector()
742 {
743
744     NTSTATUS ntStatus = STATUS_SUCCESS;
745     AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
746
747     __Enter
748     {
749
750         //
751         // Unload the library first so we close off any accesses to the cache or underlying
752         // shared memory
753         //
754
755         AFSUnloadLibrary( TRUE);
756
757         //
758         // Close off the cache file or mapping
759         //
760
761         if( pDevExt->Specific.RDR.CacheMdl != NULL)
762         {
763
764             MmUnmapLockedPages( pDevExt->Specific.RDR.CacheBaseAddress,
765                                 pDevExt->Specific.RDR.CacheMdl);
766
767             MmUnlockPages( pDevExt->Specific.RDR.CacheMdl);
768
769             ExFreePool( pDevExt->Specific.RDR.CacheMdl);
770
771             pDevExt->Specific.RDR.CacheMdl = NULL;
772             pDevExt->Specific.RDR.CacheBaseAddress = NULL;
773             pDevExt->Specific.RDR.CacheLength.QuadPart = 0;
774         }
775
776         if( pDevExt->Specific.RDR.CacheFileHandle != NULL)
777         {
778
779             ZwClose( pDevExt->Specific.RDR.CacheFileHandle);
780
781             pDevExt->Specific.RDR.CacheFileHandle = NULL;
782         }
783
784         if( pDevExt->Specific.RDR.CacheFileObject != NULL)
785         {
786
787             ObDereferenceObject( pDevExt->Specific.RDR.CacheFileObject);
788
789             pDevExt->Specific.RDR.CacheFileObject = NULL;
790         }
791
792         if( pDevExt->Specific.RDR.CacheFile.Buffer != NULL)
793         {
794
795             ExFreePool( pDevExt->Specific.RDR.CacheFile.Buffer);
796
797             pDevExt->Specific.RDR.CacheFile.Buffer = NULL;
798         }
799
800         if( AFSDumpFileLocation.Buffer != NULL)
801         {
802             ExFreePool( AFSDumpFileLocation.Buffer);
803
804             AFSDumpFileLocation.Buffer = NULL;
805         }
806
807         if ( pDevExt->Fcb != NULL)
808         {
809
810             AFSRemoveRdrFcb( &pDevExt->Fcb);
811
812             pDevExt->Fcb = NULL;
813         }
814
815     }
816
817     return ntStatus;
818 }
819
820 //
821 // Function: AFSInitRdrFcb
822 //
823 // Description:
824 //
825 //      This function performs Redirector Fcb initialization
826 //
827 // Return:
828 //
829 //      A status is returned for the function
830 //
831
832 NTSTATUS
833 AFSInitRdrFcb( OUT AFSFcb **RdrFcb)
834 {
835
836     NTSTATUS ntStatus = STATUS_SUCCESS;
837     AFSFcb *pFcb = NULL;
838     AFSNonPagedFcb *pNPFcb = NULL;
839     IO_STATUS_BLOCK stIoStatus = {0,0};
840     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
841
842     __Enter
843     {
844
845         //
846         // Initialize the root fcb
847         //
848
849         pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool,
850                                                    sizeof( AFSFcb),
851                                                    AFS_FCB_ALLOCATION_TAG);
852
853         if( pFcb == NULL)
854         {
855
856             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
857                           AFS_TRACE_LEVEL_ERROR,
858                           "AFSInitRdrFcb Failed to allocate the root fcb\n");
859
860             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
861         }
862
863         RtlZeroMemory( pFcb,
864                        sizeof( AFSFcb));
865
866         pFcb->Header.NodeByteSize = sizeof( AFSFcb);
867         pFcb->Header.NodeTypeCode = AFS_REDIRECTOR_FCB;
868
869         pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool,
870                                                              sizeof( AFSNonPagedFcb),
871                                                              AFS_FCB_NP_ALLOCATION_TAG);
872
873         if( pNPFcb == NULL)
874         {
875
876             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
877                           AFS_TRACE_LEVEL_ERROR,
878                           "AFSInitRdrFcb Failed to allocate the non-paged fcb\n");
879
880             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
881         }
882
883         RtlZeroMemory( pNPFcb,
884                        sizeof( AFSNonPagedFcb));
885
886         pNPFcb->Size = sizeof( AFSNonPagedFcb);
887
888         pNPFcb->Type = AFS_NON_PAGED_FCB;
889
890         //
891         // OK, initialize the entry
892         //
893
894         ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex);
895
896         FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex);
897
898         ExInitializeResourceLite( &pNPFcb->Resource);
899
900         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
901                       AFS_TRACE_LEVEL_VERBOSE,
902                       "AFSInitRootFcb Acquiring Fcb lock %08lX EXCL %08lX\n",
903                       &pNPFcb->Resource,
904                       PsGetCurrentThread());
905
906         ExInitializeResourceLite( &pNPFcb->PagingResource);
907
908         pFcb->Header.Resource = &pNPFcb->Resource;
909
910         pFcb->Header.PagingIoResource = &pNPFcb->PagingResource;
911
912         pFcb->NPFcb = pNPFcb;
913
914         if ( InterlockedCompareExchangePointer( (PVOID *)RdrFcb, pFcb, NULL) != NULL)
915         {
916
917             try_return( ntStatus = STATUS_REPARSE);
918         }
919
920 try_exit:
921
922         if( ntStatus != STATUS_SUCCESS)
923         {
924
925             if( pFcb != NULL)
926             {
927
928                 AFSRemoveRdrFcb( &pFcb);
929             }
930         }
931     }
932
933     return ntStatus;
934 }
935
936 //
937 // Function: AFSRemoveRdrFcb
938 //
939 // Description:
940 //
941 //      This function performs Redirector Fcb removal/deallocation
942 //
943 // Return:
944 //
945 //      void.
946 //
947
948 void
949 AFSRemoveRdrFcb( IN OUT AFSFcb **RdrFcb)
950 {
951     AFSFcb *pFcb = NULL;
952
953     pFcb = (AFSFcb *) InterlockedCompareExchangePointer( (PVOID *)RdrFcb, NULL, (PVOID)(*RdrFcb));
954
955     if ( pFcb == NULL)
956     {
957
958         return;
959     }
960
961     if( pFcb->NPFcb != NULL)
962     {
963
964         //
965         // Now the resource
966         //
967
968         ExDeleteResourceLite( &pFcb->NPFcb->Resource);
969
970         ExDeleteResourceLite( &pFcb->NPFcb->PagingResource);
971
972         //
973         // The non paged region
974         //
975
976         AFSExFreePool( pFcb->NPFcb);
977     }
978
979     //
980     // And the Fcb itself
981     //
982
983     AFSExFreePool( pFcb);
984
985     return;
986 }