2354043810e36de0834fb88e977e4f131c32440b
[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
224             case FSCTL_LOCK_VOLUME:
225             {
226                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
227                               AFS_TRACE_LEVEL_VERBOSE_2,
228                               "AFSProcessUserFsRequest Processing FSCTL_LOCK_VOLUME request\n");
229
230                 ntStatus = STATUS_NOT_IMPLEMENTED;
231
232                 break;
233             }
234
235             case FSCTL_UNLOCK_VOLUME:
236             {
237                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
238                               AFS_TRACE_LEVEL_VERBOSE_2,
239                               "AFSProcessUserFsRequest Processing FSCTL_UNLOCK_VOLUME request\n");
240
241                 ntStatus = STATUS_NOT_IMPLEMENTED;
242
243                 break;
244             }
245
246             case FSCTL_DISMOUNT_VOLUME:
247             {
248                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
249                               AFS_TRACE_LEVEL_VERBOSE_2,
250                               "AFSProcessUserFsRequest Processing FSCTL_DISMOUNT_VOLUME request\n");
251
252                 ntStatus = STATUS_NOT_IMPLEMENTED;
253
254                 break;
255             }
256
257             case FSCTL_MARK_VOLUME_DIRTY:
258             {
259                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
260                               AFS_TRACE_LEVEL_VERBOSE_2,
261                               "AFSProcessUserFsRequest Processing FSCTL_MARK_VOLUME_DIRTY request\n");
262
263                 ntStatus = STATUS_NOT_IMPLEMENTED;
264
265                 break;
266             }
267
268             case FSCTL_IS_VOLUME_DIRTY:
269             {
270                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
271                               AFS_TRACE_LEVEL_VERBOSE_2,
272                               "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_DIRTY request\n");
273
274                 ntStatus = STATUS_NOT_IMPLEMENTED;
275
276                 break;
277             }
278
279             case FSCTL_IS_VOLUME_MOUNTED:
280             {
281                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
282                               AFS_TRACE_LEVEL_VERBOSE_2,
283                               "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_MOUNTED request\n");
284
285                 ntStatus = STATUS_NOT_IMPLEMENTED;
286
287                 break;
288             }
289
290             case FSCTL_IS_PATHNAME_VALID:
291             {
292                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
293                               AFS_TRACE_LEVEL_VERBOSE_2,
294                               "AFSProcessUserFsRequest Processing FSCTL_IS_PATHNAME_VALID request\n");
295
296                 ntStatus = STATUS_SUCCESS;
297
298                 break;
299             }
300
301 #ifndef FSCTL_CSC_INTERNAL
302 #define FSCTL_CSC_INTERNAL                  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 107, METHOD_NEITHER, FILE_ANY_ACCESS)
303 #endif
304             case FSCTL_CSC_INTERNAL:
305             {
306                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
307                               AFS_TRACE_LEVEL_VERBOSE_2,
308                               "AFSProcessUserFsRequest Processing FSCTL_CSC_INTERNAL request\n");
309
310                 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
311
312                 break;
313             }
314
315             case FSCTL_GET_REPARSE_POINT:
316             {
317
318                 REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
319                 ULONG ulRemainingLen = ulOutputBufferLen;
320                 AFSReparseTagInfo *pReparseInfo = NULL;
321
322                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
323                               AFS_TRACE_LEVEL_VERBOSE_2,
324                               "AFSProcessUserFsRequest Processing FSCTL_GET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
325                               &pCcb->DirectoryCB->NameInformation.FileName,
326                               pCcb->DirectoryCB->ObjectInformation->FileType,
327                               pCcb->DirectoryCB->ObjectInformation->FileAttributes);
328
329                 //
330                 // Check if we have the reparse entry set on the entry
331                 //
332
333                 if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
334                 {
335
336                     ntStatus = STATUS_NOT_A_REPARSE_POINT;
337
338                     break;
339                 }
340
341                 if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
342                 {
343
344                     ntStatus = STATUS_BUFFER_TOO_SMALL;
345
346                     Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
347
348                     break;
349                 }
350
351                 ulRemainingLen -= FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
352
353                 //
354                 // Populate the data in the reparse buffer
355                 //
356
357                 pReparseBuffer->ReparseDataLength  = 0;
358
359                 AFSAcquireExcl( &pCcb->DirectoryCB->NonPaged->Lock,
360                                 TRUE);
361
362                 if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
363                 {
364
365                     //
366                     // We'll reset the DV to ensure we validate the metadata content
367                     //
368
369                     pCcb->DirectoryCB->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
370
371                     SetFlag( pCcb->DirectoryCB->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
372
373                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
374                                   AFS_TRACE_LEVEL_VERBOSE,
375                                   "AFSProcessUserFsRequest Verifying symlink %wZ FID %08lX-%08lX-%08lX-%08lX\n",
376                                   &pCcb->DirectoryCB->NameInformation.FileName,
377                                   pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
378                                   pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
379                                   pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
380                                   pCcb->DirectoryCB->ObjectInformation->FileId.Unique);
381
382                     ntStatus = AFSVerifyEntry( &pCcb->AuthGroup,
383                                                pCcb->DirectoryCB);
384
385                     if( !NT_SUCCESS( ntStatus))
386                     {
387
388                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
389                                       AFS_TRACE_LEVEL_ERROR,
390                                       "AFSProcessUserFsRequest Failed to verify symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
391                                       &pCcb->DirectoryCB->NameInformation.FileName,
392                                       pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
393                                       pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
394                                       pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
395                                       pCcb->DirectoryCB->ObjectInformation->FileId.Unique,
396                                       ntStatus);
397
398                         AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);
399
400                         break;
401                     }
402                 }
403
404                 pReparseInfo = (AFSReparseTagInfo *)&pReparseBuffer->GenericReparseBuffer.DataBuffer[ 0];
405
406                 switch( pCcb->DirectoryCB->ObjectInformation->FileType)
407                 {
408
409                     case AFS_FILE_TYPE_SYMLINK:
410                     {
411
412                         if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
413                         {
414
415                             ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
416
417                             break;
418                         }
419
420                         if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length)
421                         {
422
423                             ntStatus = STATUS_BUFFER_TOO_SMALL;
424
425                             Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
426                                                         FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) +
427                                                         pCcb->DirectoryCB->NameInformation.TargetName.Length;
428
429                             break;
430                         }
431
432                         pReparseInfo->SubTag = OPENAFS_SUBTAG_SYMLINK;
433
434                         pReparseInfo->AFSSymLink.RelativeLink = AFSIsRelativeName( &pCcb->DirectoryCB->NameInformation.TargetName);
435
436                         pReparseInfo->AFSSymLink.SymLinkTargetLength = pCcb->DirectoryCB->NameInformation.TargetName.Length;
437
438                         RtlCopyMemory( pReparseInfo->AFSSymLink.Buffer,
439                                        pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
440                                        pCcb->DirectoryCB->NameInformation.TargetName.Length);
441
442                         pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length);
443
444                         break;
445                     }
446
447                     case AFS_FILE_TYPE_MOUNTPOINT:
448                     {
449                         UNICODE_STRING Cell, Volume;
450                         USHORT Type;
451
452                         if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
453                         {
454                             ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
455
456                             break;
457                         }
458
459                         if ( !AFSParseMountPointTarget( &pCcb->DirectoryCB->NameInformation.TargetName,
460                                                         &Type,
461                                                         &Volume,
462                                                         &Cell))
463                         {
464                             ntStatus = STATUS_INVALID_PARAMETER;
465
466                             break;
467                         }
468
469                         if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length)
470                         {
471
472                             ntStatus = STATUS_BUFFER_TOO_SMALL;
473
474                             Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
475                                                         FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) +
476                                                         Volume.Length + Cell.Length;
477
478                             break;
479                         }
480
481                         pReparseInfo->SubTag = OPENAFS_SUBTAG_MOUNTPOINT;
482
483                         pReparseInfo->AFSMountPoint.Type = Type;
484
485                         pReparseInfo->AFSMountPoint.MountPointCellLength = Cell.Length;
486
487                         pReparseInfo->AFSMountPoint.MountPointVolumeLength = Volume.Length;
488
489                         RtlCopyMemory( pReparseInfo->AFSMountPoint.Buffer,
490                                        Cell.Buffer,
491                                        Cell.Length);
492
493                         RtlCopyMemory( &pReparseInfo->AFSMountPoint.Buffer[ Cell.Length / sizeof( WCHAR)],
494                                        Volume.Buffer,
495                                        Volume.Length);
496
497                         pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length);
498
499                         break;
500                     }
501
502                     case AFS_FILE_TYPE_DFSLINK:
503                     {
504
505                         if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
506                         {
507
508                             ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
509
510                             break;
511                         }
512
513                         if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length)
514                         {
515
516                             ntStatus = STATUS_BUFFER_TOO_SMALL;
517
518                             Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
519                                                         FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) +
520                                                         pCcb->DirectoryCB->NameInformation.TargetName.Length;
521
522                             break;
523                         }
524
525                         pReparseInfo->SubTag = OPENAFS_SUBTAG_UNC;
526
527                         pReparseInfo->UNCReferral.UNCTargetLength = pCcb->DirectoryCB->NameInformation.TargetName.Length;
528
529                         RtlCopyMemory( pReparseInfo->UNCReferral.Buffer,
530                                        pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
531                                        pCcb->DirectoryCB->NameInformation.TargetName.Length);
532
533                         pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length);
534
535                         break;
536                     }
537
538                     default:
539
540                         ntStatus = STATUS_NOT_A_REPARSE_POINT;
541
542                         break;
543                 }
544
545                 if ( ntStatus == STATUS_SUCCESS)
546                 {
547
548                     ulRemainingLen -= pReparseBuffer->ReparseDataLength;
549
550                     pReparseBuffer->ReparseTag = IO_REPARSE_TAG_OPENAFS_DFS;
551
552                     RtlCopyMemory( &pReparseBuffer->ReparseGuid,
553                                    &GUID_AFS_REPARSE_GUID,
554                                    sizeof( GUID));
555
556                     Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
557                                                               pReparseBuffer->ReparseDataLength;
558                 }
559
560                 AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);
561
562                 break;
563             }
564
565             case FSCTL_SET_REPARSE_POINT:
566             {
567
568                 REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
569
570                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
571                               AFS_TRACE_LEVEL_VERBOSE_2,
572                               "AFSProcessUserFsRequest Processing FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
573                               &pCcb->DirectoryCB->NameInformation.FileName,
574                               pCcb->DirectoryCB->ObjectInformation->FileType,
575                               pCcb->DirectoryCB->ObjectInformation->FileAttributes);
576
577                 //
578                 // Check if we have the reparse entry set on the entry
579                 //
580
581                 if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
582                 {
583
584                     ntStatus = STATUS_NOT_A_REPARSE_POINT;
585
586                     break;
587                 }
588
589                 if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
590                 {
591
592                     ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
593
594                     break;
595                 }
596
597                 if( pReparseBuffer->ReparseTag != IO_REPARSE_TAG_OPENAFS_DFS)
598                 {
599
600                     ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH;
601
602                     break;
603                 }
604
605                 if( RtlCompareMemory( &pReparseBuffer->ReparseGuid,
606                                       &GUID_AFS_REPARSE_GUID,
607                                       sizeof( GUID)) != sizeof( GUID))
608                 {
609
610                     ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;
611
612                     break;
613                 }
614
615                 //
616                 // For now deny access on this call
617                 //
618
619                 ntStatus = STATUS_INVALID_PARAMETER;
620
621                 break;
622             }
623
624             case FSCTL_DELETE_REPARSE_POINT:
625             {
626
627                 REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
628
629                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
630                               AFS_TRACE_LEVEL_VERBOSE_2,
631                               "AFSProcessUserFsRequest Processing FSCTL_DELETE_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
632                               &pCcb->DirectoryCB->NameInformation.FileName,
633                               pCcb->DirectoryCB->ObjectInformation->FileType,
634                               pCcb->DirectoryCB->ObjectInformation->FileAttributes);
635
636                 //
637                 // Check if we have the reparse entry set on the entry
638                 //
639
640                 if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
641                 {
642
643                     ntStatus = STATUS_NOT_A_REPARSE_POINT;
644
645                     break;
646                 }
647
648                 if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
649                 {
650
651                     ntStatus = STATUS_INVALID_PARAMETER;
652
653                     break;
654                 }
655
656                 if( pReparseBuffer->ReparseTag != IO_REPARSE_TAG_OPENAFS_DFS)
657                 {
658
659                     ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH;
660
661                     break;
662                 }
663
664                 if( RtlCompareMemory( &pReparseBuffer->ReparseGuid,
665                                       &GUID_AFS_REPARSE_GUID,
666                                       sizeof( GUID)) != sizeof( GUID))
667                 {
668
669                     ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;
670
671                     break;
672                 }
673
674                 //
675                 // For now deny access on this call
676                 //
677
678                 ntStatus = STATUS_ACCESS_DENIED;
679
680                 break;
681             }
682
683             default :
684
685                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
686                               AFS_TRACE_LEVEL_VERBOSE_2,
687                               "AFSProcessUserFsRequest Processing default (%08lX) request\n", ulFsControlCode);
688
689                 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
690
691                 break;
692         }
693
694 try_exit:
695
696         NOTHING;
697     }
698
699     return ntStatus;
700 }
701
702 NTSTATUS
703 AFSProcessShareFsCtrl( IN IRP *Irp,
704                        IN AFSFcb *Fcb,
705                        IN AFSCcb *Ccb)
706 {
707
708     NTSTATUS ntStatus = STATUS_SUCCESS;
709     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
710     ULONG ulOutputBufferLen = 0, ulInputBufferLen;
711     ULONG ulFsControlCode;
712
713     __Enter
714     {
715
716         ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode;
717
718         ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength;
719         ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength;
720
721         switch( ulFsControlCode)
722         {
723
724             case FSCTL_PIPE_TRANSCEIVE:
725             {
726
727                 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
728                               AFS_TRACE_LEVEL_VERBOSE,
729                               "AFSProcessShareFsCtrl On pipe %wZ Class FSCTL_PIPE_TRANSCEIVE\n",
730                               &Ccb->DirectoryCB->NameInformation.FileName);
731
732                 ntStatus = AFSNotifyPipeTransceive( Ccb,
733                                                     ulInputBufferLen,
734                                                     ulOutputBufferLen,
735                                                     pIrpSp->Parameters.FileSystemControl.Type3InputBuffer,
736                                                     Irp->UserBuffer,
737                                                     (ULONG *)&Irp->IoStatus.Information);
738
739                 if( !NT_SUCCESS( ntStatus))
740                 {
741
742                     AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
743                                   AFS_TRACE_LEVEL_VERBOSE,
744                                   "AFSProcessShareFsCtrl Failure on pipe %wZ Class FSCTL_PIPE_TRANSCEIVE Status %08lX\n",
745                                   &Ccb->DirectoryCB->NameInformation.FileName,
746                                   ntStatus);
747                 }
748
749                 break;
750             }
751
752             default:
753             {
754
755                 if( BooleanFlagOn( Ccb->DirectoryCB->Flags, AFS_DIR_ENTRY_SERVER_SERVICE))
756                 {
757
758                     //AFSPrint("AFSProcessShareFsCtrl (%08lX) For srvsvc input %08lX output %08lX\n",
759                     //                                                            ulFsControlCode,
760                     //                                                            ulInputBufferLen,
761                     //                                                            ulOutputBufferLen);
762                 }
763                 else if( BooleanFlagOn( Ccb->DirectoryCB->Flags, AFS_DIR_ENTRY_WORKSTATION_SERVICE))
764                 {
765
766                     //AFSPrint("AFSProcessShareFsCtrl (%08lX) For wkssvc input %08lX output %08lX\n",
767                     //                                                            ulFsControlCode,
768                     //                                                            ulInputBufferLen,
769                     //                                                            ulOutputBufferLen);
770                 }
771                 else
772                 {
773
774                     //AFSPrint("AFSProcessShareFsCtrl (%08lX) For IPC$ input %08lX output %08lX\n",
775                     //                                                            ulFsControlCode,
776                     //                                                            ulInputBufferLen,
777                     //                                                            ulOutputBufferLen);
778                 }
779
780                 break;
781             }
782         }
783     }
784
785     return ntStatus;
786 }