Windows: AFSRedirLib.sys file system library driver
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSFSControl.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: AFSFSControl.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 NTSTATUS
42 AFSFSControl( IN PDEVICE_OBJECT LibDeviceObject,
43               IN PIRP Irp)
44 {
45
46     NTSTATUS ntStatus = STATUS_SUCCESS;
47     IO_STACK_LOCATION *pIrpSp;
48
49     pIrpSp = IoGetCurrentIrpStackLocation( Irp);
50
51     __try
52     {
53
54         switch( pIrpSp->MinorFunction)
55         {
56
57             case IRP_MN_USER_FS_REQUEST:
58
59                 ntStatus = AFSProcessUserFsRequest( Irp);
60
61                 break;
62
63             case IRP_MN_MOUNT_VOLUME:
64
65                 break;
66
67             case IRP_MN_VERIFY_VOLUME:
68
69                 break;
70
71             default:
72
73                 break;
74         }
75
76         AFSCompleteRequest( Irp,
77                               ntStatus);
78
79     }
80     __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
81     {
82
83         AFSDbgLogMsg( 0,
84                       0,
85                       "EXCEPTION - AFSFSControl\n");
86     }
87
88     return ntStatus;
89 }
90
91 static BOOLEAN
92 AFSParseMountPointTarget( IN  UNICODE_STRING *Target,
93                           OUT USHORT         *Type,
94                           OUT UNICODE_STRING *Volume,
95                           OUT UNICODE_STRING *Cell)
96 {
97     // Targets are of the form <type>[<cell>:]<volume>
98
99     *Type = Target->Buffer[ 0];
100
101     // Extract the cell name (if any)
102
103     Cell->Buffer = &Target->Buffer[ 1];
104
105     // Search for colon separator or end of counted string
106
107     for ( Cell->Length = 0; Cell->Length < Target->Length - sizeof( WCHAR); Cell->Length += sizeof( WCHAR))
108     {
109
110         if ( Cell->Buffer[ Cell->Length / sizeof( WCHAR)] == L':')
111         {
112             break;
113         }
114     }
115
116     // If a colon is not found, it means there is no cell
117
118     if ( Cell->Buffer[ Cell->Length / sizeof( WCHAR)] == L':')
119     {
120
121         Cell->MaximumLength = Cell->Length;
122
123         if ( Cell->Length > Target->Length - 2 * sizeof( WCHAR))
124         {
125             // Invalid target string if there is no room for
126             // the volume name.
127
128             return FALSE;
129         }
130
131         Volume->Length = Volume->MaximumLength = (Target->Length - Cell->Length - 2 * sizeof( WCHAR));
132
133         Volume->Buffer = &Target->Buffer[ Cell->Length / sizeof( WCHAR) + 2];
134     }
135     else
136     {
137         // There is no cell
138
139         Volume->Length = Volume->MaximumLength = Cell->Length;
140
141         Volume->Buffer = Cell->Buffer;
142
143         Cell->Length = Cell->MaximumLength = 0;
144
145         Cell->Buffer = NULL;
146     }
147
148     return TRUE;
149 }
150
151 NTSTATUS
152 AFSProcessUserFsRequest( IN PIRP Irp)
153 {
154
155     NTSTATUS ntStatus = STATUS_SUCCESS;
156     ULONG ulFsControlCode;
157     AFSFcb *pFcb = NULL;
158     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp );
159     AFSCcb *pCcb = NULL;
160     ULONG ulOutputBufferLen, ulInputBufferLen;
161
162     __Enter
163     {
164
165         ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode;
166
167         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
168
169         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
170
171         if( pFcb == NULL ||
172             pCcb->DirectoryCB == NULL)
173         {
174
175             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
176                           AFS_TRACE_LEVEL_VERBOSE_2,
177                           "AFSProcessUserFsRequest Invalid Fcb\n");
178
179             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
180         }
181
182         if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
183         {
184
185             ntStatus = AFSProcessShareFsCtrl( Irp,
186                                               pFcb,
187                                               pCcb);
188
189             try_return( ntStatus);
190         }
191
192         ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength;
193         ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength;
194
195         //
196         // Process the request
197         //
198
199         switch( ulFsControlCode )
200         {
201
202             case FSCTL_REQUEST_OPLOCK_LEVEL_1:
203             case FSCTL_REQUEST_OPLOCK_LEVEL_2:
204             case FSCTL_REQUEST_BATCH_OPLOCK:
205             case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
206             case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
207             case FSCTL_OPLOCK_BREAK_NOTIFY:
208             case FSCTL_OPLOCK_BREAK_ACK_NO_2:
209             case FSCTL_REQUEST_FILTER_OPLOCK :
210
211                 //
212                 // Note that implementing this call will probably need us
213                 // to call the server as well as adding code in read and
214                 // write and caching.  Also that it is unlikely that
215                 // anyone will ever call us at this point - RDR doesn't
216                 // allow it
217                 //
218
219                 ntStatus = STATUS_NOT_IMPLEMENTED;
220
221                 break;
222
223             case FSCTL_LOCK_VOLUME:
224
225                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
226                               AFS_TRACE_LEVEL_VERBOSE_2,
227                               "AFSProcessUserFsRequest Processing FSCTL_LOCK_VOLUME request\n");
228
229                 break;
230
231             case FSCTL_UNLOCK_VOLUME:
232
233                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
234                               AFS_TRACE_LEVEL_VERBOSE_2,
235                               "AFSProcessUserFsRequest Processing FSCTL_UNLOCK_VOLUME request\n");
236
237                 break;
238
239             case FSCTL_DISMOUNT_VOLUME:
240
241                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
242                               AFS_TRACE_LEVEL_VERBOSE_2,
243                               "AFSProcessUserFsRequest Processing FSCTL_DISMOUNT_VOLUME request\n");
244
245                 break;
246
247             case FSCTL_MARK_VOLUME_DIRTY:
248
249                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
250                               AFS_TRACE_LEVEL_VERBOSE_2,
251                               "AFSProcessUserFsRequest Processing FSCTL_MARK_VOLUME_DIRTY request\n");
252
253                 break;
254
255             case FSCTL_IS_VOLUME_DIRTY:
256
257                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
258                               AFS_TRACE_LEVEL_VERBOSE_2,
259                               "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_DIRTY request\n");
260
261                 break;
262
263             case FSCTL_IS_VOLUME_MOUNTED:
264
265                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
266                               AFS_TRACE_LEVEL_VERBOSE_2,
267                               "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_MOUNTED request\n");
268
269                 break;
270
271             case FSCTL_IS_PATHNAME_VALID:
272
273                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
274                               AFS_TRACE_LEVEL_VERBOSE_2,
275                               "AFSProcessUserFsRequest Processing FSCTL_IS_PATHNAME_VALID request\n");
276
277                 break;
278
279             case FSCTL_GET_REPARSE_POINT:
280             {
281
282                 REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
283                 ULONG ulRemainingLen = ulOutputBufferLen;
284                 AFSReparseTagInfo *pReparseInfo = NULL;
285
286                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
287                               AFS_TRACE_LEVEL_VERBOSE_2,
288                               "AFSProcessUserFsRequest Processing FSCTL_GET_REPARSE_POINT request\n");
289
290                 if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
291                 {
292
293                     ntStatus = STATUS_BUFFER_TOO_SMALL;
294
295                     Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
296
297                     break;
298                 }
299
300                 ulRemainingLen -= FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
301
302                 //
303                 // Check if we have the reparse entry set on the entry
304                 //
305
306                 if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
307                 {
308
309                     ntStatus = STATUS_NOT_A_REPARSE_POINT;
310
311                     break;
312                 }
313
314                 //
315                 // Populate the data in the reparse buffer
316                 //
317
318                 pReparseBuffer->ReparseDataLength  = 0;
319
320                 AFSAcquireExcl( &pCcb->DirectoryCB->NonPaged->Lock,
321                                 TRUE);
322
323                 if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
324                 {
325
326                     //
327                     // We'll reset the DV to ensure we validate the metadata content
328                     //
329
330                     pCcb->DirectoryCB->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
331
332                     SetFlag( pCcb->DirectoryCB->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
333
334                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
335                                   AFS_TRACE_LEVEL_VERBOSE,
336                                   "AFSProcessUserFsRequest Verifying symlink %wZ FID %08lX-%08lX-%08lX-%08lX\n",
337                                   &pCcb->DirectoryCB->NameInformation.FileName,
338                                   pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
339                                   pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
340                                   pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
341                                   pCcb->DirectoryCB->ObjectInformation->FileId.Unique);
342
343                     ntStatus = AFSVerifyEntry( &pFcb->AuthGroup,
344                                                pCcb->DirectoryCB);
345
346                     if( !NT_SUCCESS( ntStatus))
347                     {
348
349                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
350                                       AFS_TRACE_LEVEL_ERROR,
351                                       "AFSProcessUserFsRequest Failed to verify symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
352                                       &pCcb->DirectoryCB->NameInformation.FileName,
353                                       pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
354                                       pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
355                                       pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
356                                       pCcb->DirectoryCB->ObjectInformation->FileId.Unique,
357                                       ntStatus);
358
359                         AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);
360
361                         break;
362                     }
363                 }
364
365                 pReparseInfo = (AFSReparseTagInfo *)&pReparseBuffer->GenericReparseBuffer.DataBuffer[ 0];
366
367                 switch( pCcb->DirectoryCB->ObjectInformation->FileType)
368                 {
369
370                     case AFS_FILE_TYPE_SYMLINK:
371                     {
372
373                         if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
374                         {
375
376                             ntStatus = STATUS_ACCESS_DENIED;
377
378                             break;
379                         }
380
381                         if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length)
382                         {
383
384                             ntStatus = STATUS_BUFFER_TOO_SMALL;
385
386                             Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
387                                                         FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) +
388                                                         pCcb->DirectoryCB->NameInformation.TargetName.Length;
389
390                             break;
391                         }
392
393                         pReparseInfo->SubTag = OPENAFS_SUBTAG_SYMLINK;
394
395                         pReparseInfo->AFSSymLink.RelativeLink = AFSIsRelativeName( &pCcb->DirectoryCB->NameInformation.TargetName);
396
397                         pReparseInfo->AFSSymLink.SymLinkTargetLength = pCcb->DirectoryCB->NameInformation.TargetName.Length;
398
399                         RtlCopyMemory( pReparseInfo->AFSSymLink.Buffer,
400                                        pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
401                                        pCcb->DirectoryCB->NameInformation.TargetName.Length);
402
403                         pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length);
404
405                         break;
406                     }
407
408                     case AFS_FILE_TYPE_MOUNTPOINT:
409                     {
410                         UNICODE_STRING Cell, Volume;
411                         USHORT Type;
412
413                         if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
414                         {
415                             ntStatus = STATUS_ACCESS_DENIED;
416
417                             break;
418                         }
419
420                         if ( !AFSParseMountPointTarget( &pCcb->DirectoryCB->NameInformation.TargetName,
421                                                         &Type,
422                                                         &Volume,
423                                                         &Cell))
424                         {
425                             ntStatus = STATUS_INVALID_PARAMETER;
426
427                             break;
428                         }
429
430                         if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length)
431                         {
432
433                             ntStatus = STATUS_BUFFER_TOO_SMALL;
434
435                             Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
436                                                         FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) +
437                                                         Volume.Length + Cell.Length;
438
439                             break;
440                         }
441
442                         pReparseInfo->SubTag = OPENAFS_SUBTAG_MOUNTPOINT;
443
444                         pReparseInfo->AFSMountPoint.Type = Type;
445
446                         pReparseInfo->AFSMountPoint.MountPointCellLength = Cell.Length;
447
448                         pReparseInfo->AFSMountPoint.MountPointVolumeLength = Volume.Length;
449
450                         RtlCopyMemory( pReparseInfo->AFSMountPoint.Buffer,
451                                        Cell.Buffer,
452                                        Cell.Length);
453
454                         RtlCopyMemory( &pReparseInfo->AFSMountPoint.Buffer[ Cell.Length / sizeof( WCHAR)],
455                                        Volume.Buffer,
456                                        Volume.Length);
457
458                         pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length);
459
460                         break;
461                     }
462
463                     case AFS_FILE_TYPE_DFSLINK:
464                     {
465
466                         if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
467                         {
468
469                             ntStatus = STATUS_ACCESS_DENIED;
470
471                             break;
472                         }
473
474                         if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length)
475                         {
476
477                             ntStatus = STATUS_BUFFER_TOO_SMALL;
478
479                             Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
480                                                         FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) +
481                                                         pCcb->DirectoryCB->NameInformation.TargetName.Length;
482
483                             break;
484                         }
485
486                         pReparseInfo->SubTag = OPENAFS_SUBTAG_UNC;
487
488                         pReparseInfo->UNCReferral.UNCTargetLength = pCcb->DirectoryCB->NameInformation.TargetName.Length;
489
490                         RtlCopyMemory( pReparseInfo->UNCReferral.Buffer,
491                                        pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
492                                        pCcb->DirectoryCB->NameInformation.TargetName.Length);
493
494                         pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length);
495
496                         break;
497                     }
498
499                     default:
500
501                         ntStatus = STATUS_NOT_A_REPARSE_POINT;
502
503                         break;
504                 }
505
506                 if ( ntStatus == STATUS_SUCCESS)
507                 {
508
509                     ulRemainingLen -= pReparseBuffer->ReparseDataLength;
510
511                     pReparseBuffer->ReparseTag = IO_REPARSE_TAG_OPENAFS_DFS;
512
513                     RtlCopyMemory( &pReparseBuffer->ReparseGuid,
514                                    &GUID_AFS_REPARSE_GUID,
515                                    sizeof( GUID));
516
517                     Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
518                                                               pReparseBuffer->ReparseDataLength;
519                 }
520
521                 AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);
522
523                 break;
524             }
525
526             case FSCTL_SET_REPARSE_POINT:
527             {
528
529                 REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
530
531                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
532                               AFS_TRACE_LEVEL_VERBOSE_2,
533                               "AFSProcessUserFsRequest Processing FSCTL_SET_REPARSE_POINT request\n");
534
535                 if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
536                 {
537
538                     ntStatus = STATUS_INVALID_PARAMETER;
539
540                     break;
541                 }
542
543                 //
544                 // Check if we have the reparse entry set on the entry
545                 //
546
547                 if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
548                 {
549
550                     ntStatus = STATUS_NOT_A_REPARSE_POINT;
551
552                     break;
553                 }
554
555                 if( pReparseBuffer->ReparseTag != IO_REPARSE_TAG_OPENAFS_DFS)
556                 {
557
558                     ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH;
559
560                     break;
561                 }
562
563                 if( RtlCompareMemory( &pReparseBuffer->ReparseGuid,
564                                       &GUID_AFS_REPARSE_GUID,
565                                       sizeof( GUID)) != sizeof( GUID))
566                 {
567
568                     ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;
569
570                     break;
571                 }
572
573                 //
574                 // For now deny access on this call
575                 //
576
577                 break;
578             }
579
580             case FSCTL_DELETE_REPARSE_POINT:
581             {
582
583                 REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
584
585                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
586                               AFS_TRACE_LEVEL_VERBOSE_2,
587                               "AFSProcessUserFsRequest Processing FSCTL_DELETE_REPARSE_POINT request\n");
588
589                 if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
590                 {
591
592                     ntStatus = STATUS_INVALID_PARAMETER;
593
594                     break;
595                 }
596
597                 //
598                 // Check if we have the reparse entry set on the entry
599                 //
600
601                 if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
602                 {
603
604                     ntStatus = STATUS_NOT_A_REPARSE_POINT;
605
606                     break;
607                 }
608
609                 if( pReparseBuffer->ReparseTag != IO_REPARSE_TAG_OPENAFS_DFS)
610                 {
611
612                     ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH;
613
614                     break;
615                 }
616
617                 if( RtlCompareMemory( &pReparseBuffer->ReparseGuid,
618                                       &GUID_AFS_REPARSE_GUID,
619                                       sizeof( GUID)) != sizeof( GUID))
620                 {
621
622                     ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;
623
624                     break;
625                 }
626
627                 //
628                 // For now deny access on this call
629                 //
630
631                 ntStatus = STATUS_ACCESS_DENIED;
632
633                 break;
634             }
635
636             default :
637
638                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
639                               AFS_TRACE_LEVEL_VERBOSE_2,
640                               "AFSProcessUserFsRequest Processing default (%08lX) request\n", ulFsControlCode);
641
642                 ntStatus = STATUS_INVALID_PARAMETER;
643
644                 break;
645         }
646
647 try_exit:
648
649         NOTHING;
650     }
651
652     return ntStatus;
653 }
654
655 NTSTATUS
656 AFSProcessShareFsCtrl( IN IRP *Irp,
657                        IN AFSFcb *Fcb,
658                        IN AFSCcb *Ccb)
659 {
660
661     NTSTATUS ntStatus = STATUS_SUCCESS;
662     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
663     ULONG ulOutputBufferLen = 0, ulInputBufferLen;
664     ULONG ulFsControlCode;
665
666     __Enter
667     {
668
669         ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode;
670
671         ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength;
672         ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength;
673
674         switch( ulFsControlCode)
675         {
676
677             case FSCTL_PIPE_TRANSCEIVE:
678             {
679
680                 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
681                               AFS_TRACE_LEVEL_VERBOSE,
682                               "AFSProcessShareFsCtrl On pipe %wZ Class FSCTL_PIPE_TRANSCEIVE\n",
683                               &Ccb->DirectoryCB->NameInformation.FileName);
684
685                 ntStatus = AFSNotifyPipeTransceive( Ccb,
686                                                     ulInputBufferLen,
687                                                     ulOutputBufferLen,
688                                                     pIrpSp->Parameters.FileSystemControl.Type3InputBuffer,
689                                                     Irp->UserBuffer,
690                                                     (ULONG *)&Irp->IoStatus.Information);
691
692                 if( !NT_SUCCESS( ntStatus))
693                 {
694
695                     AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
696                                   AFS_TRACE_LEVEL_VERBOSE,
697                                   "AFSProcessShareFsCtrl Failure on pipe %wZ Class FSCTL_PIPE_TRANSCEIVE Status %08lX\n",
698                                   &Ccb->DirectoryCB->NameInformation.FileName,
699                                   ntStatus);
700                 }
701
702                 break;
703             }
704
705             default:
706             {
707
708                 if( BooleanFlagOn( Ccb->DirectoryCB->Flags, AFS_DIR_ENTRY_SERVER_SERVICE))
709                 {
710
711                     //AFSPrint("AFSProcessShareFsCtrl (%08lX) For srvsvc input %08lX output %08lX\n",
712                     //                                                            ulFsControlCode,
713                     //                                                            ulInputBufferLen,
714                     //                                                            ulOutputBufferLen);
715                 }
716                 else if( BooleanFlagOn( Ccb->DirectoryCB->Flags, AFS_DIR_ENTRY_WORKSTATION_SERVICE))
717                 {
718
719                     //AFSPrint("AFSProcessShareFsCtrl (%08lX) For wkssvc input %08lX output %08lX\n",
720                     //                                                            ulFsControlCode,
721                     //                                                            ulInputBufferLen,
722                     //                                                            ulOutputBufferLen);
723                 }
724                 else
725                 {
726
727                     //AFSPrint("AFSProcessShareFsCtrl (%08lX) For IPC$ input %08lX output %08lX\n",
728                     //                                                            ulFsControlCode,
729                     //                                                            ulInputBufferLen,
730                     //                                                            ulOutputBufferLen);
731                 }
732
733                 break;
734             }
735         }
736     }
737
738     return ntStatus;
739 }