ReactOS 0.4.16-dev-91-g764881a
fileinfo.c File Reference
#include "fatprocs.h"
Include dependency graph for fileinfo.c:

Go to the source code of this file.

Macros

#define BugCheckFileId   (FAT_BUG_CHECK_FILEINFO)
 
#define Dbg   (DEBUG_TRACE_FILEINFO)
 

Functions

VOID FatQueryBasicInfo (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PFILE_OBJECT FileObject, IN OUT PFILE_BASIC_INFORMATION Buffer, IN OUT PLONG Length)
 
 _Requires_lock_held_ (_Global_critical_region_)
 
 _Function_class_ (IRP_MJ_SET_INFORMATION)
 
VOID FatQueryInternalInfo (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN OUT PFILE_INTERNAL_INFORMATION Buffer, IN OUT PLONG Length)
 
VOID FatQueryEaInfo (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN OUT PFILE_EA_INFORMATION Buffer, IN OUT PLONG Length)
 
VOID FatQueryPositionInfo (IN PIRP_CONTEXT IrpContext, IN PFILE_OBJECT FileObject, IN OUT PFILE_POSITION_INFORMATION Buffer, IN OUT PLONG Length)
 
VOID FatQueryShortNameInfo (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN OUT PFILE_NAME_INFORMATION Buffer, IN OUT PLONG Length)
 
NTSTATUS FatSetRenameInfo (IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PVCB Vcb, IN PFCB Fcb, IN PCCB Ccb)
 
NTSTATUS FatSetPositionInfo (IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PFILE_OBJECT FileObject)
 

Macro Definition Documentation

◆ BugCheckFileId

#define BugCheckFileId   (FAT_BUG_CHECK_FILEINFO)

Definition at line 23 of file fileinfo.c.

◆ Dbg

#define Dbg   (DEBUG_TRACE_FILEINFO)

Definition at line 29 of file fileinfo.c.

Function Documentation

◆ _Function_class_()

_Function_class_ ( IRP_MJ_SET_INFORMATION  )

Definition at line 280 of file fileinfo.c.

309{
311 PIRP_CONTEXT IrpContext = NULL;
312
314
315 PAGED_CODE();
316
317 DebugTrace(+1, Dbg, "FatFsdSetInformation\n", 0);
318
319 //
320 // Call the common set routine, with blocking allowed if synchronous
321 //
322
324
326
327 _SEH2_TRY {
328
329 IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
330
331 Status = FatCommonSetInformation( IrpContext, Irp );
332
334
335 //
336 // We had some trouble trying to perform the requested
337 // operation, so we'll abort the I/O request with
338 // the error status that we get back from the
339 // execption code
340 //
341
342 Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
343 } _SEH2_END;
344
345 if (TopLevel) { IoSetTopLevelIrp( NULL ); }
346
348
349 //
350 // And return to our caller
351 //
352
353 DebugTrace(-1, Dbg, "FatFsdSetInformation -> %08lx\n", Status);
354
355 UNREFERENCED_PARAMETER( VolumeDeviceObject );
356
357 return Status;
358}
#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
#define Dbg
Definition: fileinfo.c:29
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:2418
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:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164

◆ _Requires_lock_held_()

_Requires_lock_held_ ( _Global_critical_region_  )

Definition at line 40 of file fileinfo.c.

228{
230 PIRP_CONTEXT IrpContext = NULL;
231
233
234 PAGED_CODE();
235
236 DebugTrace(+1, Dbg, "FatFsdQueryInformation\n", 0);
237
238 //
239 // Call the common query routine, with blocking allowed if synchronous
240 //
241
243
245
246 _SEH2_TRY {
247
248 IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
249
250 Status = FatCommonQueryInformation( IrpContext, Irp );
251
253
254 //
255 // We had some trouble trying to perform the requested
256 // operation, so we'll abort the I/O request with
257 // the error status that we get back from the
258 // execption code
259 //
260
261 Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
262 } _SEH2_END;
263
264 if (TopLevel) { IoSetTopLevelIrp( NULL ); }
265
267
268 //
269 // And return to our caller
270 //
271
272 DebugTrace(-1, Dbg, "FatFsdQueryInformation -> %08lx\n", Status);
273
274 UNREFERENCED_PARAMETER( VolumeDeviceObject );
275
276 return Status;
277}

◆ FatQueryBasicInfo()

VOID FatQueryBasicInfo ( IN PIRP_CONTEXT  IrpContext,
IN PFCB  Fcb,
IN PFILE_OBJECT  FileObject,
IN OUT PFILE_BASIC_INFORMATION  Buffer,
IN OUT PLONG  Length 
)

Definition at line 1044 of file fileinfo.c.

1075{
1076 PAGED_CODE();
1077
1079 UNREFERENCED_PARAMETER( IrpContext );
1080
1081 DebugTrace(+1, Dbg, "FatQueryBasicInfo...\n", 0);
1082
1083 //
1084 // Zero out the output buffer, and set it to indicate that
1085 // the query is a normal file. Later we might overwrite the
1086 // attribute.
1087 //
1088
1090
1091 //
1092 // Extract the data and fill in the non zero fields of the output
1093 // buffer
1094 //
1095
1096 if (Fcb->Header.NodeTypeCode == FAT_NTC_ROOT_DCB) {
1097
1098 //
1099 // We have to munge a lie on the fly. Every time we have to
1100 // use 1/1/80 we need to convert to GMT since the TZ may have
1101 // changed on us.
1102 //
1103
1105 &Buffer->LastWriteTime );
1106 Buffer->CreationTime = Buffer->LastAccessTime = Buffer->LastWriteTime;
1107
1108 } else {
1109
1110 Buffer->LastWriteTime = Fcb->LastWriteTime;
1111 Buffer->CreationTime = Fcb->CreationTime;
1112 Buffer->LastAccessTime = Fcb->LastAccessTime;
1113 }
1114
1115 Buffer->FileAttributes = Fcb->DirentFatFlags;
1116
1117
1118 //
1119 // If the temporary flag is set, then set it in the buffer.
1120 //
1121
1123
1124 SetFlag( Buffer->FileAttributes, FILE_ATTRIBUTE_TEMPORARY );
1125 }
1126
1127 //
1128 // If no attributes were set, set the normal bit.
1129 //
1130
1131 if (Buffer->FileAttributes == 0) {
1132
1133 Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
1134 }
1135
1136 //
1137 // Update the length and status output variables
1138 //
1139
1140 *Length -= sizeof( FILE_BASIC_INFORMATION );
1141
1142 DebugTrace( 0, Dbg, "*Length = %08lx\n", *Length);
1143
1144 DebugTrace(-1, Dbg, "FatQueryBasicInfo -> VOID\n", 0);
1145
1146 return;
1147}
_In_ PFCB Fcb
Definition: cdprocs.h:159
Definition: bufpool.h:45
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
#define ExLocalTimeToSystemTime(LocTime, SysTime)
Definition: env_spec_w32.h:738
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
LARGE_INTEGER FatJanOne1980
Definition: fatdata.c:73
#define FCB_STATE_TEMPORARY
Definition: fatstruc.h:1198
#define FILE_BASIC_INFORMATION
Definition: disk.h:53
#define FILE_ATTRIBUTE_TEMPORARY
Definition: nt_native.h:708
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
LONGLONG CreationTime
Definition: cdstruc.h:1030
LARGE_INTEGER LastWriteTime
Definition: fatstruc.h:922
FSRTL_ADVANCED_FCB_HEADER Header
Definition: cdstruc.h:925
ULONG FcbState
Definition: cdstruc.h:971
LARGE_INTEGER LastAccessTime
Definition: fatstruc.h:921
UCHAR DirentFatFlags
Definition: fatstruc.h:1133
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550

◆ FatQueryEaInfo()

VOID FatQueryEaInfo ( IN PIRP_CONTEXT  IrpContext,
IN PFCB  Fcb,
IN OUT PFILE_EA_INFORMATION  Buffer,
IN OUT PLONG  Length 
)

Definition at line 1306 of file fileinfo.c.

1335{
1336 PBCB Bcb;
1337
1338 PAGED_CODE();
1339
1341 UNREFERENCED_PARAMETER( IrpContext );
1342
1343 DebugTrace(+1, Dbg, "FatQueryEaInfo...\n", 0);
1344
1345 Bcb = NULL;
1346
1347 _SEH2_TRY {
1348
1349 //
1350 // Zero out the output buffer
1351 //
1352
1354
1355#if 0
1356 //
1357 // The Root dcb does not have any EAs so don't look for any. Fat32
1358 // doesn't have any, either.
1359 //
1360
1361 if ( NodeType( Fcb ) != FAT_NTC_ROOT_DCB &&
1362 !FatIsFat32( Fcb->Vcb )) {
1363
1365
1366 //
1367 // Try to get the dirent for this file.
1368 //
1369
1370 FatGetDirentFromFcbOrDcb( IrpContext,
1371 Fcb,
1372 &Dirent,
1373 &Bcb );
1374
1375 if (Dirent != NULL) {
1376
1377 //
1378 // Get a the size needed to store the full eas for the file.
1379 //
1380
1381 FatGetEaLength( IrpContext,
1382 Fcb->Vcb,
1383 Dirent,
1384 &Buffer->EaSize );
1385 }
1386 }
1387#endif
1388
1389 //
1390 // Update the length and status output variables
1391 //
1392
1393 *Length -= sizeof( FILE_EA_INFORMATION );
1394
1395 } _SEH2_FINALLY {
1396
1398
1399 //
1400 // Unpin the dirent if pinned.
1401 //
1402
1403 FatUnpinBcb( IrpContext, Bcb );
1404
1405 DebugTrace( 0, Dbg, "*Length = %08lx\n", *Length);
1406
1407 DebugTrace(-1, Dbg, "FatQueryEaInfo -> VOID\n", 0);
1408 } _SEH2_END;
1409}
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
Definition: cdprocs.h:427
#define NodeType(P)
Definition: nodetype.h:51
VOID FatQueryEaInfo(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN OUT PFILE_EA_INFORMATION Buffer, IN OUT PLONG Length)
Definition: fileinfo.c:1306
#define DebugUnwind(X)
Definition: fatdata.h:315
IN PVCB IN VBO IN ULONG OUT PBCB * Bcb
Definition: fatprocs.h:415
#define FatUnpinBcb(IRPCONTEXT, BCB)
Definition: fatprocs.h:547
#define FatIsFat32(VCB)
Definition: fatprocs.h:1447
#define _SEH2_FINALLY
Definition: filesup.c:21
struct _FILE_EA_INFORMATION FILE_EA_INFORMATION
PVCB Vcb
Definition: cdstruc.h:933

Referenced by FatQueryEaInfo().

◆ FatQueryInternalInfo()

VOID FatQueryInternalInfo ( IN PIRP_CONTEXT  IrpContext,
IN PFCB  Fcb,
IN OUT PFILE_INTERNAL_INFORMATION  Buffer,
IN OUT PLONG  Length 
)

Definition at line 1242 of file fileinfo.c.

1271{
1272 PAGED_CODE();
1273
1274 UNREFERENCED_PARAMETER( IrpContext );
1275
1276 DebugTrace(+1, Dbg, "FatQueryInternalInfo...\n", 0);
1277
1278 _SEH2_TRY {
1279
1280 Buffer->IndexNumber.QuadPart = FatGenerateFileIdFromFcb( Fcb );
1281
1282 //
1283 // Update the length and status output variables
1284 //
1285
1286 *Length -= sizeof( FILE_INTERNAL_INFORMATION );
1287
1288 } _SEH2_FINALLY {
1289
1291
1292 DebugTrace( 0, Dbg, "*Length = %08lx\n", *Length);
1293
1294 DebugTrace(-1, Dbg, "FatQueryInternalInfo -> VOID\n", 0);
1295 } _SEH2_END;
1296
1297 return;
1298}
VOID FatQueryInternalInfo(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN OUT PFILE_INTERNAL_INFORMATION Buffer, IN OUT PLONG Length)
Definition: fileinfo.c:1242
#define FatGenerateFileIdFromFcb(Fcb)
Definition: fatprocs.h:3067
struct _FILE_INTERNAL_INFORMATION FILE_INTERNAL_INFORMATION

Referenced by FatQueryInternalInfo().

◆ FatQueryPositionInfo()

VOID FatQueryPositionInfo ( IN PIRP_CONTEXT  IrpContext,
IN PFILE_OBJECT  FileObject,
IN OUT PFILE_POSITION_INFORMATION  Buffer,
IN OUT PLONG  Length 
)

Definition at line 1417 of file fileinfo.c.

1446{
1447 PAGED_CODE();
1448
1449 DebugTrace(+1, Dbg, "FatQueryPositionInfo...\n", 0);
1450
1451 //
1452 // Get the current position found in the file object.
1453 //
1454
1455 Buffer->CurrentByteOffset = FileObject->CurrentByteOffset;
1456
1457 //
1458 // Update the length and status output variables
1459 //
1460
1461 *Length -= sizeof( FILE_POSITION_INFORMATION );
1462
1463 DebugTrace( 0, Dbg, "*Length = %08lx\n", *Length);
1464
1465 DebugTrace(-1, Dbg, "FatQueryPositionInfo -> VOID\n", 0);
1466
1467 UNREFERENCED_PARAMETER( IrpContext );
1468
1469 return;
1470}
struct _FILE_POSITION_INFORMATION FILE_POSITION_INFORMATION

◆ FatQueryShortNameInfo()

VOID FatQueryShortNameInfo ( IN PIRP_CONTEXT  IrpContext,
IN PFCB  Fcb,
IN OUT PFILE_NAME_INFORMATION  Buffer,
IN OUT PLONG  Length 
)

Definition at line 1686 of file fileinfo.c.

1715{
1717
1719 WCHAR ShortNameBuffer[12];
1721
1722 PAGED_CODE();
1723
1724 DebugTrace(+1, Dbg, "FatQueryNameInfo...\n", 0);
1725
1726 //
1727 // Convert the name to UNICODE
1728 //
1729
1730 ShortName.Length = 0;
1731 ShortName.MaximumLength = sizeof(ShortNameBuffer);
1732 ShortName.Buffer = ShortNameBuffer;
1733
1735
1736#ifdef _MSC_VER
1737#pragma prefast( suppress:28931, "needed for debug build" )
1738#endif
1741 FALSE );
1742
1744
1745 //
1746 // If we overflow, set *Length to -1 as a flag.
1747 //
1748
1749 if (*Length < ShortName.Length) {
1750
1752 *Length = -1;
1753
1754 } else {
1755
1756 BytesToCopy = ShortName.Length;
1757 *Length -= ShortName.Length;
1758 }
1759
1760 RtlCopyMemory( &Buffer->FileName[0],
1761 &ShortName.Buffer[0],
1762 BytesToCopy );
1763
1764 Buffer->FileNameLength = ShortName.Length;
1765
1766 //
1767 // Return to caller
1768 //
1769
1770 DebugTrace( 0, Dbg, "*Length = %08lx\n", *Length);
1771
1772 DebugTrace(-1, Dbg, "FatQueryNameInfo -> VOID\n", 0);
1773
1774 UNREFERENCED_PARAMETER( IrpContext );
1775
1776 return;
1777}
#define FALSE
Definition: types.h:117
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING ShortName
Definition: fatprocs.h:1307
_In_ UINT _In_ UINT BytesToCopy
Definition: ndis.h:3168
NTSTATUS NTAPI RtlOemStringToCountedUnicodeString(IN OUT PUNICODE_STRING UniDest, IN PCOEM_STRING OemSource, IN BOOLEAN AllocateDestinationString)
Definition: unicode.c:1473
#define STATUS_SUCCESS
Definition: shellext.h:65
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1115
union _FILE_NAME_NODE::@728 Name
OEM_STRING Oem
Definition: fatstruc.h:693
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
#define NT_ASSERT
Definition: rtlfuncs.h:3324
__wchar_t WCHAR
Definition: xmlstorage.h:180

◆ FatSetPositionInfo()

NTSTATUS FatSetPositionInfo ( IN PIRP_CONTEXT  IrpContext,
IN PIRP  Irp,
IN PFILE_OBJECT  FileObject 
)

Definition at line 4010 of file fileinfo.c.

4036{
4038
4039 PAGED_CODE();
4040
4041 DebugTrace(+1, Dbg, "FatSetPositionInfo...\n", 0);
4042
4043 Buffer = Irp->AssociatedIrp.SystemBuffer;
4044
4045 //
4046 // Check if the file does not use intermediate buffering. If it
4047 // does not use intermediate buffering then the new position we're
4048 // supplied must be aligned properly for the device
4049 //
4050
4052
4054
4056
4057 if ((Buffer->CurrentByteOffset.LowPart & DeviceObject->AlignmentRequirement) != 0) {
4058
4059 DebugTrace(0, Dbg, "Cannot set position due to aligment conflict\n", 0);
4060 DebugTrace(-1, Dbg, "FatSetPositionInfo -> %08lx\n", STATUS_INVALID_PARAMETER);
4061
4063 }
4064 }
4065
4066 //
4067 // The input parameter is fine so set the current byte offset and
4068 // complete the request
4069 //
4070
4071 DebugTrace(0, Dbg, "Set the new position to %08lx\n", Buffer->CurrentByteOffset);
4072
4073 FileObject->CurrentByteOffset = Buffer->CurrentByteOffset;
4074
4075 DebugTrace(-1, Dbg, "FatSetPositionInfo -> %08lx\n", STATUS_SUCCESS);
4076
4077 UNREFERENCED_PARAMETER( IrpContext );
4078
4079 return STATUS_SUCCESS;
4080}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define FO_NO_INTERMEDIATE_BUFFERING
Definition: iotypes.h:1778

◆ FatSetRenameInfo()

NTSTATUS FatSetRenameInfo ( IN PIRP_CONTEXT  IrpContext,
IN PIRP  Irp,
IN PVCB  Vcb,
IN PFCB  Fcb,
IN PCCB  Ccb 
)

Definition at line 2694 of file fileinfo.c.

2728{
2731 BOOLEAN CaseOnlyRename;
2732 BOOLEAN ContinueWithRename;
2734 BOOLEAN DeleteSourceDirent;
2735 BOOLEAN DeleteTarget;
2736 BOOLEAN NewDirentFromPool;
2737 BOOLEAN RenamedAcrossDirectories;
2738 BOOLEAN ReplaceIfExists;
2739
2740 CCB LocalCcb;
2741 PCCB SourceCcb;
2742
2743 DIRENT Dirent;
2744
2746
2747 OEM_STRING OldOemName;
2748 OEM_STRING NewOemName;
2749 UCHAR OemNameBuffer[24*2];
2750
2751 PBCB DotDotBcb;
2752 PBCB NewDirentBcb;
2753 PBCB OldDirentBcb;
2754 PBCB SecondPageBcb;
2755 PBCB TargetDirentBcb;
2756
2758 PDCB OldParentDcb;
2759
2760 PDIRENT DotDotDirent = NULL;
2761 PDIRENT FirstPageDirent = NULL;
2762 PDIRENT NewDirent = NULL;
2763 PDIRENT OldDirent = NULL;
2764 PDIRENT SecondPageDirent = NULL;
2765 PDIRENT ShortDirent = NULL;
2766 PDIRENT TargetDirent = NULL;
2767
2768 PFCB TempFcb;
2769
2770 PFILE_OBJECT TargetFileObject;
2772
2774
2775 PLIST_ENTRY Links;
2776
2777 ULONG BytesInFirstPage = 0;
2778 ULONG DirentsInFirstPage = 0;
2779 ULONG DirentsRequired = 0;
2780 ULONG NewOffset = 0;
2781 ULONG NotifyAction = 0;
2782 ULONG SecondPageOffset = 0;
2783 ULONG ShortDirentOffset = 0;
2784 ULONG TargetDirentOffset = 0;
2785 ULONG TargetLfnOffset = 0;
2786
2787 // NewName comes from the IRP buffer or the TargetFileObject, so we can't
2788 // go around modifying it. Instead we modify NewNameCopy.
2790
2791 // NB: these five UNICODE_STRINGS are allocated
2792 // from one chopped up pool allocation called UnicodeBuffer.
2793 UNICODE_STRING NewNameCopy;
2794 UNICODE_STRING NewUpcasedName;
2795 UNICODE_STRING OldName;
2796 UNICODE_STRING OldUpcasedName;
2797 UNICODE_STRING TargetLfn;
2798 PWCHAR UnicodeBuffer;
2799
2800 UNICODE_STRING TargetOrigLfn = {0};
2801
2802 UNICODE_STRING UniTunneledShortName;
2803 WCHAR UniTunneledShortNameBuffer[12];
2804 UNICODE_STRING UniTunneledLongName;
2805 WCHAR UniTunneledLongNameBuffer[26];
2806
2807 LARGE_INTEGER TunneledCreationTime;
2808 ULONG TunneledDataSize;
2809 BOOLEAN HaveTunneledInformation = FALSE;
2810 BOOLEAN UsingTunneledLfn = FALSE;
2811
2812 BOOLEAN InvalidateFcbOnRaise = FALSE;
2813
2814 PFILE_OBJECT DirectoryFileObject = NULL;
2815 ULONG Flags = 0;
2816
2817 PAGED_CODE();
2818
2819 DebugTrace(+1, Dbg, "FatSetRenameInfo...\n", 0);
2820
2821 //
2822 // P H A S E 0: Initialize some variables.
2823 //
2824
2825 CaseOnlyRename = FALSE;
2826 ContinueWithRename = FALSE;
2827 DeleteSourceDirent = FALSE;
2828 DeleteTarget = FALSE;
2829 NewDirentFromPool = FALSE;
2830 RenamedAcrossDirectories = FALSE;
2831
2832 DotDotBcb = NULL;
2833 NewDirentBcb = NULL;
2834 OldDirentBcb = NULL;
2835 SecondPageBcb = NULL;
2836 TargetDirentBcb = NULL;
2837
2838 NewOemName.Length = 0;
2839 NewOemName.MaximumLength = 24;
2840 NewOemName.Buffer = (PCHAR)&OemNameBuffer[0];
2841
2842 OldOemName.Length = 0;
2843 OldOemName.MaximumLength = 24;
2844 OldOemName.Buffer = (PCHAR)&OemNameBuffer[24];
2845
2846 UnicodeBuffer = FsRtlAllocatePoolWithTag( PagedPool,
2847 5 * MAX_LFN_CHARACTERS * sizeof(WCHAR),
2849
2850 NewUpcasedName.Length = 0;
2851 NewUpcasedName.MaximumLength = MAX_LFN_CHARACTERS * sizeof(WCHAR);
2852 NewUpcasedName.Buffer = &UnicodeBuffer[0];
2853
2854 OldName.Length = 0;
2855 OldName.MaximumLength = MAX_LFN_CHARACTERS * sizeof(WCHAR);
2856 OldName.Buffer = &UnicodeBuffer[MAX_LFN_CHARACTERS];
2857
2858 OldUpcasedName.Length = 0;
2859 OldUpcasedName.MaximumLength = MAX_LFN_CHARACTERS * sizeof(WCHAR);
2860 OldUpcasedName.Buffer = &UnicodeBuffer[MAX_LFN_CHARACTERS * 2];
2861
2862 TargetLfn.Length = 0;
2863 TargetLfn.MaximumLength = MAX_LFN_CHARACTERS * sizeof(WCHAR);
2864 TargetLfn.Buffer = &UnicodeBuffer[MAX_LFN_CHARACTERS * 3];
2865
2866 NewNameCopy.Length = 0;
2867 NewNameCopy.MaximumLength = MAX_LFN_CHARACTERS * sizeof(WCHAR);
2868 NewNameCopy.Buffer = &UnicodeBuffer[MAX_LFN_CHARACTERS * 4];
2869
2870 UniTunneledShortName.Length = 0;
2871 UniTunneledShortName.MaximumLength = sizeof(UniTunneledShortNameBuffer);
2872 UniTunneledShortName.Buffer = &UniTunneledShortNameBuffer[0];
2873
2874 UniTunneledLongName.Length = 0;
2875 UniTunneledLongName.MaximumLength = sizeof(UniTunneledLongNameBuffer);
2876 UniTunneledLongName.Buffer = &UniTunneledLongNameBuffer[0];
2877
2878 //
2879 // Remember the name in case we have to modify the name
2880 // value in the ea.
2881 //
2882
2883 RtlCopyMemory( OldOemName.Buffer,
2884 Fcb->ShortName.Name.Oem.Buffer,
2885 OldOemName.Length );
2886
2887 //
2888 // Get the current stack location
2889 //
2890
2892
2893 //
2894 // Extract information from the Irp to make our life easier
2895 //
2896
2898 SourceCcb = FileObject->FsContext2;
2899 TargetFileObject = IrpSp->Parameters.SetFile.FileObject;
2900 ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists;
2901
2902 RtlZeroMemory( &LocalCcb, sizeof(CCB) );
2903
2904 //
2905 // P H A S E 1:
2906 //
2907 // Test if rename is legal. Only small side-effects are not undone.
2908 //
2909
2910 _SEH2_TRY {
2911
2912 //
2913 // Can't rename the root directory
2914 //
2915
2916 if ( NodeType(Fcb) == FAT_NTC_ROOT_DCB ) {
2917
2919 }
2920
2921 //
2922 // Check that we were not given a dcb with open handles beneath
2923 // it. If there are only UncleanCount == 0 Fcbs beneath us, then
2924 // remove them from the prefix table, and they will just close
2925 // and go away naturally.
2926 //
2927
2928 if (NodeType(Fcb) == FAT_NTC_DCB) {
2929
2930 PFCB BatchOplockFcb;
2931 ULONG BatchOplockCount;
2932
2933 //
2934 // Loop until there are no batch oplocks in the subtree below
2935 // this directory.
2936 //
2937
2938 while (TRUE) {
2939
2940 BatchOplockFcb = NULL;
2941 BatchOplockCount = 0;
2942
2943 //
2944 // First look for any UncleanCount != 0 Fcbs, and fail if we
2945 // find any.
2946 //
2947
2948 for ( TempFcb = FatGetNextFcbBottomUp(IrpContext, NULL, Fcb);
2949 TempFcb != Fcb;
2950 TempFcb = FatGetNextFcbBottomUp(IrpContext, TempFcb, Fcb) ) {
2951
2952 if ( TempFcb->UncleanCount != 0 ) {
2953
2954 //
2955 // If there is a batch oplock on this file then
2956 // increment our count and remember the Fcb if
2957 // this is the first.
2958 //
2959
2960 if (FatIsFileOplockable( TempFcb ) &&
2962#if (NTDDI_VERSION >= NTDDI_WIN7)
2963 ||
2964 FsRtlCurrentOplockH( FatGetFcbOplock(TempFcb) )
2965#endif
2966 )) {
2967
2968 BatchOplockCount += 1;
2969 if ( BatchOplockFcb == NULL ) {
2970
2971 BatchOplockFcb = TempFcb;
2972 }
2973
2974 } else {
2975
2977 }
2978 }
2979 }
2980
2981 //
2982 // If this is not the first pass for rename and the number
2983 // of batch oplocks has not decreased then give up.
2984 //
2985
2986 if ( BatchOplockFcb != NULL ) {
2987
2988 if ( (Irp->IoStatus.Information != 0) &&
2989 (BatchOplockCount >= Irp->IoStatus.Information) ) {
2990
2992 }
2993
2994 //
2995 // Try to break this batch oplock.
2996 //
2997
2998 Irp->IoStatus.Information = BatchOplockCount;
2999 Status = FsRtlCheckOplock( FatGetFcbOplock(BatchOplockFcb),
3000 Irp,
3001 IrpContext,
3003 NULL );
3004
3005 //
3006 // If the oplock was already broken then look for more
3007 // batch oplocks.
3008 //
3009
3010 if (Status == STATUS_SUCCESS) {
3011
3012 continue;
3013 }
3014
3015 //
3016 // Otherwise the oplock package will post or complete the
3017 // request.
3018 //
3019
3021 }
3022
3023 break;
3024 }
3025
3026 //
3027 // Now try to get as many of these file object, and thus Fcbs
3028 // to go away as possible, flushing first, of course.
3029 //
3030
3031 FatPurgeReferencedFileObjects( IrpContext, Fcb, Flush );
3032
3033 //
3034 // OK, so there are no UncleanCount != 0, Fcbs. Infact, there
3035 // shouldn't really be any Fcbs left at all, except obstinate
3036 // ones from user mapped sections .... Remove the full file name
3037 // and exact case lfn.
3038 //
3039
3040 for ( TempFcb = FatGetNextFcbBottomUp(IrpContext, NULL, Fcb);
3041 TempFcb != Fcb;
3042 TempFcb = FatGetNextFcbBottomUp(IrpContext, TempFcb, Fcb) ) {
3043
3044 FatAcquireExclusiveFcb( IrpContext, TempFcb );
3045
3046 if (TempFcb->FullFileName.Buffer != NULL) {
3047
3048 ExFreePool( TempFcb->FullFileName.Buffer );
3049 TempFcb->FullFileName.Buffer = NULL;
3050 }
3051
3052 FatReleaseFcb( IrpContext, TempFcb );
3053 }
3054 }
3055
3056 //
3057 // Check if this is a simple rename or a fully-qualified rename
3058 // In both cases we need to figure out what the TargetDcb, and
3059 // NewName are.
3060 //
3061
3062 if (TargetFileObject == NULL) {
3063
3064 //
3065 // In the case of a simple rename the target dcb is the
3066 // same as the source file's parent dcb, and the new file name
3067 // is taken from the system buffer
3068 //
3069
3071
3072 Buffer = Irp->AssociatedIrp.SystemBuffer;
3073
3075
3076 NewName.Length = (USHORT) Buffer->FileNameLength;
3077 NewName.Buffer = (PWSTR) &Buffer->FileName;
3078
3079 //
3080 // Make sure the name is of legal length.
3081 //
3082
3083 if (NewName.Length > 255*sizeof(WCHAR)) {
3084
3086 }
3087
3088 RtlCopyUnicodeString(&NewNameCopy,&NewName);
3089
3090 } else {
3091
3092 //
3093 // For a fully-qualified rename the target dcb is taken from
3094 // the target file object, which must be on the same vcb as
3095 // the source.
3096 //
3097
3098 PVCB TargetVcb;
3099 PCCB TargetCcb;
3100
3101 if ((FatDecodeFileObject( TargetFileObject,
3102 &TargetVcb,
3103 &TargetDcb,
3104 &TargetCcb ) != UserDirectoryOpen) ||
3105 (TargetVcb != Vcb)) {
3106
3108 }
3109
3110 //
3111 // This name is by definition legal.
3112 //
3113
3114 NewName = *((PUNICODE_STRING)&TargetFileObject->FileName);
3115
3116 RtlCopyUnicodeString(&NewNameCopy,&NewName);
3117
3118 }
3119
3120 //
3121 // We will need an upcased version of the unicode name and the
3122 // old name as well.
3123 //
3124
3125 Status = RtlUpcaseUnicodeString( &NewUpcasedName, &NewName, FALSE );
3126
3127 if (!NT_SUCCESS(Status)) {
3128
3129 try_return( Status );
3130 }
3131
3132 FatGetUnicodeNameFromFcb( IrpContext, Fcb, &OldName );
3133
3134 Status = RtlUpcaseUnicodeString( &OldUpcasedName, &OldName, FALSE );
3135
3136 if (!NT_SUCCESS(Status)) {
3138 }
3139
3140 //
3141 // Check if the current name and new name are equal, and the
3142 // DCBs are equal. If they are then our work is already done.
3143 //
3144
3145 if (TargetDcb == Fcb->ParentDcb) {
3146
3147 //
3148 // OK, now if we found something then check if it was an exact
3149 // match or just a case match. If it was an exact match, then
3150 // we can bail here.
3151 //
3152
3154 &OldName,
3155 FALSE,
3156 NULL )) {
3157
3159 }
3160
3161 //
3162 // Check now for a case only rename.
3163 //
3164
3165
3166 if (FsRtlAreNamesEqual( &NewUpcasedName,
3167 &OldUpcasedName,
3168 FALSE,
3169 NULL )) {
3170
3171 CaseOnlyRename = TRUE;
3172 }
3173
3174 } else {
3175
3176 RenamedAcrossDirectories = TRUE;
3177 }
3178
3179 //
3180 // Upcase the name and convert it to the Oem code page.
3181 //
3182 // If the new UNICODE name is already more than 12 characters,
3183 // then we know the Oem name will not be valid
3184 //
3185
3186 if (NewName.Length <= 12*sizeof(WCHAR)) {
3187
3188 FatUnicodeToUpcaseOem( IrpContext, &NewOemName, &NewName );
3189
3190 //
3191 // If the name is not valid 8.3, zero the length.
3192 //
3193
3194 if (FatSpaceInName( IrpContext, &NewName ) ||
3195 !FatIsNameShortOemValid( IrpContext, NewOemName, FALSE, FALSE, FALSE)) {
3196
3197 NewOemName.Length = 0;
3198 }
3199
3200 } else {
3201
3202 NewOemName.Length = 0;
3203 }
3204
3205 //
3206 // Look in the tunnel cache for names and timestamps to restore
3207 //
3208
3209 TunneledDataSize = sizeof(LARGE_INTEGER);
3210 HaveTunneledInformation = FsRtlFindInTunnelCache( &Vcb->Tunnel,
3212 &NewName,
3213 &UniTunneledShortName,
3214 &UniTunneledLongName,
3215 &TunneledDataSize,
3216 &TunneledCreationTime );
3217 NT_ASSERT(TunneledDataSize == sizeof(LARGE_INTEGER));
3218
3219
3220 //
3221 // Now we need to determine how many dirents this new name will
3222 // require.
3223 //
3224
3225 if ((NewOemName.Length == 0) ||
3226 (FatEvaluateNameCase( IrpContext,
3227 &NewNameCopy,
3230 &CreateLfn ),
3231 CreateLfn)) {
3232
3233 DirentsRequired = FAT_LFN_DIRENTS_NEEDED(&NewNameCopy) + 1;
3234
3235 } else {
3236
3237 //
3238 // The user-given name is a short name, but we might still have
3239 // a tunneled long name we want to use. See if we can.
3240 //
3241
3242 if (UniTunneledLongName.Length &&
3243 !FatLfnDirentExists(IrpContext, TargetDcb, &UniTunneledLongName, &TargetLfn)) {
3244
3245 UsingTunneledLfn = CreateLfn = TRUE;
3246 DirentsRequired = FAT_LFN_DIRENTS_NEEDED(&UniTunneledLongName) + 1;
3247
3248 } else {
3249
3250 //
3251 // This really is a simple dirent. Note that the two AllLower BOOLEANs
3252 // are correctly set now.
3253 //
3254
3255 DirentsRequired = 1;
3256
3257
3258 }
3259 }
3260
3261 //
3262 // Do some extra checks here if we are not in Chicago mode.
3263 //
3264
3265 if (!FatData.ChicagoMode) {
3266
3267 //
3268 // If the name was not 8.3 valid, fail the rename.
3269 //
3270
3271 if (NewOemName.Length == 0) {
3272
3274 }
3275
3276 //
3277 // Don't use the magic bits.
3278 //
3279
3282 CreateLfn = FALSE;
3283 UsingTunneledLfn = FALSE;
3284 }
3285
3286 if (!CaseOnlyRename) {
3287
3288 //
3289 // Check if the new name already exists, wait is known to be
3290 // true.
3291 //
3292
3293 if (NewOemName.Length != 0) {
3294
3295 FatStringTo8dot3( IrpContext,
3296 NewOemName,
3297 &LocalCcb.OemQueryTemplate.Constant );
3298
3299 } else {
3300
3302 }
3303
3304 LocalCcb.UnicodeQueryTemplate = NewUpcasedName;
3305 LocalCcb.ContainsWildCards = FALSE;
3306
3307 Flags = 0;
3308
3309
3310 FatLocateDirent( IrpContext,
3311 TargetDcb,
3312 &LocalCcb,
3313 0,
3314 &Flags,
3315 &TargetDirent,
3316 &TargetDirentBcb,
3317 (PVBO)&TargetDirentOffset,
3318 NULL,
3319 &TargetLfn,
3320 &TargetOrigLfn );
3321
3322 if (TargetDirent != NULL) {
3323
3324
3325 //
3326 // The name already exists, check if the user wants
3327 // to overwrite the name, and has access to do the overwrite
3328 // We cannot overwrite a directory.
3329 //
3330
3331 if ((!ReplaceIfExists) ||
3332 (FlagOn(TargetDirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY)) ||
3333 (FlagOn(TargetDirent->Attributes, FAT_DIRENT_ATTR_READ_ONLY))) {
3334
3336 }
3337
3338 //
3339 // Check that the file has no open user handles, if it does
3340 // then we will deny access. We do the check by searching
3341 // down the list of fcbs opened under our parent Dcb, and making
3342 // sure none of the maching Fcbs have a non-zero unclean count or
3343 // outstanding image sections.
3344 //
3345
3346 for (Links = TargetDcb->Specific.Dcb.ParentDcbQueue.Flink;
3347 Links != &TargetDcb->Specific.Dcb.ParentDcbQueue; ) {
3348
3349 TempFcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );
3350
3351 //
3352 // Advance now. The image section flush may cause the final
3353 // close, which will recursively happen underneath of us here.
3354 // It would be unfortunate if we looked through free memory.
3355 //
3356
3357 Links = Links->Flink;
3358
3359 if ((TempFcb->DirentOffsetWithinDirectory == TargetDirentOffset) &&
3360 ((TempFcb->UncleanCount != 0) ||
3362 MmFlushForDelete))) {
3363
3364 //
3365 // If there are batch oplocks on this file then break the
3366 // oplocks before failing the rename.
3367 //
3368
3370
3371 if (FatIsFileOplockable( TempFcb ) &&
3374 ||
3375 FsRtlCurrentOplockH( FatGetFcbOplock(TempFcb) )
3376#endif
3377 )) {
3378
3379 //
3380 // Do all of our cleanup now since the IrpContext
3381 // could go away when this request is posted.
3382 //
3383
3384 FatUnpinBcb( IrpContext, TargetDirentBcb );
3385
3387 Irp,
3388 IrpContext,
3390 NULL );
3391
3392 if (Status != STATUS_PENDING) {
3393
3395 }
3396 }
3397
3399 }
3400 }
3401
3402 //
3403 // OK, this target is toast. Remember the Lfn offset.
3404 //
3405
3406 TargetLfnOffset = TargetDirentOffset -
3407 FAT_LFN_DIRENTS_NEEDED(&TargetOrigLfn) *
3408 sizeof(DIRENT);
3409
3410 DeleteTarget = TRUE;
3411 }
3412 }
3413
3414
3415 //
3416 // If we will need more dirents than we have, allocate them now.
3417 //
3418
3419 if ((TargetDcb != Fcb->ParentDcb) ||
3420 (DirentsRequired !=
3422 Fcb->LfnOffsetWithinDirectory) / sizeof(DIRENT) + 1)) {
3423
3424 //
3425 // Get some new allocation
3426 //
3427
3428 NewOffset = FatCreateNewDirent( IrpContext,
3429 TargetDcb,
3430 DirentsRequired,
3431 FALSE );
3432
3433 DeleteSourceDirent = TRUE;
3434
3435 } else {
3436
3437 NewOffset = Fcb->LfnOffsetWithinDirectory;
3438 }
3439
3440 ContinueWithRename = TRUE;
3441
3442 try_exit: NOTHING;
3443
3444 } _SEH2_FINALLY {
3445
3446 if (!ContinueWithRename) {
3447
3448 //
3449 // Undo everything from above.
3450 //
3451
3452 ExFreePool( UnicodeBuffer );
3453 FatUnpinBcb( IrpContext, TargetDirentBcb );
3454
3455 }
3456 } _SEH2_END;
3457
3458 //
3459 // Now, if we are already done, return here.
3460 //
3461
3462 if (!ContinueWithRename) {
3463
3464 return Status;
3465 }
3466
3467 //
3468 // P H A S E 2: Actually perform the rename.
3469 //
3470
3471 _SEH2_TRY {
3472
3473 //
3474 // Report the fact that we are going to remove this entry.
3475 // If we renamed within the same directory and the new name for the
3476 // file did not previously exist, we report this as a rename old
3477 // name. Otherwise this is a removed file.
3478 //
3479
3480 if (!RenamedAcrossDirectories && !DeleteTarget) {
3481
3482 NotifyAction = FILE_ACTION_RENAMED_OLD_NAME;
3483
3484 } else {
3485
3486 NotifyAction = FILE_ACTION_REMOVED;
3487 }
3488
3489 FatNotifyReportChange( IrpContext,
3490 Vcb,
3491 Fcb,
3492 ((NodeType( Fcb ) == FAT_NTC_FCB)
3495 NotifyAction );
3496
3497 _SEH2_TRY {
3498
3499 //
3500 // Capture a copy of the source dirent.
3501 //
3502
3503 FatGetDirentFromFcbOrDcb( IrpContext, Fcb, FALSE, &OldDirent, &OldDirentBcb );
3504
3505 Dirent = *OldDirent;
3506
3507 //
3508 // Tunnel the source Fcb - the names are disappearing regardless of
3509 // whether the dirent allocation physically changed
3510 //
3511
3512 FatTunnelFcbOrDcb( Fcb, SourceCcb );
3513
3514 //
3515 // From here until very nearly the end of the operation, if we raise there
3516 // is no reasonable way to suppose we'd be able to undo the damage. Not
3517 // being a transactional filesystem, FAT is at the mercy of a lot of things
3518 // (as the astute reader has no doubt realized by now).
3519 //
3520
3521 InvalidateFcbOnRaise = TRUE;
3522
3523 //
3524 // Delete our current dirent(s) if we got a new one.
3525 //
3526
3527 if (DeleteSourceDirent) {
3528
3529 FatDeleteDirent( IrpContext, Fcb, NULL, FALSE );
3530 }
3531
3532 //
3533 // Delete a target conflict if we were meant to.
3534 //
3535
3536 if (DeleteTarget) {
3537
3538 FatDeleteFile( IrpContext,
3539 TargetDcb,
3540 TargetLfnOffset,
3541 TargetDirentOffset,
3542 TargetDirent,
3543 &TargetLfn );
3544 }
3545
3546 //
3547 // We need to evaluate any short names required. If there were any
3548 // conflicts in existing short names, they would have been deleted above.
3549 //
3550 // It isn't neccesary to worry about the UsingTunneledLfn case. Since we
3551 // actually already know whether CreateLfn will be set either NewName is
3552 // an Lfn and !UsingTunneledLfn is implied or NewName is a short name and
3553 // we can handle that externally.
3554 //
3555
3556 FatSelectNames( IrpContext,
3557 TargetDcb,
3558 &NewOemName,
3559 &NewNameCopy,
3560 &NewOemName,
3561 (HaveTunneledInformation ? &UniTunneledShortName : NULL),
3564 &CreateLfn );
3565
3566 if (!CreateLfn && UsingTunneledLfn) {
3567
3568 CreateLfn = TRUE;
3569 RtlCopyUnicodeString( &NewNameCopy, &UniTunneledLongName );
3570
3571 //
3572 // Short names are always upcase if an LFN exists
3573 //
3574
3577 }
3578
3579 //
3580 // OK, now setup the new dirent(s) for the new name.
3581 //
3582
3583 FatPrepareWriteDirectoryFile( IrpContext,
3584 TargetDcb,
3585 NewOffset,
3586 sizeof(DIRENT),
3587 &NewDirentBcb,
3588#ifndef __REACTOS__
3589 &NewDirent,
3590#else
3591 (PVOID *)&NewDirent,
3592#endif
3593 FALSE,
3594 TRUE,
3595 &Status );
3596
3598
3599 //
3600 // Deal with the special case of an LFN + Dirent structure crossing
3601 // a page boundry.
3602 //
3603
3604 if ((NewOffset / PAGE_SIZE) !=
3605 ((NewOffset + (DirentsRequired - 1) * sizeof(DIRENT)) / PAGE_SIZE)) {
3606
3607 SecondPageOffset = (NewOffset & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
3608
3609 BytesInFirstPage = SecondPageOffset - NewOffset;
3610
3611 DirentsInFirstPage = BytesInFirstPage / sizeof(DIRENT);
3612
3613 FatPrepareWriteDirectoryFile( IrpContext,
3614 TargetDcb,
3615 SecondPageOffset,
3616 sizeof(DIRENT),
3617 &SecondPageBcb,
3618#ifndef __REACTOS__
3619 &SecondPageDirent,
3620#else
3621 (PVOID *)&SecondPageDirent,
3622#endif
3623 FALSE,
3624 TRUE,
3625 &Status );
3626
3628
3629 FirstPageDirent = NewDirent;
3630
3632 DirentsRequired * sizeof(DIRENT),
3633 TAG_DIRENT );
3634
3635 NewDirentFromPool = TRUE;
3636 }
3637
3638 //
3639 // Bump up Dirent and DirentOffset
3640 //
3641
3642 ShortDirent = NewDirent + DirentsRequired - 1;
3643 ShortDirentOffset = NewOffset + (DirentsRequired - 1) * sizeof(DIRENT);
3644
3645 //
3646 // Fill in the fields of the dirent.
3647 //
3648
3649 *ShortDirent = Dirent;
3650
3651 FatConstructDirent( IrpContext,
3652 ShortDirent,
3653 &NewOemName,
3656 CreateLfn ? &NewNameCopy : NULL,
3657 Dirent.Attributes,
3658 FALSE,
3659 (HaveTunneledInformation ? &TunneledCreationTime : NULL) );
3660
3661 if (HaveTunneledInformation) {
3662
3663 //
3664 // Need to go in and fix the timestamps in the FCB. Note that we can't use
3665 // the TunneledCreationTime since the conversions may have failed.
3666 //
3667
3668 Fcb->CreationTime = FatFatTimeToNtTime(IrpContext, ShortDirent->CreationTime, ShortDirent->CreationMSec);
3669 Fcb->LastWriteTime = FatFatTimeToNtTime(IrpContext, ShortDirent->LastWriteTime, 0);
3670 Fcb->LastAccessTime = FatFatDateToNtTime(IrpContext, ShortDirent->LastAccessDate);
3671 }
3672
3673
3674 //
3675 // If the dirent crossed pages, split the contents of the
3676 // temporary pool between the two pages.
3677 //
3678
3679 if (NewDirentFromPool) {
3680
3681 RtlCopyMemory( FirstPageDirent, NewDirent, BytesInFirstPage );
3682
3683 RtlCopyMemory( SecondPageDirent,
3684 NewDirent + DirentsInFirstPage,
3685 DirentsRequired*sizeof(DIRENT) - BytesInFirstPage );
3686
3687 ShortDirent = SecondPageDirent +
3688 (DirentsRequired - DirentsInFirstPage) - 1;
3689 }
3690
3691 Dirent = *ShortDirent;
3692
3693 } _SEH2_FINALLY {
3694
3695 //
3696 // Remove the entry from the splay table, and then remove the
3697 // full file name and exact case lfn. It is important that we
3698 // always remove the name from the prefix table regardless of
3699 // other errors.
3700 //
3701
3702 FatRemoveNames( IrpContext, Fcb );
3703
3704 if (Fcb->FullFileName.Buffer != NULL) {
3705
3708 }
3709
3711
3714 }
3715
3716 FatUnpinBcb( IrpContext, OldDirentBcb );
3717 FatUnpinBcb( IrpContext, TargetDirentBcb );
3718 FatUnpinBcb( IrpContext, NewDirentBcb );
3719 FatUnpinBcb( IrpContext, SecondPageBcb );
3720 } _SEH2_END;
3721
3722 //
3723 // Now we need to update the location of the file's directory
3724 // offset and move the fcb from its current parent dcb to
3725 // the target dcb.
3726 //
3727
3728 Fcb->LfnOffsetWithinDirectory = NewOffset;
3729 Fcb->DirentOffsetWithinDirectory = ShortDirentOffset;
3730
3732
3733 //
3734 // There is a deep reason we put files on the tail, others on the head,
3735 // which is to allow us to easily enumerate all child directories before
3736 // child files. This is important to let us maintain whole-volume lockorder
3737 // via BottomUp enumeration.
3738 //
3739
3740 if (NodeType(Fcb) == FAT_NTC_FCB) {
3741
3742 InsertTailList( &TargetDcb->Specific.Dcb.ParentDcbQueue,
3743 &Fcb->ParentDcbLinks );
3744
3745 } else {
3746
3747 InsertHeadList( &TargetDcb->Specific.Dcb.ParentDcbQueue,
3748 &Fcb->ParentDcbLinks );
3749 }
3750
3751 OldParentDcb = Fcb->ParentDcb;
3753
3754#if (NTDDI_VERSION >= NTDDI_WIN8)
3755 //
3756 // Break parent directory oplock on the old parent. Directory oplock
3757 // breaks are always advisory, so we will never block/get STATUS_PENDING
3758 // here.
3759 //
3760
3761 FsRtlCheckOplockEx( FatGetFcbOplock(OldParentDcb),
3762 IrpContext->OriginatingIrp,
3763 OPLOCK_FLAG_PARENT_OBJECT,
3764 NULL,
3765 NULL,
3766 NULL );
3767#endif
3768
3769 //
3770 // If we renamed across directories, some cleanup is now in order.
3771 //
3772
3773 if (RenamedAcrossDirectories) {
3774
3775#if (NTDDI_VERSION >= NTDDI_WIN8)
3776 //
3777 // Break parent directory oplock on the new parent. Directory oplock
3778 // breaks are always advisory, so we will never block/get STATUS_PENDING
3779 // here.
3780 //
3781
3782 FsRtlCheckOplockEx( FatGetFcbOplock(TargetDcb),
3783 IrpContext->OriginatingIrp,
3784 OPLOCK_FLAG_PARENT_OBJECT,
3785 NULL,
3786 NULL,
3787 NULL );
3788#endif
3789
3790 //
3791 // See if we need to uninitialize the cachemap for the source directory.
3792 // Do this now in case we get unlucky and raise trying to finalize the
3793 // operation.
3794 //
3795
3796 if (IsListEmpty(&OldParentDcb->Specific.Dcb.ParentDcbQueue) &&
3797 (OldParentDcb->OpenCount == 0) &&
3798 (OldParentDcb->Specific.Dcb.DirectoryFile != NULL)) {
3799
3800 NT_ASSERT( NodeType(OldParentDcb) == FAT_NTC_DCB );
3801
3802 DirectoryFileObject = OldParentDcb->Specific.Dcb.DirectoryFile;
3803
3804 OldParentDcb->Specific.Dcb.DirectoryFile = NULL;
3805 }
3806
3807 //
3808 // If we move a directory across directories, we have to change
3809 // the cluster number in its .. entry
3810 //
3811
3812 if (NodeType(Fcb) == FAT_NTC_DCB) {
3813
3814 FatPrepareWriteDirectoryFile( IrpContext,
3815 Fcb,
3816 sizeof(DIRENT),
3817 sizeof(DIRENT),
3818 &DotDotBcb,
3819#ifndef __REACTOS__
3820 &DotDotDirent,
3821#else
3822 (PVOID *)&DotDotDirent,
3823#endif
3824 FALSE,
3825 TRUE,
3826 &Status );
3827
3829
3830 DotDotDirent->FirstClusterOfFile = (USHORT)
3833
3834 if (FatIsFat32( Vcb )) {
3835
3836 DotDotDirent->FirstClusterOfFileHi = (USHORT)
3838 0 : (TargetDcb->FirstClusterOfFile >> 16));
3839 }
3840 }
3841 }
3842
3843 //
3844 // Now we need to setup the splay table and the name within
3845 // the fcb. Free the old short name at this point.
3846 //
3847
3848 ExFreePool( Fcb->ShortName.Name.Oem.Buffer );
3849 Fcb->ShortName.Name.Oem.Buffer = NULL;
3850
3851
3852 FatConstructNamesInFcb( IrpContext,
3853 Fcb,
3854 &Dirent,
3855 CreateLfn ? &NewName : NULL );
3856
3857 FatSetFullNameInFcb( IrpContext, Fcb, &NewName );
3858
3859 //
3860 // The rest of the actions taken are not related to correctness of
3861 // the in-memory structures, so we shouldn't toast the Fcb if we
3862 // raise from here to the end.
3863 //
3864
3865 InvalidateFcbOnRaise = FALSE;
3866
3867 //
3868 // If a file, set the file as modified so that the archive bit
3869 // is set. We prevent this from adjusting the write time by
3870 // indicating the user flag in the ccb.
3871 //
3872
3873 if (Fcb->Header.NodeTypeCode == FAT_NTC_FCB) {
3874
3877 }
3878
3879 //
3880 // We have three cases to report.
3881 //
3882 // 1. If we overwrote an existing file, we report this as
3883 // a modified file.
3884 //
3885 // 2. If we renamed to a new directory, then we added a file.
3886 //
3887 // 3. If we renamed in the same directory, then we report the
3888 // the renamednewname.
3889 //
3890
3891 if (DeleteTarget) {
3892
3893 FatNotifyReportChange( IrpContext,
3894 Vcb,
3895 Fcb,
3903
3904 } else if (RenamedAcrossDirectories) {
3905
3906 FatNotifyReportChange( IrpContext,
3907 Vcb,
3908 Fcb,
3909 ((NodeType( Fcb ) == FAT_NTC_FCB)
3913
3914 } else {
3915
3916 FatNotifyReportChange( IrpContext,
3917 Vcb,
3918 Fcb,
3919 ((NodeType( Fcb ) == FAT_NTC_FCB)
3923 }
3924
3925 //
3926 // We need to update the file name in the dirent. This value
3927 // is never used elsewhere, so we don't concern ourselves
3928 // with any error we may encounter. We let chkdsk fix the
3929 // disk at some later time.
3930 //
3931
3932 if (!FatIsFat32(Vcb) &&
3933 Dirent.ExtendedAttributes != 0) {
3934
3935 FatRenameEAs( IrpContext,
3936 Fcb,
3937 Dirent.ExtendedAttributes,
3938 &OldOemName );
3939 }
3940
3941 FatUnpinBcb( IrpContext, DotDotBcb );
3942
3943 FatUnpinRepinnedBcbs( IrpContext );
3944
3945 //
3946 // Set our final status
3947 //
3948
3950
3951 } _SEH2_FINALLY {
3952
3954
3955 ExFreePool( UnicodeBuffer );
3956
3957 if (UniTunneledLongName.Buffer != UniTunneledLongNameBuffer) {
3958
3959 //
3960 // Free pool if the buffer was grown on tunneling lookup
3961 //
3962
3963 ExFreePool(UniTunneledLongName.Buffer);
3964 }
3965
3966 if (NewDirentFromPool) {
3967
3968 ExFreePool( NewDirent );
3969 }
3970
3971 FatUnpinBcb( IrpContext, TargetDirentBcb );
3972 FatUnpinBcb( IrpContext, DotDotBcb );
3973
3974 //
3975 // Uninitialize the cachemap for the source directory if we need to.
3976 //
3977
3978 if (DirectoryFileObject) {
3979
3980 DebugTrace(0, Dbg, "Uninitialize our parent Stream Cache Map\n", 0);
3981
3982 CcUninitializeCacheMap( DirectoryFileObject, NULL, NULL );
3983
3984 ObDereferenceObject( DirectoryFileObject );
3985 }
3986
3987 //
3988 // If this was an abnormal termination, then we are in trouble.
3989 // Should the operation have been in a sensitive state there is
3990 // nothing we can do but invalidate the Fcb.
3991 //
3992
3993 if (_SEH2_AbnormalTermination() && InvalidateFcbOnRaise) {
3994
3996 }
3997
3998 DebugTrace(-1, Dbg, "FatSetRenameInfo -> %08lx\n", Status);
3999 } _SEH2_END;
4000
4001 return Status;
4002}
@ UserDirectoryOpen
Definition: cdprocs.h:576
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
#define try_return(S)
Definition: cdprocs.h:2179
@ FcbBad
Definition: cdstruc.h:780
#define TRUE
Definition: types.h:120
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
VOID FatSetFullNameInFcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb, _In_ PUNICODE_STRING FinalName)
Definition: create.c:6718
#define FAT_DIRENT_ATTR_READ_ONLY
Definition: fat.h:368
VBO * PVBO
Definition: fat.h:39
#define FAT_DIRENT_ATTR_DIRECTORY
Definition: fat.h:372
NTSTATUS FatSetRenameInfo(IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PVCB Vcb, IN PFCB Fcb, IN PCCB Ccb)
Definition: fileinfo.c:2694
#define MAX_LFN_CHARACTERS
Definition: lfn.h:50
#define FAT_LFN_DIRENTS_NEEDED(NAME)
Definition: lfn.h:53
#define FAT_NTC_FCB
Definition: nodetype.h:29
#define FAT_NTC_DCB
Definition: nodetype.h:30
#define TAG_DIRENT
Definition: nodetype.h:158
#define TAG_FILENAME_BUFFER
Definition: nodetype.h:167
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define PagedPool
Definition: env_spec_w32.h:308
VOID FatUnpinRepinnedBcbs(IN PIRP_CONTEXT IrpContext)
Definition: cachesup.c:1407
VOID FatTunnelFcbOrDcb(IN PFCB FcbOrDcb, IN PCCB Ccb OPTIONAL)
Definition: dirsup.c:652
VOID FatConstructDirent(IN PIRP_CONTEXT IrpContext, IN OUT PDIRENT Dirent, IN POEM_STRING FileName, IN BOOLEAN ComponentReallyLowercase, IN BOOLEAN ExtensionReallyLowercase, IN PUNICODE_STRING Lfn OPTIONAL, IN USHORT Attributes, IN BOOLEAN ZeroAndSetTimeFields, IN PLARGE_INTEGER SetCreationTime OPTIONAL)
Definition: dirsup.c:2171
FAT_DATA FatData
Definition: fatdata.c:56
#define DIRENT
Definition: fatfs.h:187
VOID FatUnicodeToUpcaseOem(IN PIRP_CONTEXT IrpContext, IN POEM_STRING OemString, IN PUNICODE_STRING UnicodeString)
Definition: namesup.c:632
VOID FatStringTo8dot3(_In_ PIRP_CONTEXT IrpContext, _In_ OEM_STRING InputString, _Out_writes_bytes_(11) PFAT8DOT3 Output8dot3)
Definition: namesup.c:79
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING IN PUNICODE_STRING SuggestedShortName IN OUT BOOLEAN IN OUT BOOLEAN IN OUT BOOLEAN * CreateLfn
Definition: fatprocs.h:1312
TYPE_OF_OPEN FatDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Outptr_ PVCB *Vcb, _Outptr_ PFCB *FcbOrDcb, _Outptr_ PCCB *Ccb)
Definition: filobsup.c:176
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING IN PUNICODE_STRING SuggestedShortName IN OUT BOOLEAN * AllLowerComponent
Definition: fatprocs.h:1309
#define FatNotifyReportChange(I, V, F, FL, A)
Definition: fatprocs.h:2169
VOID FatEvaluateNameCase(IN PIRP_CONTEXT IrpContext, IN PUNICODE_STRING Name, IN OUT BOOLEAN *AllLowerComponent, IN OUT BOOLEAN *AllLowerExtension, IN OUT BOOLEAN *CreateLfn)
Definition: namesup.c:891
#define FatReleaseFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1645
BOOLEAN FatSpaceInName(IN PIRP_CONTEXT IrpContext, IN PUNICODE_STRING UnicodeName)
Definition: namesup.c:1003
VOID FatConstructNamesInFcb(IN PIRP_CONTEXT IrpContext, PFCB Fcb, PDIRENT Dirent, PUNICODE_STRING Lfn OPTIONAL)
Definition: strucsup.c:3022
PFCB FatGetNextFcbBottomUp(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PFCB TerminationFcb)
Definition: strucsup.c:2525
IN PDCB TargetDcb
Definition: fatprocs.h:789
VOID NTAPI FatOplockComplete(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:35
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING IN PUNICODE_STRING SuggestedShortName IN OUT BOOLEAN IN OUT BOOLEAN * AllLowerExtension
Definition: fatprocs.h:1310
#define FatIsNameShortOemValid(IRPCONTEXT, NAME, CAN_CONTAIN_WILD_CARDS, PATH_NAME_OK, LEADING_BACKSLASH_OK)
Definition: fatprocs.h:1199
@ Flush
Definition: fatprocs.h:1055
#define FatGetFcbOplock(F)
Definition: fatprocs.h:1657
VOID FatRemoveNames(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb)
Definition: splaysup.c:222
#define FatIsFileOplockable(F)
Definition: fatprocs.h:2852
LARGE_INTEGER FatFatTimeToNtTime(_In_ PIRP_CONTEXT IrpContext, _In_ FAT_TIME_STAMP FatTime, _In_ UCHAR TenMilliSeconds)
Definition: timesup.c:233
#define FatDirectoryKey(FcbOrDcb)
Definition: fatprocs.h:851
LARGE_INTEGER FatFatDateToNtTime(_In_ PIRP_CONTEXT IrpContext, _In_ FAT_DATE FatDate)
Definition: timesup.c:171
#define CCB_FLAG_USER_SET_LAST_WRITE
Definition: fatstruc.h:1266
#define CCB_FLAG_SKIP_SHORT_NAME_COMPARE
Definition: fatstruc.h:1253
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
#define NOTHING
Definition: input_list.c:10
#define NTDDI_VERSION
Definition: k32.h:33
#define PCHAR
Definition: match.c:90
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
BOOLEAN NTAPI FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1, IN PCUNICODE_STRING Name2, IN BOOLEAN IgnoreCase, IN PCWCH UpcaseTable OPTIONAL)
Definition: name.c:296
#define STATUS_PENDING
Definition: ntstatus.h:82
BOOLEAN NTAPI FsRtlCurrentBatchOplock(IN POPLOCK Oplock)
Definition: oplock.c:1364
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1170
unsigned short USHORT
Definition: pedump.c:61
#define Vcb
Definition: cdprocs.h:1415
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:166
#define NTDDI_WIN7
Definition: sdkddkver.h:112
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4356
Definition: cdstruc.h:1067
union _CCB::@733::@735::@737 OemQueryTemplate
UNICODE_STRING UnicodeQueryTemplate
Definition: fatstruc.h:1430
FAT8DOT3 Constant
Definition: fatstruc.h:1426
ULONG Flags
Definition: cdstruc.h:1080
BOOLEAN ContainsWildCards
Definition: fatstruc.h:1379
BOOLEAN ChicagoMode
Definition: fatstruc.h:87
Definition: cdstruc.h:902
struct _FCB * ParentDcb
Definition: fatstruc.h:836
LIST_ENTRY ParentDcbLinks
Definition: fatstruc.h:828
VBO LfnOffsetWithinDirectory
Definition: fatstruc.h:913
ULONG Flags
Definition: ntfs.h:536
union _FCB::@729 Specific
UNICODE_STRING ExactCaseLongName
Definition: fatstruc.h:1139
UNICODE_STRING FullFileName
Definition: fatstruc.h:1122
FCB_CONDITION FcbCondition
Definition: fatstruc.h:850
CLONG OpenCount
Definition: fatstruc.h:881
struct _FCB::@729::@731 Dcb
CLONG UncleanCount
Definition: fatstruc.h:873
ULONG FirstClusterOfFile
Definition: fatstruc.h:818
PNON_PAGED_FCB NonPaged
Definition: fatstruc.h:811
VBO DirentOffsetWithinDirectory
Definition: fatstruc.h:906
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
struct _IO_STACK_LOCATION::@3974::@3984 SetFile
union _IO_STACK_LOCATION::@1575 Parameters
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: fatstruc.h:729
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: cdstruc.h:498
BOOLEAN NTAPI FsRtlFindInTunnelCache(IN PTUNNEL Cache, IN ULONGLONG DirectoryKey, IN PUNICODE_STRING Name, OUT PUNICODE_STRING ShortName, OUT PUNICODE_STRING LongName, IN OUT PULONG DataLength, OUT PVOID Data)
Definition: tunnel.c:766
uint16_t * PWSTR
Definition: typedefs.h:56
union _LARGE_INTEGER LARGE_INTEGER
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
STRING OEM_STRING
Definition: umtypes.h:203
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define FILE_NOTIFY_CHANGE_SIZE
#define FILE_ACTION_MODIFIED
#define FILE_ACTION_RENAMED_OLD_NAME
#define FILE_NOTIFY_CHANGE_LAST_ACCESS
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
#define FILE_ACTION_REMOVED
#define FO_FILE_MODIFIED
Definition: iotypes.h:1788
#define FILE_NOTIFY_CHANGE_FILE_NAME
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FILE_ACTION_RENAMED_NEW_NAME
#define FILE_NOTIFY_CHANGE_CREATION
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define FILE_NOTIFY_CHANGE_EA
#define FILE_ACTION_ADDED
#define FILE_NOTIFY_CHANGE_DIR_NAME
#define ObDereferenceObject
Definition: obfuncs.h:203
unsigned char UCHAR
Definition: xmlstorage.h:181
_In_ PUNICODE_STRING NewName
Definition: zwfuncs.h:1203

Referenced by FatSetRenameInfo().