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