Fixed the 'REACTOS' volume label bug.
[reactos.git] / reactos / drivers / fs / vfat / direntry.c
1 /* $Id: direntry.c,v 1.3 2001/07/28 07:05:56 hbirr Exp $
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 CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->BytesPerCluster > PAGESIZE ? \
24 (pDeviceExt)->BytesPerCluster : PAGESIZE)
25
26 #define ENTRIES_PER_CACHEPAGE(pDeviceExt) (ENTRIES_PER_SECTOR * \
27 (CACHEPAGESIZE(pDeviceExt) / ((pDeviceExt)->BytesPerSector)))
28
29
30 ULONG
31 vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
32 PFAT_DIR_ENTRY pFatDirEntry)
33 {
34 ULONG cluster;
35
36 if (pDeviceExt->FatType == FAT32)
37 {
38 cluster = pFatDirEntry->FirstCluster +
39 pFatDirEntry->FirstClusterHigh * 65536;
40 }
41 else
42 {
43 cluster = pFatDirEntry->FirstCluster;
44 }
45
46 return cluster;
47 }
48
49 BOOL
50 vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry)
51 {
52 return pFatDirEntry->Filename [0] == 0xe5;
53 }
54
55 BOOL
56 vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry)
57 {
58 return pFatDirEntry->Filename [0] == 0;
59 }
60
61 BOOL
62 vfatIsDirEntryLongName (FATDirEntry * pFatDirEntry)
63 {
64 return pFatDirEntry->Attrib == 0x0f;
65 }
66
67 BOOL
68 vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry)
69 {
70 return pFatDirEntry->Attrib == 0x28;
71 }
72
73 void
74 vfatGetDirEntryName (PFAT_DIR_ENTRY dirEntry, PWSTR entryName)
75 {
76 vfat8Dot3ToString (dirEntry->Filename, dirEntry->Ext, entryName);
77 }
78
79 NTSTATUS
80 vfatGetNextDirEntry (PDEVICE_EXTENSION pDeviceExt,
81 PVFATFCB pDirectoryFCB,
82 ULONG * pDirectoryIndex,
83 PWSTR pLongFileName,
84 PFAT_DIR_ENTRY pDirEntry)
85 {
86 NTSTATUS status;
87 ULONG indexInPage = *pDirectoryIndex % ENTRIES_PER_CACHEPAGE(pDeviceExt);
88 ULONG pageNumber = *pDirectoryIndex / ENTRIES_PER_CACHEPAGE(pDeviceExt);
89 PVOID currentPage = NULL;
90 PCACHE_SEGMENT cacheSegment = NULL;
91 FATDirEntry * fatDirEntry;
92 slot * longNameEntry;
93 ULONG cpos;
94
95 DPRINT ("vfatGetNextDirEntry (%x,%x,%d,%x,%x)\n",
96 pDeviceExt,
97 pDirectoryFCB,
98 *pDirectoryIndex,
99 pLongFileName,
100 pDirEntry);
101
102 *pLongFileName = 0;
103
104 DPRINT ("Validating current directory page\n");
105 status = vfatRequestAndValidateRegion (pDeviceExt,
106 pDirectoryFCB,
107 pageNumber * CACHEPAGESIZE(pDeviceExt),
108 (PVOID *) &currentPage,
109 &cacheSegment,
110 FALSE);
111 if (!NT_SUCCESS (status))
112 {
113 return status;
114 }
115
116 while (TRUE)
117 {
118 fatDirEntry = (FATDirEntry *) currentPage;
119
120 if (vfatIsDirEntryEndMarker (&fatDirEntry [indexInPage]))
121 {
122 DPRINT ("end of directory, returning no more entries\n");
123 status = vfatReleaseRegion (pDeviceExt,
124 pDirectoryFCB,
125 cacheSegment);
126 return STATUS_NO_MORE_ENTRIES;
127 }
128 else if (vfatIsDirEntryLongName (&fatDirEntry [indexInPage]))
129 {
130 DPRINT (" long name entry found at %d\n", *pDirectoryIndex);
131 longNameEntry = (slot *) currentPage;
132
133 DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
134 5, longNameEntry [indexInPage].name0_4,
135 6, longNameEntry [indexInPage].name5_10,
136 2, longNameEntry [indexInPage].name11_12);
137
138 vfat_initstr (pLongFileName, 256);
139 vfat_wcsncpy (pLongFileName, longNameEntry [indexInPage].name0_4, 5);
140 vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name5_10, 5, 6);
141 vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name11_12, 11, 2);
142
143 DPRINT (" longName: [%S]\n", pLongFileName);
144
145 cpos = 0;
146 while ((longNameEntry [indexInPage].id != 0x41) &&
147 (longNameEntry [indexInPage].id != 0x01) &&
148 (longNameEntry [indexInPage].attr > 0))
149 {
150 (*pDirectoryIndex)++;
151 indexInPage++;
152 if (indexInPage == ENTRIES_PER_CACHEPAGE(pDeviceExt))
153 {
154 indexInPage = 0;
155 pageNumber++;
156
157 status = vfatReleaseRegion (pDeviceExt,
158 pDirectoryFCB,
159 cacheSegment);
160 if (!NT_SUCCESS (status))
161 {
162 return status;
163 }
164 status = vfatRequestAndValidateRegion (pDeviceExt,
165 pDirectoryFCB,
166 pageNumber * CACHEPAGESIZE(pDeviceExt),
167 (PVOID *) &currentPage,
168 &cacheSegment,
169 FALSE);
170 if (!NT_SUCCESS (status))
171 {
172 return status;
173 }
174 longNameEntry = (slot *) currentPage;
175 }
176 DPRINT (" index %d\n", *pDirectoryIndex);
177
178 DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
179 5, longNameEntry [indexInPage].name0_4,
180 6, longNameEntry [indexInPage].name5_10,
181 2, longNameEntry [indexInPage].name11_12);
182
183 cpos++;
184 vfat_movstr (pLongFileName, 13, 0, cpos * 13);
185 vfat_wcsncpy (pLongFileName, longNameEntry [indexInPage].name0_4, 5);
186 vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name5_10, 5, 6);
187 vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name11_12, 11, 2);
188
189 DPRINT (" longName: [%S]\n", pLongFileName);
190
191 }
192 (*pDirectoryIndex)++;
193 indexInPage++;
194 if (indexInPage == ENTRIES_PER_CACHEPAGE(pDeviceExt))
195 {
196 indexInPage = 0;
197 pageNumber++;
198
199 status = vfatReleaseRegion (pDeviceExt,
200 pDirectoryFCB,
201 cacheSegment);
202 if (!NT_SUCCESS (status))
203 {
204 return status;
205 }
206 status = vfatRequestAndValidateRegion (pDeviceExt,
207 pDirectoryFCB,
208 pageNumber * CACHEPAGESIZE(pDeviceExt),
209 (PVOID *) &currentPage,
210 &cacheSegment,
211 FALSE);
212 if (!NT_SUCCESS (status))
213 {
214 return status;
215 }
216 }
217 }
218 else
219 {
220 memcpy (pDirEntry, &fatDirEntry [indexInPage], sizeof (FAT_DIR_ENTRY));
221 (*pDirectoryIndex)++;
222 break;
223 }
224 }
225
226 DPRINT ("Releasing current directory page\n");
227 status = vfatReleaseRegion (pDeviceExt,
228 pDirectoryFCB,
229 cacheSegment);
230
231 return status;
232 }
233
234
235
236
237