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