Windows: Fix uninitialized variables
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSFSControl.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011, 2012, 2013 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, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
16  *   nor the names of their contributors may be used to endorse or promote
17  *   products derived from this software without specific prior written
18  *   permission from Kernel Drivers, LLC and Your File System, Inc.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 //
34 // File: AFSFSControl.cpp
35 //
36
37 #include "AFSCommon.h"
38
39 NTSTATUS
40 AFSFSControl( IN PDEVICE_OBJECT LibDeviceObject,
41               IN PIRP Irp)
42 {
43
44     UNREFERENCED_PARAMETER(LibDeviceObject);
45     NTSTATUS ntStatus = STATUS_SUCCESS;
46     IO_STACK_LOCATION *pIrpSp;
47
48     pIrpSp = IoGetCurrentIrpStackLocation( Irp);
49
50     __try
51     {
52
53         switch( pIrpSp->MinorFunction)
54         {
55
56             case IRP_MN_USER_FS_REQUEST:
57
58                 ntStatus = AFSProcessUserFsRequest( Irp);
59
60                 break;
61
62             case IRP_MN_MOUNT_VOLUME:
63
64                 break;
65
66             case IRP_MN_VERIFY_VOLUME:
67
68                 break;
69
70             default:
71
72                 break;
73         }
74
75         AFSCompleteRequest( Irp,
76                               ntStatus);
77
78     }
79     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
80     {
81
82         AFSDbgTrace(( 0,
83                       0,
84                       "EXCEPTION - AFSFSControl\n"));
85
86         AFSDumpTraceFilesFnc();
87     }
88
89     return ntStatus;
90 }
91
92 static BOOLEAN
93 AFSParseMountPointTarget( IN  UNICODE_STRING *Target,
94                           OUT USHORT         *Type,
95                           OUT UNICODE_STRING *Volume,
96                           OUT UNICODE_STRING *Cell)
97 {
98     // Targets are of the form <type>[<cell>:]<volume>
99
100     *Type = Target->Buffer[ 0];
101
102     // Extract the cell name (if any)
103
104     Cell->Buffer = &Target->Buffer[ 1];
105
106     // Search for colon separator or end of counted string
107
108     for ( Cell->Length = 0; Cell->Length < Target->Length - sizeof( WCHAR); Cell->Length += sizeof( WCHAR))
109     {
110
111         if ( Cell->Buffer[ Cell->Length / sizeof( WCHAR)] == L':')
112         {
113             break;
114         }
115     }
116
117     // If a colon is not found, it means there is no cell
118
119     if ( Cell->Length < Target->Length - sizeof( WCHAR) &&
120          Cell->Buffer[ Cell->Length / sizeof( WCHAR)] == L':')
121     {
122
123         Cell->MaximumLength = Cell->Length;
124
125         if ( Cell->Length > Target->Length - 2 * sizeof( WCHAR))
126         {
127             // Invalid target string if there is no room for
128             // the volume name.
129
130             return FALSE;
131         }
132
133         Volume->Length = Volume->MaximumLength = (Target->Length - Cell->Length - 2 * sizeof( WCHAR));
134
135         Volume->Buffer = &Target->Buffer[ Cell->Length / sizeof( WCHAR) + 2];
136     }
137     else
138     {
139         // There is no cell
140
141         Volume->Length = Volume->MaximumLength = Cell->Length;
142
143         Volume->Buffer = Cell->Buffer;
144
145         Cell->Length = Cell->MaximumLength = 0;
146
147         Cell->Buffer = NULL;
148     }
149
150     return TRUE;
151 }
152
153 NTSTATUS
154 AFSProcessUserFsRequest( IN PIRP Irp)
155 {
156
157     NTSTATUS ntStatus = STATUS_SUCCESS;
158     ULONG ulFsControlCode;
159     AFSFcb *pFcb = NULL;
160     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp );
161     AFSCcb *pCcb = NULL;
162     ULONG ulOutputBufferLen, ulInputBufferLen;
163
164     __Enter
165     {
166
167         ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode;
168
169         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
170
171         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
172
173         if( pFcb == NULL ||
174             pCcb == NULL ||
175             pCcb->DirectoryCB == NULL)
176         {
177
178             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
179                           AFS_TRACE_LEVEL_VERBOSE_2,
180                           "AFSProcessUserFsRequest Invalid Fcb\n"));
181
182             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
183         }
184
185         if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
186         {
187
188             ntStatus = AFSProcessShareFsCtrl( Irp,
189                                               pFcb,
190                                               pCcb);
191
192             try_return( ntStatus);
193         }
194
195         ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength;
196         ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength;
197
198         //
199         // Process the request
200         //
201
202         switch( ulFsControlCode )
203         {
204
205             case FSCTL_REQUEST_OPLOCK_LEVEL_1:
206             case FSCTL_REQUEST_OPLOCK_LEVEL_2:
207             case FSCTL_REQUEST_BATCH_OPLOCK:
208             case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
209             case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
210             case FSCTL_OPLOCK_BREAK_NOTIFY:
211             case FSCTL_OPLOCK_BREAK_ACK_NO_2:
212             case FSCTL_REQUEST_FILTER_OPLOCK :
213             {
214                 //
215                 // Note that implementing this call will probably need us
216                 // to call the server as well as adding code in read and
217                 // write and caching.  Also that it is unlikely that
218                 // anyone will ever call us at this point - RDR doesn't
219                 // allow it
220                 //
221
222                 ntStatus = STATUS_NOT_IMPLEMENTED;
223
224                 break;
225             }
226
227             case FSCTL_LOCK_VOLUME:
228             {
229                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
230                               AFS_TRACE_LEVEL_VERBOSE_2,
231                               "AFSProcessUserFsRequest Processing FSCTL_LOCK_VOLUME request\n"));
232
233                 ntStatus = STATUS_NOT_IMPLEMENTED;
234
235                 break;
236             }
237
238             case FSCTL_UNLOCK_VOLUME:
239             {
240                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
241                               AFS_TRACE_LEVEL_VERBOSE_2,
242                               "AFSProcessUserFsRequest Processing FSCTL_UNLOCK_VOLUME request\n"));
243
244                 ntStatus = STATUS_NOT_IMPLEMENTED;
245
246                 break;
247             }
248
249             case FSCTL_DISMOUNT_VOLUME:
250             {
251                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
252                               AFS_TRACE_LEVEL_VERBOSE_2,
253                               "AFSProcessUserFsRequest Processing FSCTL_DISMOUNT_VOLUME request\n"));
254
255                 ntStatus = STATUS_NOT_IMPLEMENTED;
256
257                 break;
258             }
259
260             case FSCTL_MARK_VOLUME_DIRTY:
261             {
262                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
263                               AFS_TRACE_LEVEL_VERBOSE_2,
264                               "AFSProcessUserFsRequest Processing FSCTL_MARK_VOLUME_DIRTY request\n"));
265
266                 ntStatus = STATUS_NOT_IMPLEMENTED;
267
268                 break;
269             }
270
271             case FSCTL_IS_VOLUME_DIRTY:
272             {
273                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
274                               AFS_TRACE_LEVEL_VERBOSE_2,
275                               "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_DIRTY request\n"));
276
277                 ntStatus = STATUS_NOT_IMPLEMENTED;
278
279                 break;
280             }
281
282             case FSCTL_IS_VOLUME_MOUNTED:
283             {
284                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
285                               AFS_TRACE_LEVEL_VERBOSE_2,
286                               "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_MOUNTED request\n"));
287
288                 ntStatus = STATUS_NOT_IMPLEMENTED;
289
290                 break;
291             }
292
293             case FSCTL_IS_PATHNAME_VALID:
294             {
295                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
296                               AFS_TRACE_LEVEL_VERBOSE_2,
297                               "AFSProcessUserFsRequest Processing FSCTL_IS_PATHNAME_VALID request\n"));
298
299                 ntStatus = STATUS_SUCCESS;
300
301                 break;
302             }
303
304 #ifndef FSCTL_CSC_INTERNAL
305 #define FSCTL_CSC_INTERNAL                  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 107, METHOD_NEITHER, FILE_ANY_ACCESS)
306 #endif
307             case FSCTL_CSC_INTERNAL:
308             {
309                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
310                               AFS_TRACE_LEVEL_VERBOSE_2,
311                               "AFSProcessUserFsRequest Processing FSCTL_CSC_INTERNAL request\n"));
312
313                 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
314
315                 break;
316             }
317
318             case FSCTL_GET_REPARSE_POINT:
319             {
320
321                 REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
322                 REPARSE_DATA_BUFFER *pMSFTReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
323                 ULONG ulRemainingLen = ulOutputBufferLen;
324                 AFSReparseTagInfo *pReparseInfo = NULL;
325                 BOOLEAN bRelative = FALSE;
326                 BOOLEAN bDriveLetter = FALSE;
327                 WCHAR * PathBuffer = NULL;
328
329                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
330                               AFS_TRACE_LEVEL_VERBOSE_2,
331                               "AFSProcessUserFsRequest Processing FSCTL_GET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
332                               &pCcb->DirectoryCB->NameInformation.FileName,
333                               pFcb->ObjectInformation->FileType,
334                               pFcb->ObjectInformation->FileAttributes));
335
336                 //
337                 // Check if we have the reparse entry set on the entry
338                 //
339
340                 if( !BooleanFlagOn( pFcb->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
341                 {
342
343                     ntStatus = STATUS_NOT_A_REPARSE_POINT;
344
345                     break;
346                 }
347
348
349                 switch ( pFcb->ObjectInformation->FileType) {
350                 case AFS_FILE_TYPE_MOUNTPOINT:
351
352                     if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
353                     {
354
355                         ntStatus = STATUS_BUFFER_TOO_SMALL;
356
357                         Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
358
359                         break;
360                     }
361
362                     ulRemainingLen -= FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
363
364                     break;
365
366                 default:
367
368                     if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
369                     {
370
371                         ntStatus = STATUS_BUFFER_TOO_SMALL;
372
373                         Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
374
375                         break;
376                     }
377
378                     ulRemainingLen -= FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
379
380                     break;
381                 }
382
383                 //
384                 // Populate the data in the reparse buffer
385                 //
386
387                 pReparseBuffer->ReparseDataLength  = 0;
388
389                 AFSAcquireExcl( &pCcb->DirectoryCB->NonPaged->Lock,
390                                 TRUE);
391
392                 if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
393                 {
394
395                     //
396                     // We'll reset the DV to ensure we validate the metadata content
397                     //
398
399                     pFcb->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
400
401                     SetFlag( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
402
403                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
404                                   AFS_TRACE_LEVEL_VERBOSE,
405                                   "AFSProcessUserFsRequest Verifying symlink %wZ FID %08lX-%08lX-%08lX-%08lX\n",
406                                   &pCcb->DirectoryCB->NameInformation.FileName,
407                                   pFcb->ObjectInformation->FileId.Cell,
408                                   pFcb->ObjectInformation->FileId.Volume,
409                                   pFcb->ObjectInformation->FileId.Vnode,
410                                   pFcb->ObjectInformation->FileId.Unique));
411
412                     ntStatus = AFSVerifyEntry( &pCcb->AuthGroup,
413                                                pCcb->DirectoryCB,
414                                                FALSE);
415
416                     if( !NT_SUCCESS( ntStatus))
417                     {
418
419                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
420                                       AFS_TRACE_LEVEL_ERROR,
421                                       "AFSProcessUserFsRequest Failed to verify symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
422                                       &pCcb->DirectoryCB->NameInformation.FileName,
423                                       pFcb->ObjectInformation->FileId.Cell,
424                                       pFcb->ObjectInformation->FileId.Volume,
425                                       pFcb->ObjectInformation->FileId.Vnode,
426                                       pFcb->ObjectInformation->FileId.Unique,
427                                       ntStatus));
428
429                         AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);
430
431                         break;
432                     }
433                 }
434
435                 pReparseInfo = (AFSReparseTagInfo *)&pReparseBuffer->GenericReparseBuffer.DataBuffer[ 0];
436
437                 switch( pFcb->ObjectInformation->FileType)
438                 {
439
440                     case AFS_FILE_TYPE_SYMLINK:
441                     {
442
443                         if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
444                         {
445
446                             ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
447
448                             break;
449                         }
450
451                         bRelative = AFSIsRelativeName( &pCcb->DirectoryCB->NameInformation.TargetName);
452
453                         if ( bRelative)
454                         {
455
456                             if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
457                                 pCcb->DirectoryCB->NameInformation.TargetName.Length)
458                             {
459
460                                 ntStatus = STATUS_BUFFER_TOO_SMALL;
461
462                                 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
463                                     pCcb->DirectoryCB->NameInformation.TargetName.Length;
464
465                                 break;
466                             }
467
468                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE;
469
470                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
471                                 pCcb->DirectoryCB->NameInformation.TargetName.Length;
472
473                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
474                                 pCcb->DirectoryCB->NameInformation.TargetName.Length;
475
476                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
477
478                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
479
480                             PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;
481
482                             RtlCopyMemory( PathBuffer,
483                                            pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
484                                            pCcb->DirectoryCB->NameInformation.TargetName.Length);
485
486                             pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
487                                 FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
488                                 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
489                         }
490                         else
491                         {
492
493                             if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
494                                 /* Display Name */
495                                 pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) +
496                                 /* Substitute Name */
497                                 pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR))
498                             {
499
500                                 ntStatus = STATUS_BUFFER_TOO_SMALL;
501
502                                 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
503                                     pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) +
504                                     pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR);
505
506                                 break;
507                             }
508
509                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0;
510
511                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
512                                 pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR);
513
514                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
515                                 pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR);
516
517                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset =
518                                 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength;
519
520                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
521
522                             PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;
523
524                             /* Display Name */
525                             *PathBuffer++ = L'\\';
526
527                             RtlCopyMemory( PathBuffer,
528                                            pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
529                                            pCcb->DirectoryCB->NameInformation.TargetName.Length);
530
531                             PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR);
532
533                             /* Substitute Name */
534                             *PathBuffer++ = L'\\';
535                             *PathBuffer++ = L'?';
536                             *PathBuffer++ = L'?';
537                             *PathBuffer++ = L'\\';
538                             *PathBuffer++ = L'U';
539                             *PathBuffer++ = L'N';
540                             *PathBuffer++ = L'C';
541
542                             RtlCopyMemory( PathBuffer,
543                                            pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
544                                            pCcb->DirectoryCB->NameInformation.TargetName.Length);
545
546                             pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
547                                 FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
548                                 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
549                                 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
550                         }
551
552                         break;
553                     }
554
555                     case AFS_FILE_TYPE_MOUNTPOINT:
556                     {
557                         UNICODE_STRING Cell, Volume;
558                         USHORT Type;
559
560                         if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
561                         {
562                             ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
563
564                             break;
565                         }
566
567                         if ( !AFSParseMountPointTarget( &pCcb->DirectoryCB->NameInformation.TargetName,
568                                                         &Type,
569                                                         &Volume,
570                                                         &Cell))
571                         {
572                             ntStatus = STATUS_INVALID_PARAMETER;
573
574                             break;
575                         }
576
577                         if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length)
578                         {
579
580                             ntStatus = STATUS_BUFFER_TOO_SMALL;
581
582                             Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
583                                                         FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) +
584                                                         Volume.Length + Cell.Length;
585
586                             break;
587                         }
588
589                         pReparseInfo->SubTag = OPENAFS_SUBTAG_MOUNTPOINT;
590
591                         pReparseInfo->AFSMountPoint.Type = Type;
592
593                         pReparseInfo->AFSMountPoint.MountPointCellLength = Cell.Length;
594
595                         pReparseInfo->AFSMountPoint.MountPointVolumeLength = Volume.Length;
596
597                         RtlCopyMemory( pReparseInfo->AFSMountPoint.Buffer,
598                                        Cell.Buffer,
599                                        Cell.Length);
600
601                         RtlCopyMemory( &pReparseInfo->AFSMountPoint.Buffer[ Cell.Length / sizeof( WCHAR)],
602                                        Volume.Buffer,
603                                        Volume.Length);
604
605                         pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length);
606
607                         break;
608                     }
609
610                     case AFS_FILE_TYPE_DFSLINK:
611                     {
612
613                         if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
614                         {
615
616                             ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
617
618                             break;
619                         }
620
621                         bRelative = ( pCcb->DirectoryCB->NameInformation.TargetName.Buffer[0] == L'\\');
622
623                         bDriveLetter = (bRelative == FALSE && pCcb->DirectoryCB->NameInformation.TargetName.Buffer[1] == L':');
624
625                         if ( bRelative)
626                         {
627
628                             if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
629                                 pCcb->DirectoryCB->NameInformation.TargetName.Length)
630                             {
631
632                                 ntStatus = STATUS_BUFFER_TOO_SMALL;
633
634                                 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
635                                     pCcb->DirectoryCB->NameInformation.TargetName.Length;
636
637                                 break;
638                             }
639
640                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE;
641
642                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
643                                 pCcb->DirectoryCB->NameInformation.TargetName.Length;
644
645                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
646                                 pCcb->DirectoryCB->NameInformation.TargetName.Length;
647
648                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
649
650                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
651
652                             PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;
653
654                             RtlCopyMemory( PathBuffer,
655                                            pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
656                                            pCcb->DirectoryCB->NameInformation.TargetName.Length);
657
658                             pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
659                                 FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
660                                 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
661                         }
662                         else if ( bDriveLetter)
663                         {
664
665                             if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
666                                 /* Display Name */
667                                 pCcb->DirectoryCB->NameInformation.TargetName.Length +
668                                 /* Substitute Name */
669                                 pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR))
670                             {
671
672                                 ntStatus = STATUS_BUFFER_TOO_SMALL;
673
674                                 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
675                                     pCcb->DirectoryCB->NameInformation.TargetName.Length +
676                                     pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR);
677
678                                 break;
679                             }
680
681                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0;
682
683                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
684                                 pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR);
685
686                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
687                                 pCcb->DirectoryCB->NameInformation.TargetName.Length;
688
689                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset =
690                                 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength;
691
692                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
693
694                             PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;
695
696                             /* Display Name */
697                             RtlCopyMemory( PathBuffer,
698                                            pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
699                                            pCcb->DirectoryCB->NameInformation.TargetName.Length);
700
701                             PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR);
702
703                             /* Substitute Name */
704                             *PathBuffer++ = L'\\';
705                             *PathBuffer++ = L'?';
706                             *PathBuffer++ = L'?';
707                             *PathBuffer++ = L'\\';
708
709                             RtlCopyMemory( PathBuffer,
710                                            pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
711                                            pCcb->DirectoryCB->NameInformation.TargetName.Length);
712
713                             pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
714                                 FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
715                                 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
716                                 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
717                         }
718                         else
719                         {
720
721                             if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
722                                 /* Display Name */
723                                 pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) +
724                                 /* Substitute Name */
725                                 pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR))
726                             {
727
728                                 ntStatus = STATUS_BUFFER_TOO_SMALL;
729
730                                 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
731                                     pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) +
732                                     pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR);
733
734                                 break;
735                             }
736
737                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0;
738
739                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
740                                 pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR);
741
742                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
743                                 pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR);
744
745                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset =
746                                 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength;
747
748                             pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
749
750                             PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;
751
752                             /* Display Name */
753                             *PathBuffer++ = L'\\';
754
755                             RtlCopyMemory( PathBuffer,
756                                            pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
757                                            pCcb->DirectoryCB->NameInformation.TargetName.Length);
758
759                             PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR);
760
761                             /* Substitute Name */
762                             *PathBuffer++ = L'\\';
763                             *PathBuffer++ = L'?';
764                             *PathBuffer++ = L'?';
765                             *PathBuffer++ = L'\\';
766                             *PathBuffer++ = L'U';
767                             *PathBuffer++ = L'N';
768                             *PathBuffer++ = L'C';
769
770                             RtlCopyMemory( PathBuffer,
771                                            pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
772                                            pCcb->DirectoryCB->NameInformation.TargetName.Length);
773
774                             pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
775                                 FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
776                                 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
777                                 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
778                         }
779
780                         break;
781                     }
782
783                     default:
784
785                         ntStatus = STATUS_NOT_A_REPARSE_POINT;
786
787                         break;
788                 }
789
790                 if ( ntStatus == STATUS_SUCCESS)
791                 {
792
793                     ulRemainingLen -= pReparseBuffer->ReparseDataLength;
794
795                     if ( pFcb->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
796                     {
797
798                         pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
799
800                         RtlCopyMemory( &pReparseBuffer->ReparseGuid,
801                                        &GUID_AFS_REPARSE_GUID,
802                                        sizeof( GUID));
803
804                         Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
805                             + pReparseBuffer->ReparseDataLength;
806                     }
807                     else
808                     {
809
810                         pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SYMLINK;
811
812                         Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
813                             + pReparseBuffer->ReparseDataLength;
814                     }
815                 }
816
817                 AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);
818
819                 break;
820             }
821
822             case FSCTL_SET_REPARSE_POINT:
823             {
824
825                 REPARSE_GUID_DATA_BUFFER *pReparseGUIDBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
826                 REPARSE_DATA_BUFFER *pReparseBuffer = NULL;
827                 AFSReparseTagInfo *pReparseInfo = NULL;
828                 AFSObjectInfoCB *pParentObjectInfo = NULL;
829                 UNICODE_STRING uniTargetName;
830                 ULONGLONG ullIndex = 0;
831                 LONG lCount;
832
833                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
834                               AFS_TRACE_LEVEL_VERBOSE,
835                               "AFSProcessUserFsRequest Processing FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
836                               &pCcb->DirectoryCB->NameInformation.FileName,
837                               pFcb->ObjectInformation->FileType,
838                               pFcb->ObjectInformation->FileAttributes));
839
840                 if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
841                 {
842
843                     ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
844
845                     break;
846                 }
847
848                 if( (pReparseGUIDBuffer->ReparseTag & 0x0000FFFF) == IO_REPARSE_TAG_OPENAFS_DFS)
849                 {
850
851                     if( RtlCompareMemory( &pReparseGUIDBuffer->ReparseGuid,
852                                           &GUID_AFS_REPARSE_GUID,
853                                           sizeof( GUID)) != sizeof( GUID))
854                     {
855
856                         ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;
857
858                         break;
859                     }
860
861                     if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
862                                                                         sizeof( AFSReparseTagInfo))
863                     {
864
865                         ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
866
867                         break;
868                     }
869
870                     pReparseInfo = (AFSReparseTagInfo *)pReparseGUIDBuffer->GenericReparseBuffer.DataBuffer;
871
872                     switch( pReparseInfo->SubTag)
873                     {
874
875                         case OPENAFS_SUBTAG_SYMLINK:
876                         {
877
878                             if( ulInputBufferLen < (ULONG)(FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
879                                                            FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) +
880                                                            pReparseInfo->AFSSymLink.SymLinkTargetLength))
881                             {
882
883                                 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
884
885                                 break;
886                             }
887
888                             uniTargetName.Length = pReparseInfo->AFSSymLink.SymLinkTargetLength;
889                             uniTargetName.MaximumLength = uniTargetName.Length;
890
891                             uniTargetName.Buffer = (WCHAR *)pReparseInfo->AFSSymLink.Buffer;
892
893                             break;
894                         }
895
896                         case OPENAFS_SUBTAG_UNC:
897                         {
898
899                             if( ulInputBufferLen < (ULONG)(FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
900                                                            FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) +
901                                                            pReparseInfo->UNCReferral.UNCTargetLength))
902                             {
903
904                                 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
905
906                                 break;
907                             }
908
909                             uniTargetName.Length = pReparseInfo->UNCReferral.UNCTargetLength;
910                             uniTargetName.MaximumLength = uniTargetName.Length;
911
912                             uniTargetName.Buffer = (WCHAR *)pReparseInfo->UNCReferral.Buffer;
913
914                             break;
915                         }
916
917                         case OPENAFS_SUBTAG_MOUNTPOINT:
918                             //
919                             // Not yet handled
920                             //
921                         default:
922                         {
923
924                             ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
925
926                             break;
927                         }
928                     }
929                 }
930                 else
931                 {
932                     //
933                     // Handle Microsoft Reparse Tags
934                     //
935
936                     switch( pReparseGUIDBuffer->ReparseTag)
937                     {
938
939                         case IO_REPARSE_TAG_MOUNT_POINT:
940                         {
941
942                             pReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
943
944                             uniTargetName.Length = pReparseBuffer->MountPointReparseBuffer.PrintNameLength;
945                             uniTargetName.MaximumLength = uniTargetName.Length;
946
947                             uniTargetName.Buffer = (WCHAR *)((char *)pReparseBuffer->MountPointReparseBuffer.PathBuffer +
948                                                               pReparseBuffer->MountPointReparseBuffer.PrintNameOffset);
949
950                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
951                                           AFS_TRACE_LEVEL_VERBOSE_2,
952                                           "AFSProcessUserFsRequest IO_REPARSE_TAG_MOUNT_POINT request %wZ\n",
953                                           &uniTargetName));
954
955                             ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
956
957                             break;
958                         }
959
960                         case IO_REPARSE_TAG_SYMLINK:
961                         {
962
963                             pReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
964
965                             uniTargetName.Length = pReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
966                             uniTargetName.MaximumLength = uniTargetName.Length;
967
968                             uniTargetName.Buffer = (WCHAR *)((char *)pReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer +
969                                                               pReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset);
970
971                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
972                                           AFS_TRACE_LEVEL_VERBOSE_2,
973                                           "AFSProcessUserFsRequest IO_REPARSE_TAG_SYMLINK request %wZ\n",
974                                           &uniTargetName));
975                             break;
976                         }
977
978                         default:
979                         {
980
981                             ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
982
983                             break;
984                         }
985                     }
986                 }
987
988                 if( !NT_SUCCESS( ntStatus))
989                 {
990
991                     break;
992                 }
993
994                 //
995                 // First thing is to locate/create our object information block
996                 // for this entry
997                 //
998
999                 AFSAcquireExcl( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock,
1000                                 TRUE);
1001
1002                 if ( AFSIsVolumeFID( &pFcb->ObjectInformation->ParentFileId))
1003                 {
1004
1005                     pParentObjectInfo = &pFcb->ObjectInformation->VolumeCB->ObjectInformation;
1006                 }
1007                 else
1008                 {
1009                     ullIndex = AFSCreateLowIndex( &pFcb->ObjectInformation->ParentFileId);
1010
1011                     ntStatus = AFSLocateHashEntry( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeHead,
1012                                                    ullIndex,
1013                                                    (AFSBTreeEntry **)&pParentObjectInfo);
1014                 }
1015
1016                 if ( NT_SUCCESS( ntStatus))
1017                 {
1018
1019                     lCount = AFSObjectInfoIncrement( pParentObjectInfo,
1020                                                      AFS_OBJECT_REFERENCE_FS_REQ);
1021
1022                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1023                                   AFS_TRACE_LEVEL_VERBOSE,
1024                                   "AFSProcessUserFsRequest Increment count on object %p Cnt %d\n",
1025                                   pParentObjectInfo,
1026                                   lCount));
1027
1028                     KeQueryTickCount( &pParentObjectInfo->LastAccessCount);
1029                 }
1030
1031                 AFSReleaseResource( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock);
1032
1033                 if ( NT_SUCCESS( ntStatus))
1034                 {
1035
1036                     //
1037                     // Extract out the information to the call to the service
1038                     //
1039
1040                     ntStatus = AFSCreateSymlink( &pCcb->AuthGroup,
1041                                                  pParentObjectInfo,
1042                                                  &pCcb->DirectoryCB->NameInformation.FileName,
1043                                                  pFcb->ObjectInformation,
1044                                                  &uniTargetName);
1045
1046                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1047                                   AFS_TRACE_LEVEL_VERBOSE_2,
1048                                   "AFSProcessUserFsRequest Processed FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x Status %08lX\n",
1049                                   &pCcb->DirectoryCB->NameInformation.FileName,
1050                                   pFcb->ObjectInformation->FileType,
1051                                   pFcb->ObjectInformation->FileAttributes,
1052                                   ntStatus));
1053
1054                     AFSAcquireShared( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock,
1055                                       TRUE);
1056
1057                     lCount = AFSObjectInfoDecrement( pParentObjectInfo,
1058                                                      AFS_OBJECT_REFERENCE_FS_REQ);
1059
1060                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1061                                   AFS_TRACE_LEVEL_VERBOSE,
1062                                   "AFSProcessUserFsRequest Decrement count on object %p Cnt %d\n",
1063                                   pParentObjectInfo,
1064                                   lCount));
1065
1066                     AFSReleaseResource( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock);
1067                 }
1068
1069                 break;
1070             }
1071
1072             case FSCTL_DELETE_REPARSE_POINT:
1073             {
1074
1075                 REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
1076
1077                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1078                               AFS_TRACE_LEVEL_VERBOSE_2,
1079                               "AFSProcessUserFsRequest Processing FSCTL_DELETE_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
1080                               &pCcb->DirectoryCB->NameInformation.FileName,
1081                               pFcb->ObjectInformation->FileType,
1082                               pFcb->ObjectInformation->FileAttributes));
1083
1084                 //
1085                 // Check if we have the reparse entry set on the entry
1086                 //
1087
1088                 if( !BooleanFlagOn( pFcb->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
1089                 {
1090
1091                     ntStatus = STATUS_NOT_A_REPARSE_POINT;
1092
1093                     break;
1094                 }
1095
1096                 if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
1097                 {
1098
1099                     ntStatus = STATUS_INVALID_PARAMETER;
1100
1101                     break;
1102                 }
1103
1104                 if( (pReparseBuffer->ReparseTag & 0x0000FFFF) != IO_REPARSE_TAG_OPENAFS_DFS)
1105                 {
1106
1107                     ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH;
1108
1109                     break;
1110                 }
1111
1112                 if( RtlCompareMemory( &pReparseBuffer->ReparseGuid,
1113                                       &GUID_AFS_REPARSE_GUID,
1114                                       sizeof( GUID)) != sizeof( GUID))
1115                 {
1116
1117                     ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;
1118
1119                     break;
1120                 }
1121
1122                 //
1123                 // Claim success.  The typical usage is setting delete on close
1124                 // as the next operation on the reparse point before closing
1125                 // the handle.
1126                 //
1127
1128                 ntStatus = STATUS_SUCCESS;
1129
1130                 break;
1131             }
1132
1133 #ifndef FSCTL_SET_PURGE_FAILURE_MODE
1134 #define FSCTL_SET_PURGE_FAILURE_MODE        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 156, METHOD_BUFFERED, FILE_ANY_ACCESS)
1135 #endif
1136
1137             case FSCTL_SET_PURGE_FAILURE_MODE:
1138             {
1139
1140                 //
1141                 // For the time being just succeed this call
1142                 //
1143
1144                 ntStatus = STATUS_SUCCESS;
1145
1146                 break;
1147             }
1148
1149             default :
1150             {
1151
1152                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1153                               AFS_TRACE_LEVEL_VERBOSE_2,
1154                               "AFSProcessUserFsRequest Processing default (%08lX) request\n",
1155                               ulFsControlCode));
1156
1157                 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
1158
1159                 break;
1160             }
1161         }
1162
1163 try_exit:
1164
1165         NOTHING;
1166     }
1167
1168     return ntStatus;
1169 }
1170
1171 NTSTATUS
1172 AFSProcessShareFsCtrl( IN IRP *Irp,
1173                        IN AFSFcb *Fcb,
1174                        IN AFSCcb *Ccb)
1175 {
1176
1177     UNREFERENCED_PARAMETER(Fcb);
1178     NTSTATUS ntStatus = STATUS_SUCCESS;
1179     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1180     ULONG ulOutputBufferLen = 0, ulInputBufferLen;
1181     ULONG ulFsControlCode;
1182
1183     __Enter
1184     {
1185
1186         ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode;
1187
1188         ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength;
1189         ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength;
1190
1191         switch( ulFsControlCode)
1192         {
1193
1194             case FSCTL_PIPE_TRANSCEIVE:
1195             {
1196
1197                 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
1198                               AFS_TRACE_LEVEL_VERBOSE,
1199                               "AFSProcessShareFsCtrl On pipe %wZ Class FSCTL_PIPE_TRANSCEIVE\n",
1200                               &Ccb->DirectoryCB->NameInformation.FileName));
1201
1202                 ntStatus = AFSNotifyPipeTransceive( Ccb,
1203                                                     ulInputBufferLen,
1204                                                     ulOutputBufferLen,
1205                                                     pIrpSp->Parameters.FileSystemControl.Type3InputBuffer,
1206                                                     Irp->UserBuffer,
1207                                                     (ULONG *)&Irp->IoStatus.Information);
1208
1209                 if( !NT_SUCCESS( ntStatus))
1210                 {
1211
1212                     AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
1213                                   AFS_TRACE_LEVEL_VERBOSE,
1214                                   "AFSProcessShareFsCtrl Failure on pipe %wZ Class FSCTL_PIPE_TRANSCEIVE Status %08lX\n",
1215                                   &Ccb->DirectoryCB->NameInformation.FileName,
1216                                   ntStatus));
1217                 }
1218
1219                 break;
1220             }
1221
1222             default:
1223             {
1224
1225                 AFSPrint( "AFSProcessShareFsCtrl (%08lX) For IPC$ input %08lX output %08lX\n",
1226                           ulFsControlCode,
1227                           ulInputBufferLen,
1228                           ulOutputBufferLen);
1229
1230                 break;
1231             }
1232         }
1233     }
1234
1235     return ntStatus;
1236 }