ReactOS  0.4.14-dev-55-g2da92ac
ea.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  Ea.c
8 
9 Abstract:
10 
11  This module implements the EA routines for Fat called by
12  the dispatch driver.
13 
14 
15 --*/
16 
17 #include "fatprocs.h"
18 
19 //
20 // The local debug trace level
21 //
22 
23 #define Dbg (DEBUG_TRACE_EA)
24 
25 //
26 // Local procedure prototypes
27 //
28 
32  OUT PCCB Ccb,
33  IN PPACKED_EA FirstPackedEa,
34  IN ULONG PackedEasLength,
35  OUT PUCHAR UserBuffer,
36  IN ULONG UserBufferLength,
37  IN PUCHAR UserEaList,
38  IN ULONG UserEaListLength,
40  );
41 
45  OUT PCCB Ccb,
46  IN PPACKED_EA FirstPackedEa,
47  IN ULONG PackedEasLength,
48  OUT PUCHAR UserBuffer,
49  IN ULONG UserBufferLength,
50  IN ULONG UserEaIndex,
52  );
53 
57  OUT PCCB Ccb,
58  IN PPACKED_EA FirstPackedEa,
59  IN ULONG PackedEasLength,
60  OUT PUCHAR UserBuffer,
61  IN ULONG UserBufferLength,
63  ULONG StartOffset
64  );
65 
66 BOOLEAN
70  IN PUCHAR UserBuffer
71  );
72 
73 #ifdef ALLOC_PRAGMA
74 #pragma alloc_text(PAGE, FatCommonQueryEa)
75 #pragma alloc_text(PAGE, FatCommonSetEa)
76 #pragma alloc_text(PAGE, FatFsdQueryEa)
77 #pragma alloc_text(PAGE, FatFsdSetEa)
78 #if 0
79 #pragma alloc_text(PAGE, FatIsDuplicateEaName)
80 #pragma alloc_text(PAGE, FatQueryEaIndexSpecified)
81 #pragma alloc_text(PAGE, FatQueryEaSimpleScan)
82 #pragma alloc_text(PAGE, FatQueryEaUserEaList)
83 #endif
84 #endif
85 
86 
90 NTAPI
91 FatFsdQueryEa (
92  _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
94  )
95 
96 /*++
97 
98 Routine Description:
99 
100  This routine implements the Fsd part of the NtQueryEa API
101  call.
102 
103 Arguments:
104 
105  VolumeDeviceObject - Supplies the volume device object where the file
106  being queried exists.
107 
108  Irp - Supplies the Irp being processed.
109 
110 Return Value:
111 
112  NTSTATUS - The FSD status for the Irp.
113 
114 --*/
115 
116 {
119 
121 
122  PAGED_CODE();
123 
124  DebugTrace(+1, Dbg, "FatFsdQueryEa\n", 0);
125 
126  //
127  // Call the common query routine, with blocking allowed if synchronous
128  //
129 
131 
133 
134  _SEH2_TRY {
135 
137 
139 
141 
142  //
143  // We had some trouble trying to perform the requested
144  // operation, so we'll abort the I/O request with
145  // the error status that we get back from the
146  // execption code
147  //
148 
149  Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
150  } _SEH2_END;
151 
152  if (TopLevel) { IoSetTopLevelIrp( NULL ); }
153 
155 
156  //
157  // And return to our caller
158  //
159 
160  DebugTrace(-1, Dbg, "FatFsdQueryEa -> %08lx\n", Status);
161 
162  UNREFERENCED_PARAMETER( VolumeDeviceObject );
163 
164  return Status;
165 }
166 
167 
170 NTSTATUS
171 NTAPI
172 FatFsdSetEa (
173  _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
175  )
176 
177 /*++
178 
179 Routine Description:
180 
181  This routine implements the FSD part of the NtSetEa API
182  call.
183 
184 Arguments:
185 
186  VolumeDeviceObject - Supplies the volume device object where the file
187  being set exists.
188 
189  Irp - Supplies the Irp being processed.
190 
191 Return Value:
192 
193  NTSTATUS - The FSD status for the Irp.
194 
195 --*/
196 
197 {
200 
202 
203  PAGED_CODE();
204 
205  DebugTrace(+1, Dbg, "FatFsdSetEa\n", 0);
206 
207  //
208  // Call the common set routine, with blocking allowed if synchronous
209  //
210 
212 
214 
215  _SEH2_TRY {
216 
218 
220 
222 
223  //
224  // We had some trouble trying to perform the requested
225  // operation, so we'll abort the I/O request with
226  // the error status that we get back from the
227  // execption code
228  //
229 
230  Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
231  } _SEH2_END;
232 
233  if (TopLevel) { IoSetTopLevelIrp( NULL ); }
234 
236 
237  //
238  // And return to our caller
239  //
240 
241  DebugTrace(-1, Dbg, "FatFsdSetEa -> %08lx\n", Status);
242 
243  UNREFERENCED_PARAMETER( VolumeDeviceObject );
244 
245  return Status;
246 }
247 
248 
249 NTSTATUS
252  IN PIRP Irp
253  )
254 
255 /*++
256 
257 Routine Description:
258 
259  This is the common routine for querying File ea called by both
260  the fsd and fsp threads.
261 
262 Arguments:
263 
264  Irp - Supplies the Irp being processed
265 
266 Return Value:
267 
268  NTSTATUS - The return status for the operation
269 
270 --*/
271 
272 {
273 #if 0
275 
277 
278  PUCHAR Buffer;
279  ULONG UserBufferLength;
280 
281  PUCHAR UserEaList;
282  ULONG UserEaListLength;
283  ULONG UserEaIndex;
286  BOOLEAN IndexSpecified;
287 
288  PVCB Vcb;
289  PCCB Ccb;
290 
291  PFCB Fcb;
292  PDIRENT Dirent;
293  PBCB Bcb;
294 
296  PBCB EaBcb;
297  BOOLEAN LockedEaFcb;
298 
299  PEA_SET_HEADER EaSetHeader;
301 
302  USHORT ExtendedAttributes;
303 #endif
304 
305  PAGED_CODE();
306 
309 
310 #if 0
311  //
312  // Get the current Irp stack location
313  //
314 
316 
317  DebugTrace(+1, Dbg, "FatCommonQueryEa...\n", 0);
318  DebugTrace( 0, Dbg, " Wait = %08lx\n", FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
319  DebugTrace( 0, Dbg, " Irp = %p\n", Irp );
320  DebugTrace( 0, Dbg, " ->SystemBuffer = %p\n", Irp->AssociatedIrp.SystemBuffer );
321  DebugTrace( 0, Dbg, " ->Length = %08lx\n", IrpSp->Parameters.QueryEa.Length );
322  DebugTrace( 0, Dbg, " ->EaList = %08lx\n", IrpSp->Parameters.QueryEa.EaList );
323  DebugTrace( 0, Dbg, " ->EaListLength = %08lx\n", IrpSp->Parameters.QueryEa.EaListLength );
324  DebugTrace( 0, Dbg, " ->EaIndex = %08lx\n", IrpSp->Parameters.QueryEa.EaIndex );
325  DebugTrace( 0, Dbg, " ->RestartScan = %08lx\n", FlagOn(IrpSp->Flags, SL_RESTART_SCAN));
326  DebugTrace( 0, Dbg, " ->ReturnSingleEntry = %08lx\n", FlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY));
327  DebugTrace( 0, Dbg, " ->IndexSpecified = %08lx\n", FlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED));
328 
329  Irp->IoStatus.Status = STATUS_SUCCESS;
330  Irp->IoStatus.Information = 0;
331 
332  //
333  // Check that the file object is associated with either a user file
334  // or directory open. We don't allow Ea operations on the root
335  // directory.
336  //
337 
338  {
339  TYPE_OF_OPEN OpenType;
340 
341  if (((OpenType = FatDecodeFileObject( IrpSp->FileObject,
342  &Vcb,
343  &Fcb,
344  &Ccb )) != UserFileOpen
345  && OpenType != UserDirectoryOpen) ||
346 
347  (NodeType( Fcb )) == FAT_NTC_ROOT_DCB) {
348 
350 
351  DebugTrace(-1, Dbg,
352  "FatCommonQueryEa -> %08lx\n",
354 
356  }
357  }
358 
359  //
360  // Fat32 does not support ea's.
361  //
362 
363  if (FatIsFat32(Vcb)) {
364 
366  DebugTrace(-1, Dbg,
367  "FatCommonQueryEa -> %08lx\n",
370  }
371 
372  //
373  // Acquire shared access to the Fcb and enqueue the Irp if we didn't
374  // get access.
375  //
376 
378 
379  DebugTrace(0, Dbg, "FatCommonQueryEa: Thread can't wait\n", 0);
380 
382 
383  DebugTrace(-1, Dbg, "FatCommonQueryEa -> %08lx\n", Status );
384 
385  return Status;
386  }
387 
388  FatAcquireSharedFcb( IrpContext, Fcb );
389 
390  //
391  // Reference our input parameters to make things easier
392  //
393 
394  UserBufferLength = IrpSp->Parameters.QueryEa.Length;
395  UserEaList = IrpSp->Parameters.QueryEa.EaList;
396  UserEaListLength = IrpSp->Parameters.QueryEa.EaListLength;
397  UserEaIndex = IrpSp->Parameters.QueryEa.EaIndex;
400  IndexSpecified = BooleanFlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED);
401 
402  //
403  // Initialize our local values.
404  //
405 
406  LockedEaFcb = FALSE;
407  Bcb = NULL;
408  EaBcb = NULL;
409 
411 
412  RtlZeroMemory( &EaSetRange, sizeof( EA_RANGE ));
413 
414  try {
415 
416  PPACKED_EA FirstPackedEa;
417  ULONG PackedEasLength;
418 
420 
421  //
422  // We verify that the Fcb is still valid.
423  //
424 
425  FatVerifyFcb( IrpContext, Fcb );
426 
427  //
428  // We need to get the dirent for the Fcb to recover the Ea handle.
429  //
430 
431  FatGetDirentFromFcbOrDcb( IrpContext, Fcb, &Dirent, &Bcb );
432 
433  //
434  // Verify that the Ea file is in a consistant state. If the
435  // Ea modification count in the Fcb doesn't match that in
436  // the CCB, then the Ea file has been changed from under
437  // us. If we are not starting the search from the beginning
438  // of the Ea set, we return an error.
439  //
440 
441  if (UserEaList == NULL
442  && Ccb->OffsetOfNextEaToReturn != 0
443  && !IndexSpecified
444  && !RestartScan
446 
447  DebugTrace(0, Dbg,
448  "FatCommonQueryEa: Ea file in unknown state\n", 0);
449 
451 
452  try_return( Status );
453  }
454 
455  //
456  // Show that the Ea's for this file are consistant for this
457  // file handle.
458  //
459 
461 
462  //
463  // If the handle value is 0, then the file has no Eas. We dummy up
464  // an ea list to use below.
465  //
466 
467  ExtendedAttributes = Dirent->ExtendedAttributes;
468 
470 
471  if (ExtendedAttributes == 0) {
472 
473  DebugTrace(0, Dbg,
474  "FatCommonQueryEa: Zero handle, no Ea's for this file\n", 0);
475 
476  FirstPackedEa = (PPACKED_EA) NULL;
477 
478  PackedEasLength = 0;
479 
480  } else {
481 
482  //
483  // We need to get the Ea file for this volume. If the
484  // operation doesn't complete due to blocking, then queue the
485  // Irp to the Fsp.
486  //
487 
488  FatGetEaFile( IrpContext,
489  Vcb,
490  &EaDirent,
491  &EaBcb,
492  FALSE,
493  FALSE );
494 
495  LockedEaFcb = TRUE;
496 
497  //
498  // If the above operation completed and the Ea file did not exist,
499  // the disk has been corrupted. There is an existing Ea handle
500  // without any Ea data.
501  //
502 
503  if (Vcb->VirtualEaFile == NULL) {
504 
505  DebugTrace(0, Dbg,
506  "FatCommonQueryEa: No Ea file found when expected\n", 0);
507 
509 
510  try_return( Status );
511  }
512 
513  //
514  // We need to try to get the Ea set for the desired file. If
515  // blocking is necessary then we'll post the request to the Fsp.
516  //
517 
519  Vcb,
520  ExtendedAttributes,
521  &Fcb->ShortName.Name.Oem,
522  TRUE,
523  &EaSetRange );
524 
525  EaSetHeader = (PEA_SET_HEADER) EaSetRange.Data;
526 
527  //
528  // Find the start and length of the Eas.
529  //
530 
531  FirstPackedEa = (PPACKED_EA) EaSetHeader->PackedEas;
532 
533  PackedEasLength = GetcbList( EaSetHeader ) - 4;
534  }
535 
536  //
537  // Protect our access to the user buffer since IO dosn't do this
538  // for us in this path unless we had specified that our driver
539  // requires buffering for these large requests. We don't, so ...
540  //
541 
542  try {
543 
544  //
545  // Let's clear the output buffer.
546  //
547 
548  RtlZeroMemory( Buffer, UserBufferLength );
549 
550  //
551  // We now satisfy the user's request depending on whether he
552  // specified an Ea name list, an Ea index or restarting the
553  // search.
554  //
555 
556  //
557  // The user has supplied a list of Ea names.
558  //
559 
560  if (UserEaList != NULL) {
561 
562  Irp->IoStatus = FatQueryEaUserEaList( IrpContext,
563  Ccb,
564  FirstPackedEa,
565  PackedEasLength,
566  Buffer,
567  UserBufferLength,
568  UserEaList,
569  UserEaListLength,
571 
572  //
573  // The user supplied an index into the Ea list.
574  //
575 
576  } else if (IndexSpecified) {
577 
579  Ccb,
580  FirstPackedEa,
581  PackedEasLength,
582  Buffer,
583  UserBufferLength,
584  UserEaIndex,
586 
587  //
588  // Else perform a simple scan, taking into account the restart
589  // flag and the position of the next Ea stored in the Ccb.
590  //
591 
592  } else {
593 
594  Irp->IoStatus = FatQueryEaSimpleScan( IrpContext,
595  Ccb,
596  FirstPackedEa,
597  PackedEasLength,
598  Buffer,
599  UserBufferLength,
602  ? 0
603  : Ccb->OffsetOfNextEaToReturn );
604  }
605 
608 
609  //
610  // We must have had a problem filling in the user's buffer, so fail.
611  //
612 
613  Irp->IoStatus.Status = GetExceptionCode();
614  Irp->IoStatus.Information = 0;
615  }
616 
617  Status = Irp->IoStatus.Status;
618 
619  try_exit: NOTHING;
620  } finally {
621 
623 
624  //
625  // Release the Fcb for the file object, and the Ea Fcb if
626  // successfully locked.
627  //
628 
630 
631  if (LockedEaFcb) {
632 
633  FatReleaseFcb( IrpContext, Vcb->EaFcb );
634  }
635 
636  //
637  // Unpin the dirents for the Fcb, EaFcb and EaSetFcb if necessary.
638  //
639 
642 
644 
645  if (!AbnormalTermination()) {
646 
648  }
649 
650  DebugTrace(-1, Dbg, "FatCommonQueryEa -> %08lx\n", Status);
651  }
652 
653  return Status;
654 #endif
655 }
656 
657 
658 NTSTATUS
661  IN PIRP Irp
662  )
663 
664 /*++
665 
666 Routine Description:
667 
668  This routine implements the common Set Ea File Api called by the
669  the Fsd and Fsp threads
670 
671 Arguments:
672 
673  Irp - Supplies the Irp to process
674 
675 Return Value:
676 
677  NTSTATUS - The appropriate status for the Irp
678 
679 --*/
680 
681 {
682 #if 0
684 
686 
687  USHORT ExtendedAttributes;
688 
689  PUCHAR Buffer;
690  ULONG UserBufferLength;
691 
692  PVCB Vcb;
693  PCCB Ccb;
694 
695  PFCB Fcb;
696  PDIRENT Dirent;
697  PBCB Bcb = NULL;
698 
700  PBCB EaBcb = NULL;
701 
702  PEA_SET_HEADER EaSetHeader = NULL;
703 
704  PEA_SET_HEADER PrevEaSetHeader;
705  PEA_SET_HEADER NewEaSetHeader;
707 
708  BOOLEAN AcquiredVcb = FALSE;
709  BOOLEAN AcquiredFcb = FALSE;
710  BOOLEAN AcquiredParentDcb = FALSE;
711  BOOLEAN AcquiredRootDcb = FALSE;
712  BOOLEAN AcquiredEaFcb = FALSE;
713 #endif
714 
715  PAGED_CODE();
716 
719 
720 #if 0
721 
722  //
723  // The following booleans are used in the unwind process.
724  //
725 
726  //
727  // Get the current Irp stack location
728  //
729 
731 
732  DebugTrace(+1, Dbg, "FatCommonSetEa...\n", 0);
733  DebugTrace( 0, Dbg, " Wait = %08lx\n", FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
734  DebugTrace( 0, Dbg, " Irp = %p\n", Irp );
735  DebugTrace( 0, Dbg, " ->SystemBuffer = %p\n", Irp->AssociatedIrp.SystemBuffer );
736  DebugTrace( 0, Dbg, " ->Length = %08lx\n", IrpSp->Parameters.SetEa.Length );
737 
738  Irp->IoStatus.Status = STATUS_SUCCESS;
739  Irp->IoStatus.Information = 0;
740 
741  //
742  // Check that the file object is associated with either a user file
743  // or directory open.
744  //
745 
746  {
747  TYPE_OF_OPEN OpenType;
748 
749  if (((OpenType = FatDecodeFileObject( IrpSp->FileObject,
750  &Vcb,
751  &Fcb,
752  &Ccb )) != UserFileOpen
753  && OpenType != UserDirectoryOpen) ||
754 
755  (NodeType( Fcb )) == FAT_NTC_ROOT_DCB) {
756 
758 
759  DebugTrace(-1, Dbg,
760  "FatCommonSetEa -> %08lx\n",
762 
764  }
765  }
766 
767  //
768  // Fat32 does not support ea's.
769  //
770 
771  if (FatIsFat32(Vcb)) {
772 
774  DebugTrace(-1, Dbg,
775  "FatCommonSetEa -> %08lx\n",
778  }
779 
780  //
781  // Reference our input parameters to make things easier
782  //
783 
784  UserBufferLength = IrpSp->Parameters.SetEa.Length;
785 
786  //
787  // Since we ask for no outside help (direct or buffered IO), it
788  // is our responsibility to insulate ourselves from the
789  // deviousness of the user above. Now, buffer and validate the
790  // contents.
791  //
792 
793  Buffer = FatBufferUserBuffer( IrpContext, Irp, UserBufferLength );
794 
795  //
796  // Check the validity of the buffer with the new eas. We really
797  // need to do this always since we don't know, if it was already
798  // buffered, that we buffered and checked it or some overlying
799  // filter buffered without checking.
800  //
801 
803  UserBufferLength,
804  (PULONG)&Irp->IoStatus.Information );
805 
806  if (!NT_SUCCESS( Status )) {
807 
809  DebugTrace(-1, Dbg,
810  "FatCommonSetEa -> %08lx\n",
811  Status);
812  return Status;
813  }
814 
815  //
816  // Acquire exclusive access to the Fcb. If this is a write-through operation
817  // we will need to pick up the other possible streams that can be modified in
818  // this operation so that the locking order is preserved - the root directory
819  // (dirent addition if EA database doesn't already exist) and the parent
820  // directory (addition of the EA handle to the object's dirent).
821  //
822  // We are primarily synchronizing with directory enumeration here.
823  //
824  // If we cannot wait need to send things off to the fsp.
825  //
826 
828 
829  DebugTrace(0, Dbg, "FatCommonSetEa: Set Ea must be waitable\n", 0);
830 
832 
833  DebugTrace(-1, Dbg, "FatCommonSetEa -> %08lx\n", Status );
834 
835  return Status;
836  }
837 
838  //
839  // Set this handle as having modified the file
840  //
841 
842  IrpSp->FileObject->Flags |= FO_FILE_MODIFIED;
843 
844  RtlZeroMemory( &EaSetRange, sizeof( EA_RANGE ));
845 
846  try {
847 
848  ULONG PackedEasLength;
849  BOOLEAN PreviousEas;
850  ULONG AllocationLength;
851  ULONG BytesPerCluster;
853 
855 
856  //
857  // Now go pick up everything
858  //
859 
860  FatAcquireSharedVcb( IrpContext, Fcb->Vcb );
861  AcquiredVcb = TRUE;
862  FatAcquireExclusiveFcb( IrpContext, Fcb );
863  AcquiredFcb = TRUE;
864 
866 
867  if (Fcb->ParentDcb) {
868 
869  FatAcquireExclusiveFcb( IrpContext, Fcb->ParentDcb );
870  AcquiredParentDcb = TRUE;
871  }
872 
873  FatAcquireExclusiveFcb( IrpContext, Fcb->Vcb->RootDcb );
874  AcquiredRootDcb = TRUE;
875  }
876 
877  //
878  // We verify that the Fcb is still valid.
879  //
880 
881  FatVerifyFcb( IrpContext, Fcb );
882 
883  //
884  // We need to get the dirent for the Fcb to recover the Ea handle.
885  //
886 
887  FatGetDirentFromFcbOrDcb( IrpContext, Fcb, &Dirent, &Bcb );
888 
889  DebugTrace(0, Dbg, "FatCommonSetEa: Dirent Address -> %p\n",
890  Dirent );
891  DebugTrace(0, Dbg, "FatCommonSetEa: Dirent Bcb -> %p\n",
892  Bcb);
893 
894  //
895  // If the handle value is 0, then the file has no Eas. In that
896  // case we allocate memory to hold the Eas to be added. If there
897  // are existing Eas for the file, then we must read from the
898  // file and copy the Eas.
899  //
900 
901  ExtendedAttributes = Dirent->ExtendedAttributes;
902 
904 
905  if (ExtendedAttributes == 0) {
906 
907  PreviousEas = FALSE;
908 
909  DebugTrace(0, Dbg,
910  "FatCommonSetEa: File has no current Eas\n", 0 );
911 
912  } else {
913 
914  PreviousEas = TRUE;
915 
916  DebugTrace(0, Dbg, "FatCommonSetEa: File has previous Eas\n", 0 );
917 
918  FatGetEaFile( IrpContext,
919  Vcb,
920  &EaDirent,
921  &EaBcb,
922  FALSE,
923  TRUE );
924 
925  AcquiredEaFcb = TRUE;
926 
927  //
928  // If we didn't get the file then there is an error on
929  // the disk.
930  //
931 
932  if (Vcb->VirtualEaFile == NULL) {
933 
935  try_return( Status );
936  }
937  }
938 
939  DebugTrace(0, Dbg, "FatCommonSetEa: EaBcb -> %p\n", EaBcb);
940 
941  DebugTrace(0, Dbg, "FatCommonSetEa: EaDirent -> %p\n", EaDirent);
942 
943  //
944  // If the file has existing ea's, we need to read them to
945  // determine the size of the buffer allocation.
946  //
947 
948  if (PreviousEas) {
949 
950  //
951  // We need to try to get the Ea set for the desired file.
952  //
953 
955  Vcb,
956  ExtendedAttributes,
957  &Fcb->ShortName.Name.Oem,
958  TRUE,
959  &EaSetRange );
960 
961  PrevEaSetHeader = (PEA_SET_HEADER) EaSetRange.Data;
962 
963  //
964  // We now must allocate pool memory for our copy of the
965  // EaSetHeader and then copy the Ea data into it. At that
966  // time we can unpin the EaSet.
967  //
968 
969  PackedEasLength = GetcbList( PrevEaSetHeader ) - 4;
970 
971  //
972  // Else we will create a dummy EaSetHeader.
973  //
974 
975  } else {
976 
977  PackedEasLength = 0;
978  }
979 
980  BytesPerCluster = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster;
981 
982  AllocationLength = (PackedEasLength
984  + BytesPerCluster - 1)
985  & ~(BytesPerCluster - 1);
986 
987  EaSetHeader = FsRtlAllocatePoolWithTag( PagedPool,
988  AllocationLength,
990 
991  //
992  // Copy the existing Eas over to pool memory.
993  //
994 
995  if (PreviousEas) {
996 
997  RtlCopyMemory( EaSetHeader, PrevEaSetHeader, AllocationLength );
998 
1000 
1001  } else {
1002 
1003  RtlZeroMemory( EaSetHeader, AllocationLength );
1004 
1005  RtlCopyMemory( EaSetHeader->OwnerFileName,
1006  Fcb->ShortName.Name.Oem.Buffer,
1007  Fcb->ShortName.Name.Oem.Length );
1008  }
1009 
1010 
1011  AllocationLength -= SIZE_OF_EA_SET_HEADER;
1012 
1013  DebugTrace(0, Dbg, "FatCommonSetEa: Initial Ea set -> %p\n",
1014  EaSetHeader);
1015 
1016  //
1017  // At this point we have either read in the current eas for the file
1018  // or we have initialized a new empty buffer for the eas. Now for
1019  // each full ea in the input user buffer we do the specified operation
1020  // on the ea
1021  //
1022 
1023  for (FullEa = (PFILE_FULL_EA_INFORMATION) Buffer;
1024  FullEa < (PFILE_FULL_EA_INFORMATION) &Buffer[UserBufferLength];
1025  FullEa = (PFILE_FULL_EA_INFORMATION) (FullEa->NextEntryOffset == 0 ?
1026  &Buffer[UserBufferLength] :
1027  (PUCHAR) FullEa + FullEa->NextEntryOffset)) {
1028 
1029  OEM_STRING EaName;
1030  ULONG Offset;
1031 
1032  EaName.MaximumLength = EaName.Length = FullEa->EaNameLength;
1033  EaName.Buffer = &FullEa->EaName[0];
1034 
1035  DebugTrace(0, Dbg, "FatCommonSetEa: Next Ea name -> %Z\n",
1036  &EaName);
1037 
1038  //
1039  // Make sure the ea name is valid
1040  //
1041 
1042  if (!FatIsEaNameValid( IrpContext,EaName )) {
1043 
1044  Irp->IoStatus.Information = (PUCHAR)FullEa - Buffer;
1046  try_return( Status );
1047  }
1048 
1049  //
1050  // Check that no invalid ea flags are set.
1051  //
1052 
1053  //
1054  // TEMPCODE We are returning STATUS_INVALID_EA_NAME
1055  // until a more appropriate error code exists.
1056  //
1057 
1058  if (FullEa->Flags != 0
1059  && FullEa->Flags != FILE_NEED_EA) {
1060 
1061  Irp->IoStatus.Information = (PUCHAR)FullEa - (PUCHAR)Buffer;
1063  }
1064 
1065  //
1066  // See if we can locate the ea name in the ea set
1067  //
1068 
1070  (PPACKED_EA) EaSetHeader->PackedEas,
1071  PackedEasLength,
1072  &EaName,
1073  &Offset )) {
1074 
1075  DebugTrace(0, Dbg, "FatCommonSetEa: Found Ea name\n", 0);
1076 
1077  //
1078  // We found the ea name so now delete the current entry,
1079  // and if the new ea value length is not zero then we
1080  // replace if with the new ea
1081  //
1082 
1084  EaSetHeader,
1085  &PackedEasLength,
1086  Offset );
1087  }
1088 
1089  if (FullEa->EaValueLength != 0) {
1090 
1092  &EaSetHeader,
1093  &PackedEasLength,
1094  &AllocationLength,
1095  FullEa,
1096  BytesPerCluster );
1097  }
1098  }
1099 
1100  //
1101  // If there are any ea's not removed, we
1102  // call 'AddEaSet' to insert them into the Fat chain.
1103  //
1104 
1105  if (PackedEasLength != 0) {
1106 
1107  LARGE_INTEGER EaOffset;
1108 
1109  EaOffset.HighPart = 0;
1110 
1111  //
1112  // If the packed eas length (plus 4 bytes) is greater
1113  // than the maximum allowed ea size, we return an error.
1114  //
1115 
1116  if (PackedEasLength + 4 > MAXIMUM_EA_SIZE) {
1117 
1118  DebugTrace( 0, Dbg, "Ea length is greater than maximum\n", 0 );
1119 
1121  }
1122 
1123  //
1124  // We need to now read the ea file if we haven't already.
1125  //
1126 
1127  if (EaDirent == NULL) {
1128 
1129  FatGetEaFile( IrpContext,
1130  Vcb,
1131  &EaDirent,
1132  &EaBcb,
1133  TRUE,
1134  TRUE );
1135 
1136  AcquiredEaFcb = TRUE;
1137  }
1138 
1139  FatGetDirentFromFcbOrDcb( IrpContext, Fcb, &Dirent, &Bcb );
1140 
1141  RtlZeroMemory( &EaSetRange, sizeof( EA_RANGE ));
1142 
1143  FatAddEaSet( IrpContext,
1144  Vcb,
1145  PackedEasLength + SIZE_OF_EA_SET_HEADER,
1146  EaBcb,
1147  EaDirent,
1148  &EaHandle,
1149  &EaSetRange );
1150 
1151  NewEaSetHeader = (PEA_SET_HEADER) EaSetRange.Data;
1152 
1153  DebugTrace(0, Dbg, "FatCommonSetEa: Adding an ea set\n", 0);
1154 
1155  //
1156  // Store the length of the new Ea's into the EaSetHeader.
1157  // This is the PackedEasLength + 4.
1158  //
1159 
1160  PackedEasLength += 4;
1161 
1162  CopyU4char( EaSetHeader->cbList, &PackedEasLength );
1163 
1164  //
1165  // Copy all but the first four bytes of EaSetHeader into
1166  // NewEaSetHeader. The signature and index fields have
1167  // already been filled in.
1168  //
1169 
1170  RtlCopyMemory( &NewEaSetHeader->NeedEaCount,
1171  &EaSetHeader->NeedEaCount,
1172  PackedEasLength + SIZE_OF_EA_SET_HEADER - 8 );
1173 
1174  FatMarkEaRangeDirty( IrpContext, Vcb->VirtualEaFile, &EaSetRange );
1176 
1177  CcFlushCache( Vcb->VirtualEaFile->SectionObjectPointer, NULL, 0, NULL );
1178 
1179  } else {
1180 
1181  FatGetDirentFromFcbOrDcb( IrpContext, Fcb, &Dirent, &Bcb );
1182 
1183  EaHandle = 0;
1184  }
1185 
1186  //
1187  // Now we do a wholesale replacement of the ea for the file
1188  //
1189 
1190  if (PreviousEas) {
1191 
1192  FatDeleteEaSet( IrpContext,
1193  Vcb,
1194  EaBcb,
1195  EaDirent,
1196  ExtendedAttributes,
1197  &Fcb->ShortName.Name.Oem );
1198 
1199  CcFlushCache( Vcb->VirtualEaFile->SectionObjectPointer, NULL, 0, NULL );
1200  }
1201 
1202  if (PackedEasLength != 0 ) {
1203 
1205  }
1206 
1207  //
1208  // Mark the dirent with the new ea's
1209  //
1210 
1211  Dirent->ExtendedAttributes = EaHandle;
1212 
1213  FatSetDirtyBcb( IrpContext, Bcb, Vcb, TRUE );
1214 
1215  //
1216  // We call the notify package to report that the ea's were
1217  // modified.
1218  //
1219 
1221  Vcb,
1222  Fcb,
1225 
1226  Irp->IoStatus.Information = 0;
1228 
1229  try_exit: NOTHING;
1230 
1231  //
1232  // Unpin the dirents for the Fcb and EaFcb if necessary.
1233  //
1234 
1237 
1239 
1240  } finally {
1241 
1243 
1244  //
1245  // If this is an abnormal termination, we need to clean up
1246  // any locked resources.
1247  //
1248 
1249  if (AbnormalTermination()) {
1250 
1251  //
1252  // Unpin the dirents for the Fcb, EaFcb and EaSetFcb if necessary.
1253  //
1254 
1257 
1259  }
1260 
1261  //
1262  // Release the Fcbs/Vcb acquired.
1263  //
1264 
1265  if (AcquiredEaFcb) {
1266  FatReleaseFcb( IrpContext, Vcb->EaFcb );
1267  }
1268 
1269  if (AcquiredFcb) {
1271  }
1272 
1273  if (AcquiredParentDcb) {
1275  }
1276 
1277  if (AcquiredRootDcb) {
1279  }
1280 
1281  if (AcquiredVcb) {
1283  }
1284 
1285  //
1286  // Deallocate our Ea buffer.
1287  //
1288 
1289  if (EaSetHeader != NULL) {
1290 
1291  ExFreePool( EaSetHeader );
1292  }
1293 
1294  //
1295  // Complete the irp.
1296  //
1297 
1298  if (!AbnormalTermination()) {
1299 
1301  }
1302 
1303  DebugTrace(-1, Dbg, "FatCommonSetEa -> %08lx\n", Status);
1304  }
1305 
1306  //
1307  // And return to our caller
1308  //
1309 
1310  return Status;
1311 #endif
1312 }
1313 
1314 
1315 #if 0
1316 
1317 //
1318 // Local Support Routine
1319 //
1320 
1324  OUT PCCB Ccb,
1325  IN PPACKED_EA FirstPackedEa,
1326  IN ULONG PackedEasLength,
1327  OUT PUCHAR UserBuffer,
1328  IN ULONG UserBufferLength,
1329  IN PUCHAR UserEaList,
1330  IN ULONG UserEaListLength,
1332  )
1333 
1334 /*++
1335 
1336 Routine Description:
1337 
1338  This routine is the work routine for querying EAs given an ea index
1339 
1340 Arguments:
1341 
1342  Ccb - Supplies the Ccb for the query
1343 
1344  FirstPackedEa - Supplies the first ea for the file being queried
1345 
1346  PackedEasLength - Supplies the length of the ea data
1347 
1348  UserBuffer - Supplies the buffer to receive the full eas
1349 
1350  UserBufferLength - Supplies the length, in bytes, of the user buffer
1351 
1352  UserEaList - Supplies the user specified ea name list
1353 
1354  UserEaListLength - Supplies the length, in bytes, of the user ea list
1355 
1356  ReturnSingleEntry - Indicates if we are to return a single entry or not
1357 
1358 Return Value:
1359 
1360  IO_STATUS_BLOCK - Receives the completion status for the operation
1361 
1362 --*/
1363 
1364 {
1366 
1367  ULONG Offset;
1368  ULONG RemainingUserBufferLength;
1369 
1370  PPACKED_EA PackedEa;
1371  ULONG PackedEaSize;
1372 
1373  PFILE_FULL_EA_INFORMATION LastFullEa = NULL;
1374  ULONG LastFullEaSize;
1375  PFILE_FULL_EA_INFORMATION NextFullEa;
1376 
1378 
1379  BOOLEAN Overflow;
1380 
1381  DebugTrace(+1, Dbg, "FatQueryEaUserEaList...\n", 0);
1382 
1383  LastFullEa = NULL;
1384  NextFullEa = (PFILE_FULL_EA_INFORMATION) UserBuffer;
1385  RemainingUserBufferLength = UserBufferLength;
1386 
1387  Overflow = FALSE;
1388 
1389  for (GetEa = (PFILE_GET_EA_INFORMATION) &UserEaList[0];
1390  GetEa < (PFILE_GET_EA_INFORMATION) ((PUCHAR) UserEaList
1391  + UserEaListLength);
1392  GetEa = (GetEa->NextEntryOffset == 0
1394  : (PFILE_GET_EA_INFORMATION) ((PUCHAR) GetEa
1395  + GetEa->NextEntryOffset))) {
1396 
1397  OEM_STRING Str;
1398  OEM_STRING OutputEaName;
1399 
1400  DebugTrace(0, Dbg, "Top of loop, GetEa = %p\n", GetEa);
1401  DebugTrace(0, Dbg, "LastFullEa = %p\n", LastFullEa);
1402  DebugTrace(0, Dbg, "NextFullEa = %p\n", NextFullEa);
1403  DebugTrace(0, Dbg, "RemainingUserBufferLength = %08lx\n", RemainingUserBufferLength);
1404 
1405  //
1406  // Make a string reference to the GetEa and see if we can
1407  // locate the ea by name
1408  //
1409 
1410  Str.MaximumLength = Str.Length = GetEa->EaNameLength;
1411  Str.Buffer = &GetEa->EaName[0];
1412 
1413  //
1414  // Check for a valid name.
1415  //
1416 
1417  if (!FatIsEaNameValid( IrpContext, Str )) {
1418 
1419  DebugTrace(-1, Dbg,
1420  "FatQueryEaUserEaList: Invalid Ea Name -> %Z\n",
1421  &Str);
1422 
1423  Iosb.Information = (PUCHAR)GetEa - UserEaList;
1424  Iosb.Status = STATUS_INVALID_EA_NAME;
1425  return Iosb;
1426  }
1427 
1428  //
1429  // If this is a duplicate name, we skip to the next.
1430  //
1431 
1432  if (FatIsDuplicateEaName( IrpContext, GetEa, UserEaList )) {
1433 
1434  DebugTrace(0, Dbg, "FatQueryEaUserEaList: Duplicate name\n", 0);
1435  continue;
1436  }
1437 
1439  FirstPackedEa,
1440  PackedEasLength,
1441  &Str,
1442  &Offset )) {
1443 
1444  Offset = 0xffffffff;
1445 
1446  DebugTrace(0, Dbg, "Need to dummy up an ea\n", 0);
1447 
1448  //
1449  // We were not able to locate the name therefore we must
1450  // dummy up a entry for the query. The needed Ea size is
1451  // the size of the name + 4 (next entry offset) + 1 (flags)
1452  // + 1 (name length) + 2 (value length) + the name length +
1453  // 1 (null byte).
1454  //
1455 
1456  if ((ULONG)(4+1+1+2+GetEa->EaNameLength+1)
1457  > RemainingUserBufferLength) {
1458 
1459  Overflow = TRUE;
1460  break;
1461  }
1462 
1463  //
1464  // Everything is going to work fine, so copy over the name,
1465  // set the name length and zero out the rest of the ea.
1466  //
1467 
1468  NextFullEa->NextEntryOffset = 0;
1469  NextFullEa->Flags = 0;
1470  NextFullEa->EaNameLength = GetEa->EaNameLength;
1471  NextFullEa->EaValueLength = 0;
1472  RtlCopyMemory( &NextFullEa->EaName[0],
1473  &GetEa->EaName[0],
1474  GetEa->EaNameLength );
1475 
1476  //
1477  // Upcase the name in the buffer.
1478  //
1479 
1480  OutputEaName.MaximumLength = OutputEaName.Length = Str.Length;
1481  OutputEaName.Buffer = NextFullEa->EaName;
1482 
1483  FatUpcaseEaName( IrpContext, &OutputEaName, &OutputEaName );
1484 
1485  NextFullEa->EaName[GetEa->EaNameLength] = 0;
1486 
1487  } else {
1488 
1489  DebugTrace(0, Dbg, "Located the ea, Offset = %08lx\n", Offset);
1490 
1491  //
1492  // We were able to locate the packed ea
1493  // Reference the packed ea
1494  //
1495 
1496  PackedEa = (PPACKED_EA) ((PUCHAR) FirstPackedEa + Offset);
1497  SizeOfPackedEa( PackedEa, &PackedEaSize );
1498 
1499  DebugTrace(0, Dbg, "PackedEaSize = %08lx\n", PackedEaSize);
1500 
1501  //
1502  // We know that the packed ea is 4 bytes smaller than its
1503  // equivalent full ea so we need to check the remaining
1504  // user buffer length against the computed full ea size.
1505  //
1506 
1507  if (PackedEaSize + 4 > RemainingUserBufferLength) {
1508 
1509  Overflow = TRUE;
1510  break;
1511  }
1512 
1513  //
1514  // Everything is going to work fine, so copy over the packed
1515  // ea to the full ea and zero out the next entry offset field.
1516  //
1517 
1518  RtlCopyMemory( &NextFullEa->Flags,
1519  &PackedEa->Flags,
1520  PackedEaSize );
1521 
1522  NextFullEa->NextEntryOffset = 0;
1523  }
1524 
1525  //
1526  // At this point we've copied a new full ea into the next full ea
1527  // location. So now go back and set the set full eas entry offset
1528  // field to be the difference between out two pointers.
1529  //
1530 
1531  if (LastFullEa != NULL) {
1532 
1533  LastFullEa->NextEntryOffset = (ULONG)((PUCHAR) NextFullEa
1534  - (PUCHAR) LastFullEa);
1535  }
1536 
1537  //
1538  // Set the last full ea to the next full ea, compute
1539  // where the next full should be, and decrement the remaining user
1540  // buffer length appropriately
1541  //
1542 
1543  LastFullEa = NextFullEa;
1544  LastFullEaSize = LongAlign( SizeOfFullEa( LastFullEa ));
1545  RemainingUserBufferLength -= LastFullEaSize;
1546  NextFullEa = (PFILE_FULL_EA_INFORMATION) ((PUCHAR) NextFullEa
1547  + LastFullEaSize);
1548 
1549  //
1550  // Remember the offset of the next ea in case we're asked to
1551  // resume the iteration
1552  //
1553 
1554  Ccb->OffsetOfNextEaToReturn = FatLocateNextEa( IrpContext,
1555  FirstPackedEa,
1556  PackedEasLength,
1557  Offset );
1558 
1559  //
1560  // If we were to return a single entry then break out of our loop
1561  // now
1562  //
1563 
1564  if (ReturnSingleEntry) {
1565 
1566  break;
1567  }
1568  }
1569 
1570  //
1571  // Now we've iterated all that can and we've exited the preceding loop
1572  // with either all, some or no information stored in the return buffer.
1573  // We can decide if we got everything to fit by checking the local
1574  // Overflow variable
1575  //
1576 
1577  if (Overflow) {
1578 
1579  Iosb.Information = 0;
1580  Iosb.Status = STATUS_BUFFER_OVERFLOW;
1581 
1582  } else {
1583 
1584  //
1585  // Otherwise we've been successful in returing at least one
1586  // ea so we'll compute the number of bytes used to store the
1587  // full ea information. The number of bytes used is the difference
1588  // between the LastFullEa and the start of the buffer, and the
1589  // non-aligned size of the last full ea.
1590  //
1591 
1592  Iosb.Information = ((PUCHAR) LastFullEa - UserBuffer)
1593  + SizeOfFullEa(LastFullEa);
1594 
1595  Iosb.Status = STATUS_SUCCESS;
1596  }
1597 
1598  DebugTrace(-1, Dbg, "FatQueryEaUserEaList -> Iosb.Status = %08lx\n",
1599  Iosb.Status);
1600 
1601  return Iosb;
1602 }
1603 
1604 
1605 //
1606 // Local Support Routine
1607 //
1608 
1612  OUT PCCB Ccb,
1613  IN PPACKED_EA FirstPackedEa,
1614  IN ULONG PackedEasLength,
1615  OUT PUCHAR UserBuffer,
1616  IN ULONG UserBufferLength,
1617  IN ULONG UserEaIndex,
1619  )
1620 
1621 /*++
1622 
1623 Routine Description:
1624 
1625  This routine is the work routine for querying EAs given an ea index
1626 
1627 Arguments:
1628 
1629  Ccb - Supplies the Ccb for the query
1630 
1631  FirstPackedEa - Supplies the first ea for the file being queried
1632 
1633  PackedEasLength - Supplies the length of the ea data
1634 
1635  UserBuffer - Supplies the buffer to receive the full eas
1636 
1637  UserBufferLength - Supplies the length, in bytes, of the user buffer
1638 
1639  UserEaIndex - Supplies the index of the first ea to return.
1640 
1641  RestartScan - Indicates if the first item to return is at the
1642  beginning of the packed ea list or if we should resume our
1643  previous iteration
1644 
1645 Return Value:
1646 
1647  IO_STATUS_BLOCK - Receives the completion status for the operation
1648 
1649 --*/
1650 
1651 {
1653 
1654  ULONG i;
1655  ULONG Offset;
1656 
1657  DebugTrace(+1, Dbg, "FatQueryEaIndexSpecified...\n", 0);
1658 
1659  //
1660  // Zero out the information field of the iosb
1661  //
1662 
1663  Iosb.Information = 0;
1664 
1665  //
1666  // If the index value is zero or there are no Eas on the file, then
1667  // the specified index can't be returned.
1668  //
1669 
1670  if (UserEaIndex == 0
1671  || PackedEasLength == 0) {
1672 
1673  DebugTrace( -1, Dbg, "FatQueryEaIndexSpecified: Non-existant entry\n", 0 );
1674 
1676 
1677  return Iosb;
1678  }
1679 
1680  //
1681  // Iterate the eas until we find the index we're after.
1682  //
1683 
1684  for (i = 1, Offset = 0;
1685  (i < UserEaIndex) && (Offset < PackedEasLength);
1687  FirstPackedEa,
1688  PackedEasLength, Offset )) {
1689 
1690  NOTHING;
1691  }
1692 
1693  //
1694  // Make sure the offset we're given to the ea is a real offset otherwise
1695  // the ea doesn't exist
1696  //
1697 
1698  if (Offset >= PackedEasLength) {
1699 
1700  //
1701  // If we just passed the last Ea, we will return STATUS_NO_MORE_EAS.
1702  // This is for the caller who may be enumerating the Eas.
1703  //
1704 
1705  if (i == UserEaIndex) {
1706 
1707  Iosb.Status = STATUS_NO_MORE_EAS;
1708 
1709  //
1710  // Otherwise we report that this is a bad ea index.
1711  //
1712 
1713  } else {
1714 
1716  }
1717 
1718  DebugTrace(-1, Dbg, "FatQueryEaIndexSpecified -> %08lx\n", Iosb.Status);
1719  return Iosb;
1720  }
1721 
1722  //
1723  // We now have the offset of the first Ea to return to the user.
1724  // We simply call our EaSimpleScan routine to do the actual work.
1725  //
1726 
1728  Ccb,
1729  FirstPackedEa,
1730  PackedEasLength,
1731  UserBuffer,
1732  UserBufferLength,
1734  Offset );
1735 
1736  DebugTrace(-1, Dbg, "FatQueryEaIndexSpecified -> %08lx\n", Iosb.Status);
1737 
1738  return Iosb;
1739 
1740 }
1741 
1742 
1743 //
1744 // Local Support Routine
1745 //
1746 
1750  OUT PCCB Ccb,
1751  IN PPACKED_EA FirstPackedEa,
1752  IN ULONG PackedEasLength,
1753  OUT PUCHAR UserBuffer,
1754  IN ULONG UserBufferLength,
1756  ULONG StartOffset
1757  )
1758 
1759 /*++
1760 
1761 Routine Description:
1762 
1763  This routine is the work routine for querying EAs from the beginning of
1764  the ea list.
1765 
1766 Arguments:
1767 
1768  Ccb - Supplies the Ccb for the query
1769 
1770  FirstPackedEa - Supplies the first ea for the file being queried
1771 
1772  PackedEasLength - Supplies the length of the ea data
1773 
1774  UserBuffer - Supplies the buffer to receive the full eas
1775 
1776  UserBufferLength - Supplies the length, in bytes, of the user buffer
1777 
1778  ReturnSingleEntry - Indicates if we are to return a single entry or not
1779 
1780  StartOffset - Indicates the offset within the Ea data to return the
1781  first block of data.
1782 
1783 Return Value:
1784 
1785  IO_STATUS_BLOCK - Receives the completion status for the operation
1786 
1787 --*/
1788 
1789 {
1791 
1792  ULONG RemainingUserBufferLength;
1793 
1794  PPACKED_EA PackedEa;
1795  ULONG PackedEaSize;
1796 
1797  PFILE_FULL_EA_INFORMATION LastFullEa;
1798  ULONG LastFullEaSize;
1799  PFILE_FULL_EA_INFORMATION NextFullEa;
1800  BOOLEAN BufferOverflow = FALSE;
1801 
1802 
1803  DebugTrace(+1, Dbg, "FatQueryEaSimpleScan...\n", 0);
1804 
1805  //
1806  // Zero out the information field in the Iosb
1807  //
1808 
1809  Iosb.Information = 0;
1810 
1811  LastFullEa = NULL;
1812  NextFullEa = (PFILE_FULL_EA_INFORMATION) UserBuffer;
1813  RemainingUserBufferLength = UserBufferLength;
1814 
1815  while (StartOffset < PackedEasLength) {
1816 
1817  DebugTrace(0, Dbg, "Top of loop, Offset = %08lx\n", StartOffset);
1818  DebugTrace(0, Dbg, "LastFullEa = %p\n", LastFullEa);
1819  DebugTrace(0, Dbg, "NextFullEa = %p\n", NextFullEa);
1820  DebugTrace(0, Dbg, "RemainingUserBufferLength = %08lx\n", RemainingUserBufferLength);
1821 
1822  //
1823  // Reference the packed ea of interest.
1824  //
1825 
1826  PackedEa = (PPACKED_EA) ((PUCHAR) FirstPackedEa + StartOffset);
1827 
1828  SizeOfPackedEa( PackedEa, &PackedEaSize );
1829 
1830  DebugTrace(0, Dbg, "PackedEaSize = %08lx\n", PackedEaSize);
1831 
1832  //
1833  // We know that the packed ea is 4 bytes smaller than its
1834  // equivalent full ea so we need to check the remaining
1835  // user buffer length against the computed full ea size.
1836  //
1837 
1838  if (PackedEaSize + 4 > RemainingUserBufferLength) {
1839 
1840  BufferOverflow = TRUE;
1841  break;
1842  }
1843 
1844  //
1845  // Everything is going to work fine, so copy over the packed
1846  // ea to the full ea and zero out the next entry offset field.
1847  // Then go back and set the last full eas entry offset field
1848  // to be the difference between the two pointers.
1849  //
1850 
1851  RtlCopyMemory( &NextFullEa->Flags, &PackedEa->Flags, PackedEaSize );
1852  NextFullEa->NextEntryOffset = 0;
1853 
1854  if (LastFullEa != NULL) {
1855 
1856  LastFullEa->NextEntryOffset = (ULONG)((PUCHAR) NextFullEa
1857  - (PUCHAR) LastFullEa);
1858  }
1859 
1860  //
1861  // Set the last full ea to the next full ea, compute
1862  // where the next full should be, and decrement the remaining user
1863  // buffer length appropriately
1864  //
1865 
1866  LastFullEa = NextFullEa;
1867  LastFullEaSize = LongAlign( SizeOfFullEa( LastFullEa ));
1868  RemainingUserBufferLength -= LastFullEaSize;
1869  NextFullEa = (PFILE_FULL_EA_INFORMATION) ((PUCHAR) NextFullEa
1870  + LastFullEaSize);
1871 
1872  //
1873  // Remember the offset of the next ea in case we're asked to
1874  // resume the teration
1875  //
1876 
1877  StartOffset = FatLocateNextEa( IrpContext,
1878  FirstPackedEa,
1879  PackedEasLength,
1880  StartOffset );
1881 
1882  Ccb->OffsetOfNextEaToReturn = StartOffset;
1883 
1884  //
1885  // If we were to return a single entry then break out of our loop
1886  // now
1887  //
1888 
1889  if (ReturnSingleEntry) {
1890 
1891  break;
1892  }
1893  }
1894 
1895  //
1896  // Now we've iterated all that can and we've exited the preceding loop
1897  // with either some or no information stored in the return buffer.
1898  // We can decide which it is by checking if the last full ea is null
1899  //
1900 
1901  if (LastFullEa == NULL) {
1902 
1903  Iosb.Information = 0;
1904 
1905  //
1906  // We were not able to return a single ea entry, now we need to find
1907  // out if it is because we didn't have an entry to return or the
1908  // buffer is too small. If the Offset variable is less than
1909  // PackedEaList->UsedSize then the user buffer is too small
1910  //
1911 
1912  if (PackedEasLength == 0) {
1913 
1914  Iosb.Status = STATUS_NO_EAS_ON_FILE;
1915 
1916  } else if (StartOffset >= PackedEasLength) {
1917 
1918  Iosb.Status = STATUS_NO_MORE_EAS;
1919 
1920  } else {
1921 
1922  Iosb.Status = STATUS_BUFFER_TOO_SMALL;
1923  }
1924 
1925  } else {
1926 
1927  //
1928  // Otherwise we've been successful in returing at least one
1929  // ea so we'll compute the number of bytes used to store the
1930  // full ea information. The number of bytes used is the difference
1931  // between the LastFullEa and the start of the buffer, and the
1932  // non-aligned size of the last full ea.
1933  //
1934 
1935  Iosb.Information = ((PUCHAR) LastFullEa - UserBuffer)
1936  + SizeOfFullEa( LastFullEa );
1937 
1938  //
1939  // If there are more to return, report the buffer was too small.
1940  // Otherwise return STATUS_SUCCESS.
1941  //
1942 
1943  if (BufferOverflow) {
1944 
1945  Iosb.Status = STATUS_BUFFER_OVERFLOW;
1946 
1947  } else {
1948 
1949  Iosb.Status = STATUS_SUCCESS;
1950  }
1951  }
1952 
1953  DebugTrace(-1, Dbg, "FatQueryEaSimpleScan -> Iosb.Status = %08lx\n",
1954  Iosb.Status);
1955 
1956  return Iosb;
1957 
1958 }
1959 
1960 
1961 //
1962 // Local Support Routine
1963 //
1964 
1965 BOOLEAN
1969  IN PUCHAR UserBuffer
1970  )
1971 
1972 /*++
1973 
1974 Routine Description:
1975 
1976  This routine walks through a list of ea names to find a duplicate name.
1977  'GetEa' is an actual position in the list. We are only interested in
1978  previous matching ea names, as the ea information for that ea name
1979  would have been returned with the previous instance.
1980 
1981 Arguments:
1982 
1983  GetEa - Supplies the Ea name structure for the ea name to match.
1984 
1985  UserBuffer - Supplies a pointer to the user buffer with the list
1986  of ea names to search for.
1987 
1988 Return Value:
1989 
1990  BOOLEAN - TRUE if a previous match is found, FALSE otherwise.
1991 
1992 --*/
1993 
1994 {
1995  PFILE_GET_EA_INFORMATION ThisGetEa;
1996 
1997  BOOLEAN DuplicateFound;
1998  OEM_STRING EaString;
1999 
2000  DebugTrace(+1, Dbg, "FatIsDuplicateEaName...\n", 0);
2001 
2002  EaString.MaximumLength = EaString.Length = GetEa->EaNameLength;
2003  EaString.Buffer = &GetEa->EaName[0];
2004 
2005  FatUpcaseEaName( IrpContext, &EaString, &EaString );
2006 
2007  DuplicateFound = FALSE;
2008 
2009  for (ThisGetEa = (PFILE_GET_EA_INFORMATION) &UserBuffer[0];
2010  ThisGetEa < GetEa
2011  && ThisGetEa->NextEntryOffset != 0;
2012  ThisGetEa = (PFILE_GET_EA_INFORMATION) ((PUCHAR) ThisGetEa
2013  + ThisGetEa->NextEntryOffset)) {
2014 
2015  OEM_STRING Str;
2016 
2017  DebugTrace(0, Dbg, "Top of loop, ThisGetEa = %p\n", ThisGetEa);
2018 
2019  //
2020  // Make a string reference to the GetEa and see if we can
2021  // locate the ea by name
2022  //
2023 
2024  Str.MaximumLength = Str.Length = ThisGetEa->EaNameLength;
2025  Str.Buffer = &ThisGetEa->EaName[0];
2026 
2027  DebugTrace(0, Dbg, "FatIsDuplicateEaName: Next Name -> %Z\n", &Str);
2028 
2029  if ( FatAreNamesEqual(IrpContext, Str, EaString) ) {
2030 
2031  DebugTrace(0, Dbg, "FatIsDuplicateEaName: Duplicate found\n", 0);
2032  DuplicateFound = TRUE;
2033  break;
2034  }
2035  }
2036 
2037  DebugTrace(-1, Dbg, "FatIsDuplicateEaName: Exit -> %04x\n", DuplicateFound);
2038 
2039  return DuplicateFound;
2040 }
2041 #endif
2042 
2043 
#define STATUS_EAS_NOT_SUPPORTED
Definition: ntstatus.h:301
#define IN
Definition: typedefs.h:38
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
UCHAR Flags
Definition: fat.h:695
IO_STATUS_BLOCK FatQueryEaSimpleScan(IN PIRP_CONTEXT IrpContext, OUT PCCB Ccb, IN PPACKED_EA FirstPackedEa, IN ULONG PackedEasLength, OUT PUCHAR UserBuffer, IN ULONG UserBufferLength, IN BOOLEAN ReturnSingleEntry, ULONG StartOffset)
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1221
#define FsRtlEnterFileSystem
BOOLEAN FatIsIrpTopLevel(IN PIRP Irp)
Definition: fatdata.c:817
IN PVCB IN VBO IN ULONG OUT PBCB * Bcb
Definition: fatprocs.h:402
PVOID FatMapUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp)
Definition: deviosup.c:3369
IO_STATUS_BLOCK FatQueryEaIndexSpecified(IN PIRP_CONTEXT IrpContext, OUT PCCB Ccb, IN PPACKED_EA FirstPackedEa, IN ULONG PackedEasLength, OUT PUCHAR UserBuffer, IN ULONG UserBufferLength, IN ULONG UserEaIndex, IN BOOLEAN ReturnSingleEntry)
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ BOOLEAN _In_ ULONG _In_opt_ PULONG _In_ BOOLEAN RestartScan
Definition: fltkernel.h:2298
#define AbnormalTermination()
Definition: exception.h:73
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
#define SL_INDEX_SPECIFIED
Definition: iotypes.h:1794
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
#define FsRtlExitFileSystem
struct _FILE_FULL_EA_INFORMATION * PFILE_FULL_EA_INFORMATION
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2621
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
IO_STATUS_BLOCK FatQueryEaUserEaList(IN PIRP_CONTEXT IrpContext, OUT PCCB Ccb, IN PPACKED_EA FirstPackedEa, IN ULONG PackedEasLength, OUT PUCHAR UserBuffer, IN ULONG UserBufferLength, IN PUCHAR UserEaList, IN ULONG UserEaListLength, IN BOOLEAN ReturnSingleEntry)
Definition: cdstruc.h:908
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define IRP_CONTEXT_FLAG_WRITE_THROUGH
Definition: ext2fs.h:1079
VOID FatUnpinRepinnedBcbs(IN PIRP_CONTEXT IrpContext)
Definition: cachesup.c:1407
Definition: cdstruc.h:1073
unsigned char * PUCHAR
Definition: retypes.h:3
#define Dbg
Definition: ea.c:23
BOOLEAN FatIsEaNameValid(IN PIRP_CONTEXT IrpContext, IN OEM_STRING Name)
Definition: easup.c:3429
#define SizeOfPackedEa(EA, SIZE)
Definition: fat.h:738
#define FatNotifyReportChange(I, V, F, FL, A)
Definition: fatprocs.h:2156
VOID FatMarkEaRangeDirty(IN PIRP_CONTEXT IrpContext, IN PFILE_OBJECT EaFileObject, IN OUT PEA_RANGE EaRange)
Definition: easup.c:3709
LONG NTSTATUS
Definition: precomp.h:26
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
struct _FILE_GET_EA_INFORMATION * PFILE_GET_EA_INFORMATION
#define STATUS_NO_EAS_ON_FILE
Definition: ntstatus.h:304
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ BOOLEAN ReturnSingleEntry
Definition: fltkernel.h:2295
PEXT2_IRP_CONTEXT IrpContext
Definition: ext4_xattr.h:141
VOID FatUnpinEaRange(IN PIRP_CONTEXT IrpContext, IN OUT PEA_RANGE EaRange)
Definition: easup.c:3782
union _FILE_NAME_NODE::@692 Name
#define MAXIMUM_EA_SIZE
Definition: fat.h:676
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
Definition: cdstruc.h:504
IN PVCB IN PUCHAR IN ULONG IN POEM_STRING OUT PUSHORT EaHandle
Definition: fatprocs.h:884
ULONG Flags
Definition: ext2fs.h:1044
#define CopyU4char(Dst, Src)
Definition: fatprocs.h:2141
STRING OEM_STRING
Definition: umtypes.h:203
PVOID FatBufferUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp, IN ULONG BufferLength)
Definition: deviosup.c:3427
struct _FCB * ParentDcb
Definition: fatstruc.h:835
ULONG EaModificationCount
Definition: fatstruc.h:1106
#define PAGED_CODE()
Definition: video.h:57
NTSTATUS FatCommonSetEa(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: ea.c:659
BOOLEAN FatIsDuplicateEaName(IN PIRP_CONTEXT IrpContext, IN PFILE_GET_EA_INFORMATION GetEa, IN PUCHAR UserBuffer)
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
_SEH2_TRY
Definition: create.c:4250
IN PFCB IN PCCB IN TYPE_OF_OPEN IN BOOLEAN IN BOOLEAN TopLevel
Definition: fatprocs.h:2401
#define STATUS_EA_TOO_LARGE
Definition: ntstatus.h:302
IN OUT PVCB OUT PDIRENT * EaDirent
Definition: fatprocs.h:904
VOID FatReadEaSet(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN USHORT EaHandle, IN POEM_STRING FileName, IN BOOLEAN ReturnEntireSet, OUT PEA_RANGE EaSetRange)
Definition: easup.c:1306
#define FO_FILE_MODIFIED
Definition: iotypes.h:1745
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define IRP_MJ_SET_EA
#define FILE_ACTION_MODIFIED
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define FatUnpinBcb(IRPCONTEXT, BCB)
Definition: fatprocs.h:537
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS NTAPI IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: util.c:191
#define SizeOfFullEa(EA)
Definition: fatprocs.h:1021
UCHAR OwnerFileName[14]
Definition: fat.h:667
NTSTATUS FatCommonQueryEa(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: ea.c:250
Definition: bufpool.h:45
#define MAXUINT_PTR
Definition: basetsd.h:100
NodeType
Definition: Node.h:5
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2300
#define FILE_NEED_EA
#define STATUS_NO_MORE_EAS
Definition: ntstatus.h:186
OEM_STRING Oem
Definition: fatstruc.h:692
#define IRP_MJ_QUERY_EA
#define GetExceptionCode()
Definition: exception.h:65
#define DebugUnwind(X)
Definition: fatdata.h:315
#define FatReleaseFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1635
return Iosb
Definition: create.c:4426
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define try_return(S)
Definition: cdprocs.h:2189
#define STATUS_NONEXISTENT_EA_ENTRY
Definition: ntstatus.h:303
struct _FCB * RootDcb
Definition: fatstruc.h:284
IN PVCB IN ULONG IN PBCB OUT PDIRENT OUT PUSHORT OUT PEA_RANGE EaSetRange
Definition: fatprocs.h:936
#define Vcb
Definition: cdprocs.h:1425
VOID FatAppendPackedEa(IN PIRP_CONTEXT IrpContext, IN OUT PEA_SET_HEADER *EaSetHeader, IN OUT PULONG PackedEasLength, IN OUT PULONG AllocationLength, IN PFILE_FULL_EA_INFORMATION FullEa, IN ULONG BytesPerCluster)
Definition: easup.c:2967
_Function_class_(IRP_MJ_QUERY_EA)
Definition: ea.c:87
#define FatUpcaseEaName(IRPCONTEXT, NAME, UPCASEDNAME)
Definition: fatprocs.h:859
#define _Inout_
Definition: no_sal2.h:244
#define CanFsdWait(I)
Definition: cdprocs.h:2011
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
EA_SET_HEADER * PEA_SET_HEADER
Definition: fat.h:672
#define except(x)
Definition: btrfs_drv.h:135
enum _TYPE_OF_OPEN TYPE_OF_OPEN
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:593
#define NOTHING
Definition: env_spec_w32.h:461
PACKED_EA * PPACKED_EA
Definition: fat.h:700
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define STATUS_INVALID_EA_NAME
Definition: ntstatus.h:187
#define FatAreNamesEqual(IRPCONTEXT, NAMEA, NAMEB)
Definition: fatprocs.h:1149
DRIVER_DISPATCH(nfs41_FsdDispatch)
#define FatIsFat32(VCB)
Definition: fatprocs.h:1437
#define LongAlign(Ptr)
Definition: cdprocs.h:1573
BOOLEAN FatLocateEaByName(IN PIRP_CONTEXT IrpContext, IN PPACKED_EA FirstPackedEa, IN ULONG PackedEasLength, IN POEM_STRING EaName, OUT PULONG Offset)
Definition: easup.c:3344
Status
Definition: gdiplustypes.h:24
#define _In_
Definition: no_sal2.h:204
ULONG32 NeedEaCount
Definition: fat.h:666
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
#define SL_RETURN_SINGLE_ENTRY
Definition: iotypes.h:1793
_SEH2_END
Definition: create.c:4424
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
#define FILE_NOTIFY_CHANGE_EA
unsigned short USHORT
Definition: pedump.c:61
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
ULONG FatLocateNextEa(IN PIRP_CONTEXT IrpContext, IN PPACKED_EA FirstPackedEa, IN ULONG PackedEasLength, IN ULONG PreviousOffset)
Definition: easup.c:3257
unsigned int * PULONG
Definition: retypes.h:1
#define FatReleaseVcb(IRPCONTEXT, Vcb)
Definition: fatprocs.h:1631
#define SL_RESTART_SCAN
Definition: iotypes.h:1792
UCHAR PackedEas[1]
Definition: fat.h:670
UCHAR cbList[4]
Definition: fat.h:669
NTSTATUS FatFsdPostRequest(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:229
#define OUT
Definition: typedefs.h:39
#define GetcbList(EASET)
Definition: fat.h:678
unsigned int ULONG
Definition: retypes.h:1
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
Definition: cdprocs.h:429
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
PVCB Vcb
Definition: cdstruc.h:939
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define TAG_EA_SET_HEADER
Definition: nodetype.h:161
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
_In_ PFCB Fcb
Definition: cdprocs.h:151
IN OUT PVCB OUT PDIRENT OUT PBCB * EaBcb
Definition: fatprocs.h:904
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define STATUS_EA_CORRUPT_ERROR
Definition: ntstatus.h:305
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1114
#define SIZE_OF_EA_SET_HEADER
Definition: fat.h:674
TYPE_OF_OPEN FatDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Outptr_ PVCB *Vcb, _Outptr_ PFCB *FcbOrDcb, _Outptr_ PCCB *Ccb)
Definition: filobsup.c:176
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
VOID FatDeletePackedEa(IN PIRP_CONTEXT IrpContext, IN OUT PEA_SET_HEADER EaSetHeader, IN OUT PULONG PackedEasLength, IN ULONG Offset)
Definition: easup.c:3148