All:
[reactos.git] / reactos / drivers / fs / vfat / direntry.c
1 /* $Id: direntry.c,v 1.6 2002/03/18 22:37:12 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)->FatInfo.BytesPerCluster > PAGESIZE ? \
24 (pDeviceExt)->FatInfo.BytesPerCluster : PAGESIZE)
25
26 #define ENTRIES_PER_CACHEPAGE(pDeviceExt) (ENTRIES_PER_SECTOR * \
27 (CACHEPAGESIZE(pDeviceExt) / ((pDeviceExt)->FatInfo.BytesPerSector)))
28
29
30 ULONG
31 vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
32 PFAT_DIR_ENTRY pFatDirEntry)
33 {
34 ULONG cluster;
35
36 if (pDeviceExt->FatInfo.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 ULONG indexInPage = *pDirectoryIndex % ENTRIES_PER_CACHEPAGE(pDeviceExt);
87 ULONG pageNumber = *pDirectoryIndex / ENTRIES_PER_CACHEPAGE(pDeviceExt);
88 PVOID currentPage = NULL;
89 FATDirEntry * fatDirEntry;
90 slot * longNameEntry;
91 ULONG cpos;
92 LARGE_INTEGER FileOffset;
93 PVOID Context;
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 FileOffset.QuadPart = pageNumber * CACHEPAGESIZE(pDeviceExt);
105 if (!CcMapData(pDirectoryFCB->FileObject, &FileOffset,
106 CACHEPAGESIZE(pDeviceExt), TRUE, &Context, &currentPage))
107 {
108 return STATUS_UNSUCCESSFUL;
109 }
110
111 while (TRUE)
112 {
113 fatDirEntry = (FATDirEntry *) currentPage;
114
115 if (vfatIsDirEntryEndMarker (&fatDirEntry [indexInPage]))
116 {
117 DPRINT ("end of directory, returning no more entries\n");
118 CcUnpinData(Context);
119 return STATUS_NO_MORE_ENTRIES;
120 }
121 else if (vfatIsDirEntryLongName (&fatDirEntry [indexInPage])
122 && !vfatIsDirEntryDeleted (&fatDirEntry [indexInPage]))
123 {
124 DPRINT (" long name entry found at %d\n", *pDirectoryIndex);
125 longNameEntry = (slot *) currentPage;
126
127 DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
128 5, longNameEntry [indexInPage].name0_4,
129 6, longNameEntry [indexInPage].name5_10,
130 2, longNameEntry [indexInPage].name11_12);
131
132 vfat_initstr (pLongFileName, 256);
133 vfat_wcsncpy (pLongFileName, longNameEntry [indexInPage].name0_4, 5);
134 vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name5_10, 5, 6);
135 vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name11_12, 11, 2);
136
137 DPRINT (" longName: [%S]\n", pLongFileName);
138
139 cpos = 0;
140 while ((longNameEntry [indexInPage].id != 0x41) &&
141 (longNameEntry [indexInPage].id != 0x01) &&
142 (longNameEntry [indexInPage].attr > 0))
143 {
144 (*pDirectoryIndex)++;
145 indexInPage++;
146 if (indexInPage == ENTRIES_PER_CACHEPAGE(pDeviceExt))
147 {
148 indexInPage = 0;
149 pageNumber++;
150
151 CcUnpinData(Context);
152 FileOffset.QuadPart = pageNumber * CACHEPAGESIZE(pDeviceExt);
153 if (!CcMapData(pDirectoryFCB->FileObject, &FileOffset,
154 CACHEPAGESIZE(pDeviceExt), TRUE, &Context, &currentPage))
155 {
156 return STATUS_UNSUCCESSFUL;
157 }
158 longNameEntry = (slot *) currentPage;
159 }
160 DPRINT (" index %d\n", *pDirectoryIndex);
161
162 DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
163 5, longNameEntry [indexInPage].name0_4,
164 6, longNameEntry [indexInPage].name5_10,
165 2, longNameEntry [indexInPage].name11_12);
166
167 cpos++;
168 vfat_movstr (pLongFileName, 13, 0, cpos * 13);
169 vfat_wcsncpy (pLongFileName, longNameEntry [indexInPage].name0_4, 5);
170 vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name5_10, 5, 6);
171 vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name11_12, 11, 2);
172
173 DPRINT (" longName: [%S]\n", pLongFileName);
174
175 }
176 (*pDirectoryIndex)++;
177 indexInPage++;
178 if (indexInPage == ENTRIES_PER_CACHEPAGE(pDeviceExt))
179 {
180 indexInPage = 0;
181 pageNumber++;
182
183 CcUnpinData(Context);
184 FileOffset.QuadPart = pageNumber * CACHEPAGESIZE(pDeviceExt);
185 if (!CcMapData(pDirectoryFCB->FileObject, &FileOffset,
186 CACHEPAGESIZE(pDeviceExt), TRUE, &Context, &currentPage))
187 {
188 return STATUS_UNSUCCESSFUL;
189 }
190 }
191 }
192 else
193 {
194 memcpy (pDirEntry, &fatDirEntry [indexInPage], sizeof (FAT_DIR_ENTRY));
195 (*pDirectoryIndex)++;
196 break;
197 }
198 }
199 CcUnpinData(Context);
200 return STATUS_SUCCESS;
201 }
202
203
204
205
206