ReactOS 0.4.15-dev-7998-gdb93cb1
ea.c File Reference
#include "fatprocs.h"
Include dependency graph for ea.c:

Go to the source code of this file.

Macros

#define Dbg   (DEBUG_TRACE_EA)
 

Functions

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)
 
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)
 
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)
 
BOOLEAN FatIsDuplicateEaName (IN PIRP_CONTEXT IrpContext, IN PFILE_GET_EA_INFORMATION GetEa, IN PUCHAR UserBuffer)
 
 _Function_class_ (IRP_MJ_QUERY_EA)
 
 _Function_class_ (IRP_MJ_SET_EA)
 
NTSTATUS FatCommonQueryEa (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
 
NTSTATUS FatCommonSetEa (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
 

Macro Definition Documentation

◆ Dbg

#define Dbg   (DEBUG_TRACE_EA)

Definition at line 23 of file ea.c.

Function Documentation

◆ _Function_class_() [1/2]

_Function_class_ ( IRP_MJ_QUERY_EA  )

Definition at line 87 of file ea.c.

116{
118 PIRP_CONTEXT IrpContext = NULL;
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
136 IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
137
138 Status = FatCommonQueryEa( IrpContext, Irp );
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}
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define CanFsdWait(I)
Definition: cdprocs.h:2001
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
NTSTATUS FatCommonQueryEa(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: ea.c:250
#define Dbg
Definition: ea.c:23
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
BOOLEAN FatIsIrpTopLevel(IN PIRP Irp)
Definition: fatdata.c:817
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
IN PFCB IN PCCB IN TYPE_OF_OPEN IN BOOLEAN IN BOOLEAN TopLevel
Definition: fatprocs.h:2417
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2301
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
Status
Definition: gdiplustypes.h:25
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:158

◆ _Function_class_() [2/2]

_Function_class_ ( IRP_MJ_SET_EA  )

Definition at line 168 of file ea.c.

197{
199 PIRP_CONTEXT IrpContext = NULL;
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
217 IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
218
219 Status = FatCommonSetEa( IrpContext, Irp );
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}
NTSTATUS FatCommonSetEa(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: ea.c:659

◆ FatCommonQueryEa()

NTSTATUS FatCommonQueryEa ( IN PIRP_CONTEXT  IrpContext,
IN PIRP  Irp 
)

Definition at line 250 of file ea.c.

272{
273#if 0
275
277
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;
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
377 if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
378
379 DebugTrace(0, Dbg, "FatCommonQueryEa: Thread can't wait\n", 0);
380
381 Status = FatFsdPostRequest( IrpContext, Irp );
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
419 Buffer = FatMapUserBuffer( IrpContext, Irp );
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
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
469 FatUnpinBcb( IrpContext, Bcb );
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
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
518 FatReadEaSet( IrpContext,
519 Vcb,
520 ExtendedAttributes,
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
578 Irp->IoStatus = FatQueryEaIndexSpecified( IrpContext,
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
629 FatReleaseFcb( IrpContext, Fcb );
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
640 FatUnpinBcb( IrpContext, Bcb );
641 FatUnpinBcb( IrpContext, EaBcb );
642
643 FatUnpinEaRange( IrpContext, &EaSetRange );
644
645 if (!AbnormalTermination()) {
646
647 FatCompleteRequest( IrpContext, Irp, Status );
648 }
649
650 DebugTrace(-1, Dbg, "FatCommonQueryEa -> %08lx\n", Status);
651 }
652
653 return Status;
654#endif
655}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
NodeType
Definition: Node.h:6
#define except(x)
Definition: btrfs_drv.h:136
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
Definition: cdprocs.h:427
@ UserDirectoryOpen
Definition: cdprocs.h:576
@ UserFileOpen
Definition: cdprocs.h:577
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
enum _TYPE_OF_OPEN TYPE_OF_OPEN
#define try_return(S)
Definition: cdprocs.h:2179
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1215
Definition: bufpool.h:45
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
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)
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)
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)
EA_SET_HEADER * PEA_SET_HEADER
Definition: fat.h:672
#define GetcbList(EASET)
Definition: fat.h:678
PACKED_EA * PPACKED_EA
Definition: fat.h:700
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
VOID FatUnpinEaRange(IN PIRP_CONTEXT IrpContext, IN OUT PEA_RANGE EaRange)
Definition: easup.c:3782
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 FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
PVOID FatMapUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp)
Definition: deviosup.c:3357
#define DebugUnwind(X)
Definition: fatdata.h:315
IN PVCB IN VBO IN ULONG OUT PBCB * Bcb
Definition: fatprocs.h:414
IN PVCB IN ULONG IN PBCB OUT PDIRENT OUT PUSHORT OUT PEA_RANGE EaSetRange
Definition: fatprocs.h:951
#define FatUnpinBcb(IRPCONTEXT, BCB)
Definition: fatprocs.h:546
NTSTATUS FatFsdPostRequest(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:229
TYPE_OF_OPEN FatDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Outptr_ PVCB *Vcb, _Outptr_ PFCB *FcbOrDcb, _Outptr_ PCCB *Ccb)
Definition: filobsup.c:176
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2633
#define FatReleaseFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1644
IN OUT PVCB OUT PDIRENT OUT PBCB * EaBcb
Definition: fatprocs.h:915
IN OUT PVCB OUT PDIRENT * EaDirent
Definition: fatprocs.h:914
#define FatIsFat32(VCB)
Definition: fatprocs.h:1446
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ BOOLEAN _In_ ULONG _In_opt_ PULONG _In_ BOOLEAN RestartScan
Definition: fltkernel.h:2299
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ BOOLEAN ReturnSingleEntry
Definition: fltkernel.h:2295
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
#define NOTHING
Definition: input_list.c:10
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
#define STATUS_EA_CORRUPT_ERROR
Definition: ntstatus.h:319
#define STATUS_NO_EAS_ON_FILE
Definition: ntstatus.h:318
#define STATUS_EAS_NOT_SUPPORTED
Definition: ntstatus.h:315
unsigned short USHORT
Definition: pedump.c:61
#define Vcb
Definition: cdprocs.h:1415
#define AbnormalTermination()
Definition: seh.h:28
#define GetExceptionCode()
Definition: seh.h:27
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: cdstruc.h:1067
UCHAR PackedEas[1]
Definition: fat.h:670
Definition: cdstruc.h:902
ULONG EaModificationCount
Definition: fatstruc.h:1107
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1115
union _FILE_NAME_NODE::@719 Name
OEM_STRING Oem
Definition: fatstruc.h:693
struct _IO_STACK_LOCATION::@3979::@3990 QueryEa
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
union _IO_STACK_LOCATION::@1564 Parameters
Definition: cdstruc.h:498
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define SL_INDEX_SPECIFIED
Definition: iotypes.h:1837
#define SL_RETURN_SINGLE_ENTRY
Definition: iotypes.h:1836
#define SL_RESTART_SCAN
Definition: iotypes.h:1835

Referenced by _Function_class_(), FatCommonQueryEa(), and FatFspDispatch().

◆ FatCommonSetEa()

NTSTATUS FatCommonSetEa ( IN PIRP_CONTEXT  IrpContext,
IN PIRP  Irp 
)

Definition at line 659 of file ea.c.

681{
682#if 0
684
686
687 USHORT ExtendedAttributes;
688
690 ULONG UserBufferLength;
691
692 PVCB Vcb;
693 PCCB Ccb;
694
695 PFCB Fcb;
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
808 FatCompleteRequest( IrpContext, Irp, Status );
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
827 if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {
828
829 DebugTrace(0, Dbg, "FatCommonSetEa: Set Ea must be waitable\n", 0);
830
831 Status = FatFsdPostRequest( IrpContext, Irp );
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
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
865 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) {
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
903 FatUnpinBcb( IrpContext, Bcb );
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
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
954 FatReadEaSet( IrpContext,
955 Vcb,
956 ExtendedAttributes,
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
999 FatUnpinEaRange( IrpContext, &EaSetRange );
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
1069 if (FatLocateEaByName( IrpContext,
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
1083 FatDeletePackedEa( IrpContext,
1084 EaSetHeader,
1085 &PackedEasLength,
1086 Offset );
1087 }
1088
1089 if (FullEa->EaValueLength != 0) {
1090
1091 FatAppendPackedEa( IrpContext,
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 );
1175 FatUnpinEaRange( IrpContext, &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
1220 FatNotifyReportChange( IrpContext,
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
1235 FatUnpinBcb( IrpContext, Bcb );
1236 FatUnpinBcb( IrpContext, EaBcb );
1237
1238 FatUnpinRepinnedBcbs( IrpContext );
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
1255 FatUnpinBcb( IrpContext, Bcb );
1256 FatUnpinBcb( IrpContext, EaBcb );
1257
1258 FatUnpinEaRange( IrpContext, &EaSetRange );
1259 }
1260
1261 //
1262 // Release the Fcbs/Vcb acquired.
1263 //
1264
1265 if (AcquiredEaFcb) {
1266 FatReleaseFcb( IrpContext, Vcb->EaFcb );
1267 }
1268
1269 if (AcquiredFcb) {
1270 FatReleaseFcb( IrpContext, Fcb );
1271 }
1272
1273 if (AcquiredParentDcb) {
1274 FatReleaseFcb( IrpContext, Fcb->ParentDcb );
1275 }
1276
1277 if (AcquiredRootDcb) {
1278 FatReleaseFcb( IrpContext, Fcb->Vcb->RootDcb );
1279 }
1280
1281 if (AcquiredVcb) {
1282 FatReleaseVcb( IrpContext, Fcb->Vcb );
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
1300 FatCompleteRequest( IrpContext, Irp, Status );
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}
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 NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MAXIMUM_EA_SIZE
Definition: fat.h:676
#define SIZE_OF_EA_SET_HEADER
Definition: fat.h:674
#define TAG_EA_SET_HEADER
Definition: nodetype.h:161
VOID FatMarkEaRangeDirty(IN PIRP_CONTEXT IrpContext, IN PFILE_OBJECT EaFileObject, IN OUT PEA_RANGE EaRange)
Definition: easup.c:3709
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
VOID FatDeletePackedEa(IN PIRP_CONTEXT IrpContext, IN OUT PEA_SET_HEADER EaSetHeader, IN OUT PULONG PackedEasLength, IN ULONG Offset)
Definition: easup.c:3148
BOOLEAN FatLocateEaByName(IN PIRP_CONTEXT IrpContext, IN PPACKED_EA FirstPackedEa, IN ULONG PackedEasLength, IN POEM_STRING EaName, OUT PULONG Offset)
Definition: easup.c:3344
BOOLEAN FatIsEaNameValid(IN PIRP_CONTEXT IrpContext, IN OEM_STRING Name)
Definition: easup.c:3429
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define PagedPool
Definition: env_spec_w32.h:308
#define IRP_CONTEXT_FLAG_WRITE_THROUGH
Definition: ext2fs.h:1088
VOID FatUnpinRepinnedBcbs(IN PIRP_CONTEXT IrpContext)
Definition: cachesup.c:1407
PVOID FatBufferUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp, IN ULONG BufferLength)
Definition: deviosup.c:3411
#define FatNotifyReportChange(I, V, F, FL, A)
Definition: fatprocs.h:2168
IN PVCB IN PUCHAR IN ULONG IN POEM_STRING OUT PUSHORT EaHandle
Definition: fatprocs.h:898
#define FatReleaseVcb(IRPCONTEXT, Vcb)
Definition: fatprocs.h:1640
#define CopyU4char(Dst, Src)
Definition: fatprocs.h:2153
struct _FILE_FULL_EA_INFORMATION * PFILE_FULL_EA_INFORMATION
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
NTSTATUS NTAPI IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: util.c:191
#define STATUS_INVALID_EA_NAME
Definition: ntstatus.h:199
#define STATUS_EA_TOO_LARGE
Definition: ntstatus.h:316
ULONG32 NeedEaCount
Definition: fat.h:666
UCHAR cbList[4]
Definition: fat.h:669
UCHAR OwnerFileName[14]
Definition: fat.h:667
struct _FCB * ParentDcb
Definition: fatstruc.h:836
PVCB Vcb
Definition: cdstruc.h:933
struct _IO_STACK_LOCATION::@3979::@3991 SetEa
struct _FCB * RootDcb
Definition: fatstruc.h:285
uint32_t * PULONG
Definition: typedefs.h:59
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
STRING OEM_STRING
Definition: umtypes.h:203
#define FILE_ACTION_MODIFIED
#define FO_FILE_MODIFIED
Definition: iotypes.h:1788
#define FILE_NEED_EA
#define FILE_NOTIFY_CHANGE_EA

Referenced by _Function_class_(), FatCommonSetEa(), and FatFspDispatch().

◆ FatIsDuplicateEaName()

BOOLEAN FatIsDuplicateEaName ( IN PIRP_CONTEXT  IrpContext,
IN PFILE_GET_EA_INFORMATION  GetEa,
IN PUCHAR  UserBuffer 
)

◆ FatQueryEaIndexSpecified()

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 
)

Referenced by FatCommonQueryEa().

◆ FatQueryEaSimpleScan()

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 
)

Referenced by FatCommonQueryEa().

◆ FatQueryEaUserEaList()

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 
)

Referenced by FatCommonQueryEa().