ReactOS 0.4.15-dev-8191-gbc6c731
dirsup.c File Reference
#include "fatprocs.h"
Include dependency graph for dirsup.c:

Go to the source code of this file.

Macros

#define BugCheckFileId   (FAT_BUG_CHECK_DIRSUP)
 
#define Dbg   (DEBUG_TRACE_DIRSUP)
 
#define FatConstructDot(IRPCONTEXT, DCB, PARENT, DIRENT)
 
#define FatConstructDotDot(IRPCONTEXT, DCB, PARENT, DIRENT)
 
#define FatConstructEndDirent(IRPCONTEXT, DIRENT)   NOTHING
 
#define FatReadDirent(IRPCONTEXT, DCB, VBO, BCB, DIRENT, STATUS)
 

Functions

UCHAR FatComputeLfnChecksum (PDIRENT Dirent)
 
 _Requires_lock_held_ (_Global_critical_region_)
 
VOID FatTunnelFcbOrDcb (IN PFCB FcbOrDcb, IN PCCB Ccb OPTIONAL)
 
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)
 
VOID FatConstructLabelDirent (IN PIRP_CONTEXT IrpContext, IN OUT PDIRENT Dirent, IN POEM_STRING Label)
 

Macro Definition Documentation

◆ BugCheckFileId

#define BugCheckFileId   (FAT_BUG_CHECK_DIRSUP)

Definition at line 22 of file dirsup.c.

◆ Dbg

#define Dbg   (DEBUG_TRACE_DIRSUP)

Definition at line 28 of file dirsup.c.

◆ FatConstructDot

#define FatConstructDot (   IRPCONTEXT,
  DCB,
  PARENT,
  DIRENT 
)
Value:
{ \
\
RtlCopyMemory( (PUCHAR)(DIRENT), ". ", 11 ); \
(DIRENT)->LastWriteTime = (PARENT)->LastWriteTime; \
(DIRENT)->CreationTime = (PARENT)->CreationTime; \
(DIRENT)->CreationMSec = (PARENT)->CreationMSec; \
(DIRENT)->LastAccessDate = (PARENT)->LastAccessDate; \
} \
(DIRENT)->FirstClusterOfFile = \
(USHORT)(DCB)->FirstClusterOfFile; \
(DIRENT)->FirstClusterOfFileHi = \
(USHORT)((DCB)->FirstClusterOfFile/0x10000); \
}
#define FAT_DIRENT_ATTR_DIRECTORY
Definition: fat.h:372
FAT_DATA FatData
Definition: fatdata.c:56
#define DIRENT
Definition: fatfs.h:187
FCB DCB
Definition: fatstruc.h:1184
unsigned short USHORT
Definition: pedump.c:61
BOOLEAN ChicagoMode
Definition: fatstruc.h:87
unsigned char * PUCHAR
Definition: typedefs.h:53
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes

Definition at line 49 of file dirsup.c.

◆ FatConstructDotDot

#define FatConstructDotDot (   IRPCONTEXT,
  DCB,
  PARENT,
  DIRENT 
)
Value:
{ \
\
RtlCopyMemory( (PUCHAR)(DIRENT), ".. ", 11 ); \
(DIRENT)->LastWriteTime = (PARENT)->LastWriteTime; \
(DIRENT)->CreationTime = (PARENT)->CreationTime; \
(DIRENT)->CreationMSec = (PARENT)->CreationMSec; \
(DIRENT)->LastAccessDate = (PARENT)->LastAccessDate; \
} \
(DIRENT)->FirstClusterOfFile = 0; \
(DIRENT)->FirstClusterOfFileHi = 0; \
} else { \
(DIRENT)->FirstClusterOfFile = (USHORT) \
((DCB)->ParentDcb->FirstClusterOfFile); \
(DIRENT)->FirstClusterOfFileHi = (USHORT) \
((DCB)->ParentDcb->FirstClusterOfFile/0x10000); \
} \
}
#define NodeType(P)
Definition: nodetype.h:51
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB ParentDcb
Definition: create.c:4141
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
Definition: cdstruc.h:902

Definition at line 80 of file dirsup.c.

◆ FatConstructEndDirent

#define FatConstructEndDirent (   IRPCONTEXT,
  DIRENT 
)    NOTHING

Definition at line 113 of file dirsup.c.

◆ FatReadDirent

#define FatReadDirent (   IRPCONTEXT,
  DCB,
  VBO,
  BCB,
  DIRENT,
  STATUS 
)
Value:
if ((VBO) >= (DCB)->Header.AllocationSize.LowPart) { \
FatUnpinBcb( (IRPCONTEXT), *(BCB) ); \
} else if ( ((VBO) % PAGE_SIZE == 0) || (*(BCB) == NULL) ) { \
FatUnpinBcb( (IRPCONTEXT), *(BCB) ); \
FatReadDirectoryFile( (IRPCONTEXT), \
(DCB), \
(VBO) & ~(PAGE_SIZE - 1), \
FALSE, \
(BCB), \
(PVOID *)(DIRENT), \
(STATUS) ); \
*(DIRENT) = (PVOID)((PUCHAR)*(DIRENT) + ((VBO) % PAGE_SIZE)); \
}
#define STATUS
Definition: blue.h:116
Definition: Header.h:9
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
ULONG32 VBO
Definition: fat.h:38
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define STATUS_END_OF_FILE
Definition: shellext.h:67

Definition at line 132 of file dirsup.c.

Function Documentation

◆ _Requires_lock_held_()

_Requires_lock_held_ ( _Global_critical_region_  )

Definition at line 158 of file dirsup.c.

231{
232 VBO UnusedVbo;
233 VBO DeletedHint;
235
236 PBCB Bcb = NULL;
239
240 PAGED_CODE();
241
242 DebugTrace(+1, Dbg, "FatCreateNewDirent\n", 0);
243
244 DebugTrace( 0, Dbg, " ParentDirectory = %p\n", ParentDirectory);
245
246 //
247 // If UnusedDirentVbo is within our current file allocation then we
248 // don't have to search through the directory at all; we know just
249 // where to put it.
250 //
251 // If UnusedDirentVbo is beyond the current file allocation then
252 // there are no more unused dirents in the current allocation, though
253 // upon adding another cluster of allocation UnusedDirentVbo
254 // will point to an unused dirent. Haveing found no unused dirents
255 // we use the DeletedDirentHint to try and find a deleted dirent in
256 // the current allocation. In this also runs off the end of the file,
257 // we finally have to break down and allocate another sector. Note
258 // that simply writing beyond the current allocation will automatically
259 // do just this.
260 //
261 // We also must deal with the special case where UnusedDirentVbo and
262 // DeletedDirentHint have yet to be initialized. In this case we must
263 // first walk through the directory looking for the first deleted entry
264 // first unused dirent. After this point we continue as before.
265 // This initial state is denoted by the special value of 0xffffffff.
266 //
267
268 UnusedVbo = ParentDirectory->Specific.Dcb.UnusedDirentVbo;
269 DeletedHint = ParentDirectory->Specific.Dcb.DeletedDirentHint;
270
271 //
272 // Check for our first call to this routine with this Dcb. If so
273 // we have to correctly set the two hints in the Dcb.
274 //
275
276 if (UnusedVbo == 0xffffffff || RescanDir) {
277
278 FatRescanDirectory( IrpContext, ParentDirectory );
279
280 UnusedVbo = ParentDirectory->Specific.Dcb.UnusedDirentVbo;
281 DeletedHint = ParentDirectory->Specific.Dcb.DeletedDirentHint;
282 }
283
284 //
285 // Now we know that UnusedDirentVbo and DeletedDirentHint are correctly
286 // set so we check if there is already an unused dirent in the the
287 // current allocation. This is the easy case.
288 //
289
290 DebugTrace( 0, Dbg, " UnusedVbo = %08lx\n", UnusedVbo);
291 DebugTrace( 0, Dbg, " DeletedHint = %08lx\n", DeletedHint);
292
293 if (!RescanDir && ( UnusedVbo + (DirentsNeeded * sizeof(DIRENT)) <=
294 ParentDirectory->Header.AllocationSize.LowPart )) {
295
296 //
297 // Get this unused dirent for the caller. We have a
298 // sporting chance that we won't have to wait.
299 //
300
301 DebugTrace( 0, Dbg, "There is a never used entry.\n", 0);
302
303 ByteOffset = UnusedVbo;
304
305 UnusedVbo += DirentsNeeded * sizeof(DIRENT);
306
307 } else {
308
309 //
310 // Life is tough. We have to march from the DeletedDirentHint
311 // looking for a deleted dirent. If we get to EOF without finding
312 // one, we will have to allocate a new cluster.
313 //
314
315 ByteOffset =
316 RtlFindClearBits( &ParentDirectory->Specific.Dcb.FreeDirentBitmap,
318 DeletedHint / sizeof(DIRENT) );
319
320 //
321 // Do a quick check for a root directory allocation that failed
322 // simply because of fragmentation. Also, only attempt to defrag
323 // if the length is less that 0x40000. This is to avoid
324 // complications arising from crossing a MM view boundary (256kb).
325 // By default on DOS the root directory is only 0x2000 long.
326 //
327 // Don't try to defrag fat32 root dirs.
328 //
329
331 (ByteOffset == -1) &&
333 (ParentDirectory->Header.AllocationSize.LowPart <= 0x40000)) {
334
335 ByteOffset = FatDefragDirectory( IrpContext, ParentDirectory, DirentsNeeded );
336 }
337
338 if (ByteOffset != -1) {
339
340 //
341 // If we consuemed deleted dirents at Deleted Hint, update.
342 // We also may have consumed some un-used dirents as well,
343 // so be sure to check for that as well.
344 //
345
346 ByteOffset *= sizeof(DIRENT);
347
348 if (ByteOffset == DeletedHint) {
349
350 DeletedHint += DirentsNeeded * sizeof(DIRENT);
351 }
352
353 if (ByteOffset + DirentsNeeded * sizeof(DIRENT) > UnusedVbo) {
354
355 UnusedVbo = ByteOffset + DirentsNeeded * sizeof(DIRENT);
356 }
357
358 } else {
359
360 //
361 // We are going to have to allocate another cluster. Do
362 // so, update both the UnusedVbo and the DeletedHint and bail.
363 //
364
365 DebugTrace( 0, Dbg, "We have to allocate another cluster.\n", 0);
366
367 //
368 // A reason why we might fail, unrelated to physical reasons,
369 // is that we constrain to 64k directory entries to match the
370 // restriction on Win95. There are fundamental reasons to do
371 // this since searching a FAT directory is a linear operation
372 // and to allow FAT32 to toss us over the cliff is not permissable.
373 //
374
375 if (ParentDirectory->Header.AllocationSize.LowPart >= (64 * 1024 * sizeof(DIRENT)) ||
376
377 //
378 // Make sure we are not trying to expand the root directory on non
379 // FAT32. FAT16 and FAT12 have fixed size allocations.
380 //
381
384
385 DebugTrace(0, Dbg, "Full root directory or too big on FAT32. Raise Status.\n", 0);
386
387 FatRaiseStatus( IrpContext, STATUS_CANNOT_MAKE );
388 }
389
390 //
391 // Take the last dirent(s) in this cluster. We will allocate
392 // more clusters below.
393 //
394
395 ByteOffset = UnusedVbo;
396 UnusedVbo += DirentsNeeded * sizeof(DIRENT);
397
398 //
399 // Touch the directory file to cause space for the new dirents
400 // to be allocated.
401 //
402
403 Bcb = NULL;
404
405 _SEH2_TRY {
406
408
409 FatPrepareWriteDirectoryFile( IrpContext,
411 UnusedVbo,
412 1,
413 &Bcb,
414 &Buffer,
415 FALSE,
416 TRUE,
417 &Status );
418
419 } _SEH2_FINALLY {
420
421 FatUnpinBcb( IrpContext, Bcb );
422 } _SEH2_END;
423 }
424 }
425
426 //
427 // If we are only requesting a single dirent, and we did not get the
428 // first dirent in a directory, then check that the preceding dirent
429 // is not an orphaned LFN. If it is, then mark it deleted. Thus
430 // reducing the possibility of an accidental pairing.
431 //
432 // Only do this when we are in Chicago Mode.
433 //
434
435 Bcb = NULL;
436
437 if (FatData.ChicagoMode &&
438 (DirentsNeeded == 1) &&
440 0 : 2 * sizeof(DIRENT)))) {
441 _SEH2_TRY {
442
443 FatReadDirent( IrpContext,
445 ByteOffset - sizeof(DIRENT),
446 &Bcb,
447 &Dirent,
448 &Status );
449
450 if ((Status != STATUS_SUCCESS) ||
451 (Dirent->FileName[0] == FAT_DIRENT_NEVER_USED)) {
452
453 FatPopUpFileCorrupt( IrpContext, ParentDirectory );
454
456 }
457
458 if ((Dirent->Attributes == FAT_DIRENT_ATTR_LFN) &&
459 (Dirent->FileName[0] != FAT_DIRENT_DELETED)) {
460
461 //
462 // Pin it, mark it, and set it dirty.
463 //
464
465 FatPinMappedData( IrpContext,
467 ByteOffset - sizeof(DIRENT),
468 sizeof(DIRENT),
469 &Bcb );
470
471 Dirent->FileName[0] = FAT_DIRENT_DELETED;
472
473 FatSetDirtyBcb( IrpContext, Bcb, ParentDirectory->Vcb, TRUE );
474
476 (ByteOffset - sizeof(DIRENT))/ sizeof(DIRENT),
477 DirentsNeeded ) );
478
479 RtlClearBits( &ParentDirectory->Specific.Dcb.FreeDirentBitmap,
480 (ByteOffset - sizeof(DIRENT))/ sizeof(DIRENT),
482
483 }
484
485 } _SEH2_FINALLY {
486
487 FatUnpinBcb( IrpContext, Bcb );
488 } _SEH2_END;
489 }
490
491 //
492 // Assert that the dirents are in fact unused
493 //
494
495 _SEH2_TRY {
496
497 ULONG i;
498
499 Bcb = NULL;
500
501 for (i = 0; i < DirentsNeeded; i++) {
502
503 FatReadDirent( IrpContext,
505 ByteOffset + i*sizeof(DIRENT),
506 &Bcb,
507 &Dirent,
508 &Status );
509
510 if ((Status != STATUS_SUCCESS) ||
511 ((Dirent->FileName[0] != FAT_DIRENT_NEVER_USED) &&
512 (Dirent->FileName[0] != FAT_DIRENT_DELETED))) {
513
514 FatPopUpFileCorrupt( IrpContext, ParentDirectory );
516 }
517 }
518
519 } _SEH2_FINALLY {
520
521 FatUnpinBcb( IrpContext, Bcb );
522 } _SEH2_END;
523
524 //
525 // Set the Bits in the bitmap and move the Unused Dirent Vbo.
526 //
527
529 ByteOffset / sizeof(DIRENT),
530 DirentsNeeded ) );
531
532 RtlSetBits( &ParentDirectory->Specific.Dcb.FreeDirentBitmap,
533 ByteOffset / sizeof(DIRENT),
535
536 //
537 // Save the newly computed values in the Parent Directory Fcb
538 //
539
540 ParentDirectory->Specific.Dcb.UnusedDirentVbo = UnusedVbo;
541 ParentDirectory->Specific.Dcb.DeletedDirentHint = DeletedHint;
542
543 DebugTrace(-1, Dbg, "FatCreateNewDirent -> (VOID)\n", 0);
544
545 return ByteOffset;
546}
NodeType
Definition: Node.h:6
LONG NTSTATUS
Definition: precomp.h:26
PAGED_CODE()
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
Definition: dirsup.c:425
Definition: bufpool.h:45
#define TRUE
Definition: types.h:120
#define FAT_DIRENT_DELETED
Definition: fat.h:337
#define FAT_DIRENT_NEVER_USED
Definition: fat.h:334
#define FAT_DIRENT_ATTR_LFN
Definition: fat.h:375
VOID FatPinMappedData(IN PIRP_CONTEXT IrpContext, IN PDCB Dcb, IN VBO StartingVbo, IN ULONG ByteCount, OUT PBCB *Bcb)
Definition: cachesup.c:1866
#define FatReadDirent(IRPCONTEXT, DCB, VBO, BCB, DIRENT, STATUS)
Definition: dirsup.c:132
#define Dbg
Definition: dirsup.c:28
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
IN PDCB IN ULONG IN BOOLEAN RescanDir
Definition: fatprocs.h:701
IN PVCB IN VBO IN ULONG OUT PBCB * Bcb
Definition: fatprocs.h:414
#define FatUnpinBcb(IRPCONTEXT, BCB)
Definition: fatprocs.h:546
IN PDCB ParentDirectory
Definition: fatprocs.h:698
IN PDCB IN ULONG DirentsNeeded
Definition: fatprocs.h:699
#define FatRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2977
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:731
#define FatIsFat32(VCB)
Definition: fatprocs.h:1446
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
Status
Definition: gdiplustypes.h:25
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
NTSYSAPI BOOLEAN WINAPI RtlAreBitsClear(PCRTL_BITMAP, ULONG, ULONG)
NTSYSAPI ULONG WINAPI RtlFindClearBits(PCRTL_BITMAP, ULONG, ULONG)
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
NTSYSAPI BOOLEAN WINAPI RtlAreBitsSet(PCRTL_BITMAP, ULONG, ULONG)
#define STATUS_CANNOT_MAKE
Definition: ntstatus.h:854
#define STATUS_SUCCESS
Definition: shellext.h:65
PVCB Vcb
Definition: cdstruc.h:933
union _FCB::@727 Specific
struct _FCB::@727::@729 Dcb
FSRTL_ADVANCED_FCB_HEADER Header
Definition: cdstruc.h:925
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
#define NT_ASSERT
Definition: rtlfuncs.h:3310

◆ FatComputeLfnChecksum()

UCHAR FatComputeLfnChecksum ( PDIRENT  Dirent)

Definition at line 2878 of file dirsup.c.

2898{
2899 ULONG i;
2900 UCHAR Checksum;
2901
2902 PAGED_CODE();
2903
2904 Checksum = Dirent->FileName[0];
2905
2906 for (i=1; i < 11; i++) {
2907
2908 Checksum = ((Checksum & 1) ? 0x80 : 0) +
2909 (Checksum >> 1) +
2910 Dirent->FileName[i];
2911 }
2912
2913 return Checksum;
2914}
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by FatConstructDirent().

◆ FatConstructDirent()

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 at line 2171 of file dirsup.c.

2218{
2219 PAGED_CODE();
2220
2221 DebugTrace(+1, Dbg, "FatConstructDirent\n", 0);
2222
2223 DebugTrace( 0, Dbg, " Dirent = %p\n", Dirent);
2224 DebugTrace( 0, Dbg, " FileName = %Z\n", FileName);
2225 DebugTrace( 0, Dbg, " Attributes = %08lx\n", Attributes);
2226
2227 if (ZeroAndSetTimeFields) {
2228
2229 RtlZeroMemory( Dirent, sizeof(DIRENT) );
2230 }
2231
2232 //
2233 // We just merrily go and fill up the dirent with the fields given.
2234 //
2235
2236 FatStringTo8dot3( IrpContext, *FileName, (PFAT8DOT3)&Dirent->FileName[0] );
2237
2238 if (ZeroAndSetTimeFields || SetCreationTime) {
2239
2240 LARGE_INTEGER Time, SaveTime;
2241
2243
2244 if (FatData.ChicagoMode) {
2245
2246 if (!SetCreationTime || !FatNtTimeToFatTime( IrpContext,
2247 SetCreationTime,
2248 FALSE,
2250 &Dirent->CreationMSec )) {
2251
2252 //
2253 // No tunneled time or the tunneled time was bogus. Since we aren't
2254 // responsible for initializing the to-be-created Fcb with creation
2255 // time, we can't do the usual thing and let NtTimeToFatTime perform
2256 // rounding on the timestamp - this would mess up converting to the
2257 // LastWriteTime below.
2258 //
2259
2260 SaveTime = Time;
2261
2262 if (!FatNtTimeToFatTime( IrpContext,
2263 &SaveTime,
2264 FALSE,
2266 &Dirent->CreationMSec )) {
2267
2268 //
2269 // Failed again. Wow.
2270 //
2271
2273 Dirent->CreationMSec = 0;
2274 }
2275 }
2276 }
2277
2278 if (ZeroAndSetTimeFields) {
2279
2280 //
2281 // We only touch the other timestamps if we are initializing the dirent
2282 //
2283
2284 if (!FatNtTimeToFatTime( IrpContext,
2285 &Time,
2286 TRUE,
2288 NULL )) {
2289
2290 DebugTrace( 0, Dbg, "Current time invalid.\n", 0);
2291
2293 }
2294
2295 if (FatData.ChicagoMode) {
2296
2297 Dirent->LastAccessDate = Dirent->LastWriteTime.Date;
2298 }
2299 }
2300 }
2301
2302 //
2303 // Copy the attributes
2304 //
2305
2306 Dirent->Attributes = (UCHAR)Attributes;
2307
2308 //
2309 // Set the magic bit here, to tell dirctrl.c that this name is really
2310 // lowercase.
2311 //
2312
2313 Dirent->NtByte = 0;
2314
2315 if (ComponentReallyLowercase) {
2316
2318 }
2319
2320 if (ExtensionReallyLowercase) {
2321
2323 }
2324
2325 //
2326 // See if we have to create an Lfn entry
2327 //
2328
2329 if (ARGUMENT_PRESENT(Lfn)) {
2330
2331 UCHAR DirentChecksum;
2332 UCHAR DirentsInLfn;
2333 UCHAR LfnOrdinal;
2334 PWCHAR LfnBuffer;
2335 PLFN_DIRENT LfnDirent;
2336
2338
2339 DirentChecksum = FatComputeLfnChecksum( Dirent );
2340
2341 LfnOrdinal =
2342 DirentsInLfn = (UCHAR)FAT_LFN_DIRENTS_NEEDED(Lfn);
2343
2344 LfnBuffer = &Lfn->Buffer[(DirentsInLfn - 1) * 13];
2345
2346 NT_ASSERT( DirentsInLfn <= MAX_LFN_DIRENTS );
2347
2348 for (LfnDirent = (PLFN_DIRENT)Dirent - DirentsInLfn;
2349 LfnDirent < (PLFN_DIRENT)Dirent;
2350 LfnDirent += 1, LfnOrdinal -= 1, LfnBuffer -= 13) {
2351
2352 WCHAR FinalLfnBuffer[13];
2353 PWCHAR Buffer;
2354
2355 //
2356 // We need to special case the "final" dirent.
2357 //
2358
2359 if (LfnOrdinal == DirentsInLfn) {
2360
2361 ULONG i;
2362 ULONG RemainderChars;
2363
2364 RemainderChars = (Lfn->Length / sizeof(WCHAR)) % 13;
2365
2366 LfnDirent->Ordinal = LfnOrdinal | FAT_LAST_LONG_ENTRY;
2367
2368 if (RemainderChars != 0) {
2369
2370 RtlCopyMemory( FinalLfnBuffer,
2371 LfnBuffer,
2372 RemainderChars * sizeof(WCHAR) );
2373
2374 for (i = RemainderChars; i < 13; i++) {
2375
2376 //
2377 // Figure out which character to use.
2378 //
2379
2380 if (i == RemainderChars) {
2381
2382 FinalLfnBuffer[i] = 0x0000;
2383
2384 } else {
2385
2386 FinalLfnBuffer[i] = 0xffff;
2387 }
2388 }
2389
2390 Buffer = FinalLfnBuffer;
2391
2392 } else {
2393
2394 Buffer = LfnBuffer;
2395 }
2396
2397 } else {
2398
2399 LfnDirent->Ordinal = LfnOrdinal;
2400
2401 Buffer = LfnBuffer;
2402 }
2403
2404 //
2405 // Now fill in the name.
2406 //
2407
2408 RtlCopyMemory( &LfnDirent->Name1[0],
2409 &Buffer[0],
2410 5 * sizeof(WCHAR) );
2411
2412 RtlCopyMemory( &LfnDirent->Name2[0],
2413 &Buffer[5],
2414 6 * sizeof(WCHAR) );
2415
2416 RtlCopyMemory( &LfnDirent->Name3[0],
2417 &Buffer[11],
2418 2 * sizeof(WCHAR) );
2419
2420 //
2421 // And the other fields
2422 //
2423
2424 LfnDirent->Attributes = FAT_DIRENT_ATTR_LFN;
2425
2426 LfnDirent->Type = 0;
2427
2428 LfnDirent->Checksum = DirentChecksum;
2429
2430 LfnDirent->MustBeZero = 0;
2431 }
2432 }
2433
2434 DebugTrace(-1, Dbg, "FatConstructDirent -> (VOID)\n", 0);
2435 return;
2436}
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING Lfn
Definition: create.c:4145
#define FAT_DIRENT_NT_BYTE_8_LOWER_CASE
Definition: fat.h:361
#define FAT_DIRENT_NT_BYTE_3_LOWER_CASE
Definition: fat.h:362
FAT8DOT3 * PFAT8DOT3
Definition: fat.h:296
#define MAX_LFN_DIRENTS
Definition: lfn.h:51
#define FAT_LAST_LONG_ENTRY
Definition: lfn.h:35
LFN_DIRENT * PLFN_DIRENT
Definition: lfn.h:44
#define FAT_LFN_DIRENTS_NEEDED(NAME)
Definition: lfn.h:53
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
UCHAR FatComputeLfnChecksum(PDIRENT Dirent)
Definition: dirsup.c:2878
VOID FatStringTo8dot3(_In_ PIRP_CONTEXT IrpContext, _In_ OEM_STRING InputString, _Out_writes_bytes_(11) PFAT8DOT3 Output8dot3)
Definition: namesup.c:79
static PLARGE_INTEGER Time
Definition: time.c:105
#define ARGUMENT_PRESENT(ArgumentPointer)
LONGLONG CreationTime
Definition: cdstruc.h:1030
LARGE_INTEGER LastWriteTime
Definition: fatstruc.h:922
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint16_t * PWCHAR
Definition: typedefs.h:56
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by FatSetRenameInfo().

◆ FatConstructLabelDirent()

VOID FatConstructLabelDirent ( IN PIRP_CONTEXT  IrpContext,
IN OUT PDIRENT  Dirent,
IN POEM_STRING  Label 
)

Definition at line 2440 of file dirsup.c.

2465{
2466 PAGED_CODE();
2467
2468 DebugTrace(+1, Dbg, "FatConstructLabelDirent\n", 0);
2469
2470 DebugTrace( 0, Dbg, " Dirent = %p\n", Dirent);
2471 DebugTrace( 0, Dbg, " Label = %Z\n", Label);
2472
2473 RtlZeroMemory( Dirent, sizeof(DIRENT) );
2474
2475 //
2476 // We just merrily go and fill up the dirent with the fields given.
2477 //
2478
2479 RtlCopyMemory( Dirent->FileName, Label->Buffer, Label->Length );
2480
2481 //
2482 // Pad the label with spaces, not nulls.
2483 //
2484
2485 RtlFillMemory( &Dirent->FileName[Label->Length], 11 - Label->Length, ' ');
2486
2487 Dirent->LastWriteTime = FatGetCurrentFatTime( IrpContext );
2488
2489 Dirent->Attributes = FAT_DIRENT_ATTR_VOLUME_ID;
2490 Dirent->ExtendedAttributes = 0;
2491 Dirent->FileSize = 0;
2492
2493 DebugTrace(-1, Dbg, "FatConstructLabelDirent -> (VOID)\n", 0);
2494 return;
2495}
PWCHAR Label
Definition: format.c:70
#define FAT_DIRENT_ATTR_VOLUME_ID
Definition: fat.h:371
FAT_TIME_STAMP FatGetCurrentFatTime(_In_ PIRP_CONTEXT IrpContext)
Definition: timesup.c:317
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:599

Referenced by FatSetFsLabelInfo().

◆ FatTunnelFcbOrDcb()

VOID FatTunnelFcbOrDcb ( IN PFCB  FcbOrDcb,
IN PCCB Ccb  OPTIONAL 
)

Definition at line 652 of file dirsup.c.

675{
676 UNICODE_STRING ShortNameWithCase = {0};
677 UNICODE_STRING DownCaseSeg;
678 WCHAR ShortNameBuffer[8+1+3];
680 USHORT i;
681
682 PAGED_CODE();
683
684 DebugTrace(+1, Dbg, "FatTunnelFcbOrDcb\n", 0);
685
686 if (NodeType(FcbOrDcb) == FAT_NTC_DCB) {
687
688 //
689 // Directory deletion. Flush all entries from this directory in
690 // the cache for this volume
691 //
692
695
696 } else {
697
698 //
699 // Was a file, so throw it into the tunnel cache
700 //
701
702 //
703 // Get the short name into UNICODE
704 //
705
706 ShortNameWithCase.Length = 0;
707 ShortNameWithCase.MaximumLength = sizeof(ShortNameBuffer);
708 ShortNameWithCase.Buffer = ShortNameBuffer;
709
710#ifdef _MSC_VER
711#pragma prefast( suppress:28931, "needed for debug build" )
712#endif
713 Status = RtlOemStringToCountedUnicodeString( &ShortNameWithCase,
715 FALSE);
716
717 NT_ASSERT(ShortNameWithCase.Length != 0);
718
720
722
723 //
724 // Have to repair the case of the short name
725 //
726
727 for (i = 0; i < (ShortNameWithCase.Length/sizeof(WCHAR)) &&
728 ShortNameWithCase.Buffer[i] != L'.'; i++);
729
730 //
731 // Now pointing at the '.', or otherwise the end of name component
732 //
733
735
736 DownCaseSeg.Buffer = ShortNameWithCase.Buffer;
737 DownCaseSeg.MaximumLength = DownCaseSeg.Length = i*sizeof(WCHAR);
738
739 RtlDowncaseUnicodeString(&DownCaseSeg, &DownCaseSeg, FALSE);
740 }
741
742 i++;
743
744 //
745 // Now pointing at first wchar of the extension.
746 //
747
749
750 //
751 // It is not neccesarily the case that we can rely on the flag
752 // indicating that we really have an extension.
753 //
754
755 if ((i*sizeof(WCHAR)) < ShortNameWithCase.Length) {
756 DownCaseSeg.Buffer = &ShortNameWithCase.Buffer[i];
757 DownCaseSeg.MaximumLength = DownCaseSeg.Length = ShortNameWithCase.Length - i*sizeof(WCHAR);
758
759 RtlDowncaseUnicodeString(&DownCaseSeg, &DownCaseSeg, FALSE);
760 }
761 }
762 }
763
764 //
765 // ... and add it in
766 //
767
770 &ShortNameWithCase,
773 sizeof(LARGE_INTEGER),
775 }
776
777 DebugTrace(-1, Dbg, "FatTunnelFcbOrDcb -> (VOID)\n", 0);
778
779 return;
780}
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define FAT_NTC_DCB
Definition: nodetype.h:30
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN PFCB FcbOrDcb
Definition: fatprocs.h:306
#define FatDirectoryKey(FcbOrDcb)
Definition: fatprocs.h:850
#define FCB_STATE_8_LOWER_CASE
Definition: fatstruc.h:1210
#define CCB_FLAG_OPENED_BY_SHORTNAME
Definition: fatstruc.h:1296
#define FCB_STATE_3_LOWER_CASE
Definition: fatstruc.h:1211
NTSYSAPI NTSTATUS WINAPI RtlDowncaseUnicodeString(UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN)
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI RtlOemStringToCountedUnicodeString(IN OUT PUNICODE_STRING UniDest, IN PCOEM_STRING OemSource, IN BOOLEAN AllocateDestinationString)
Definition: unicode.c:1473
struct _FCB * ParentDcb
Definition: fatstruc.h:836
ULONG Flags
Definition: ntfs.h:536
UNICODE_STRING ExactCaseLongName
Definition: fatstruc.h:1139
ULONG FcbState
Definition: cdstruc.h:971
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1115
OEM_STRING Oem
Definition: fatstruc.h:693
union _FILE_NAME_NODE::@726 Name
USHORT MaximumLength
Definition: env_spec_w32.h:370
TUNNEL Tunnel
Definition: fatstruc.h:512
VOID NTAPI FsRtlAddToTunnelCache(IN PTUNNEL Cache, IN ULONGLONG DirectoryKey, IN PUNICODE_STRING ShortName, IN PUNICODE_STRING LongName, IN BOOLEAN KeyByShortName, IN ULONG DataLength, IN PVOID Data)
Definition: tunnel.c:342
VOID NTAPI FsRtlDeleteKeyFromTunnelCache(IN PTUNNEL Cache, IN ULONGLONG DirectoryKey)
Definition: tunnel.c:589

Referenced by _Requires_lock_held_(), and FatSetRenameInfo().