branch update for HEAD-2003021201
[reactos.git] / drivers / fs / vfat / direntry.c
1 /* $Id$
2  *
3  *
4  * FILE:             DirEntry.c
5  * PURPOSE:          Routines to manipulate directory entries.
6  * COPYRIGHT:        See COPYING in the top level directory
7  * PROJECT:          ReactOS kernel
8  * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
9  *                   Rex Jolliff (rex@lvcablemodem.com)
10  */
11
12 /*  -------------------------------------------------------  INCLUDES  */
13
14 #include <ddk/ntddk.h>
15 #include <wchar.h>
16 #include <limits.h>
17
18 #define NDEBUG
19 #include <debug.h>
20
21 #include "vfat.h"
22
23 #define ENTRIES_PER_PAGE   (PAGE_SIZE / sizeof (FATDirEntry))
24
25 ULONG 
26 vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION  pDeviceExt,
27                              PFAT_DIR_ENTRY  pFatDirEntry)
28 {
29   ULONG  cluster;
30
31   if (pDeviceExt->FatInfo.FatType == FAT32)
32   {
33     cluster = pFatDirEntry->FirstCluster + 
34       pFatDirEntry->FirstClusterHigh * 65536;
35   }
36   else
37   {
38     cluster = pFatDirEntry->FirstCluster;
39   }
40
41   return  cluster;
42 }
43
44 BOOL
45 vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry)
46 {
47   return  pFatDirEntry->Filename [0] == 0xe5;
48 }
49
50 BOOL
51 vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry)
52 {
53   return  pFatDirEntry->Filename [0] == 0;
54 }
55
56 BOOL
57 vfatIsDirEntryLongName (FATDirEntry * pFatDirEntry)
58 {
59   return  pFatDirEntry->Attrib == 0x0f;
60 }
61
62 BOOL
63 vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry)
64 {
65   return 0x08 == (pFatDirEntry->Attrib & 0x1f);
66 }
67
68 void
69 vfatGetDirEntryName (PFAT_DIR_ENTRY  dirEntry,  PWSTR  entryName)
70 {
71   vfat8Dot3ToString (dirEntry, entryName);
72 }
73
74
75 NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
76                              PVOID * pPage,
77                              IN PVFATFCB pDirFcb,
78                              IN OUT PULONG pDirIndex,
79                              OUT PWSTR pFileName,
80                              OUT PFAT_DIR_ENTRY pDirEntry,
81                              OUT PULONG pStartIndex)
82 {
83     ULONG dirMap;
84     PWCHAR pName;
85     LARGE_INTEGER FileOffset;
86     FATDirEntry * fatDirEntry;
87     slot * longNameEntry;
88     ULONG index;
89
90     *pFileName = 0;
91
92     FileOffset.u.HighPart = 0;
93     FileOffset.u.LowPart = ROUND_DOWN(*pDirIndex * sizeof(FATDirEntry), PAGE_SIZE);
94
95     if (*pContext == NULL || (*pDirIndex % ENTRIES_PER_PAGE) == 0)
96     {
97        if (*pContext != NULL)
98        {
99           CcUnpinData(*pContext);
100        }
101        if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
102        {
103           *pContext = NULL;
104           return STATUS_NO_MORE_ENTRIES;
105        }
106     }
107
108
109     fatDirEntry = (FATDirEntry*)(*pPage) + *pDirIndex % ENTRIES_PER_PAGE;
110     longNameEntry = (slot*) fatDirEntry;
111     dirMap = 0;
112
113     if (pStartIndex)
114     {
115         *pStartIndex = *pDirIndex;
116     }
117
118     while (TRUE)
119     {
120         if (vfatIsDirEntryEndMarker(fatDirEntry))
121         {
122             CcUnpinData(*pContext);
123             *pContext = NULL;
124             return STATUS_NO_MORE_ENTRIES;
125         }
126
127         if (vfatIsDirEntryDeleted (fatDirEntry))
128         {
129             dirMap = 0;
130             *pFileName = 0;
131             if (pStartIndex)
132             {
133                 *pStartIndex = *pDirIndex + 1;
134             }
135         }
136         else
137         {
138             if (vfatIsDirEntryLongName (fatDirEntry))
139             {
140                 if (dirMap == 0)
141                 {
142                     DPRINT ("  long name entry found at %d\n", *pDirIndex);
143                     memset(pFileName, 0, 256 * sizeof(WCHAR));
144                 }
145
146                 DPRINT ("  name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
147                          5, longNameEntry->name0_4,
148                          6, longNameEntry->name5_10,
149                          2, longNameEntry->name11_12);
150
151                 index = (longNameEntry->id & 0x1f) - 1;
152                 dirMap |= 1 << index;
153                 pName = pFileName + 13 * index;
154
155                 memcpy(pName, longNameEntry->name0_4, 5 * sizeof(WCHAR));
156                 memcpy(pName + 5, longNameEntry->name5_10, 6 * sizeof(WCHAR));
157                 memcpy(pName + 11, longNameEntry->name11_12, 2 * sizeof(WCHAR));
158       
159                 DPRINT ("  longName: [%S]\n", pFileName);
160             }
161             else
162             {
163                 memcpy (pDirEntry, fatDirEntry, sizeof (FAT_DIR_ENTRY));
164                 break;
165             }
166         }
167         (*pDirIndex)++;
168         if ((*pDirIndex % ENTRIES_PER_PAGE) == 0)
169         {
170             CcUnpinData(*pContext);
171             FileOffset.u.LowPart += PAGE_SIZE;
172             if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
173             {
174                 CHECKPOINT;
175                 *pContext = NULL;
176                 return STATUS_NO_MORE_ENTRIES;
177             }
178             fatDirEntry = (FATDirEntry*)*pPage;
179             longNameEntry = (slot*) *pPage;
180         }
181         else
182         {
183             fatDirEntry++;
184             longNameEntry++;
185         }
186     }
187     return STATUS_SUCCESS;
188 }
189
190
191
192
193
194
195
196