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