4 * COPYRIGHT: See COPYING in the top level directory
5 * PROJECT: ReactOS kernel
6 * FILE: services/fs/vfat/dir.c
7 * PURPOSE: VFAT Filesystem : directory control
13 #include <ddk/ntddk.h>
22 // function like DosDateTimeToFileTime
23 BOOL FsdDosDateTimeToFileTime (WORD wDosDate, WORD wDosTime, TIME * FileTime)
25 PDOSTIME pdtime = (PDOSTIME) & wDosTime;
26 PDOSDATE pddate = (PDOSDATE) & wDosDate;
27 TIME_FIELDS TimeFields;
32 TimeFields.Milliseconds = 0;
33 TimeFields.Second = pdtime->Second * 2;
34 TimeFields.Minute = pdtime->Minute;
35 TimeFields.Hour = pdtime->Hour;
37 TimeFields.Day = pddate->Day;
38 TimeFields.Month = pddate->Month;
39 TimeFields.Year = 1980 + pddate->Year;
41 RtlTimeFieldsToTime (&TimeFields, (PLARGE_INTEGER) FileTime);
47 // function like FileTimeToDosDateTime
49 FsdFileTimeToDosDateTime (TIME * FileTime, WORD * pwDosDate, WORD * pwDosTime)
51 PDOSTIME pdtime = (PDOSTIME) pwDosTime;
52 PDOSDATE pddate = (PDOSDATE) pwDosDate;
53 TIME_FIELDS TimeFields;
58 RtlTimeToTimeFields ((PLARGE_INTEGER) FileTime, &TimeFields);
62 pdtime->Second = TimeFields.Second / 2;
63 pdtime->Minute = TimeFields.Minute;
64 pdtime->Hour = TimeFields.Hour;
69 pddate->Day = TimeFields.Day;
70 pddate->Month = TimeFields.Month;
71 pddate->Year = TimeFields.Year - 1980;
78 #define DWORD_ROUND_UP(x) ROUND_UP((x), (sizeof(DWORD)))
81 VfatGetFileNameInformation (PVFATFCB pFcb,
82 PFILE_NAMES_INFORMATION pInfo, ULONG BufferLength)
85 Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
86 if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
87 return STATUS_BUFFER_OVERFLOW;
88 pInfo->FileNameLength = Length;
89 pInfo->NextEntryOffset =
90 DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length);
91 memcpy (pInfo->FileName, pFcb->ObjectName, Length);
92 return STATUS_SUCCESS;
96 VfatGetFileDirectoryInformation (PVFATFCB pFcb,
97 PDEVICE_EXTENSION DeviceExt,
98 PFILE_DIRECTORY_INFORMATION pInfo,
102 Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
103 if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
104 return STATUS_BUFFER_OVERFLOW;
105 pInfo->FileNameLength = Length;
106 pInfo->NextEntryOffset =
107 DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length);
108 memcpy (pInfo->FileName, pFcb->ObjectName, Length);
109 // pInfo->FileIndex=;
110 FsdDosDateTimeToFileTime (pFcb->entry.CreationDate,
111 pFcb->entry.CreationTime, &pInfo->CreationTime);
112 FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0,
113 &pInfo->LastAccessTime);
114 FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
115 &pInfo->LastWriteTime);
116 pInfo->ChangeTime = pInfo->LastWriteTime;
117 pInfo->EndOfFile.u.HighPart = 0;
118 pInfo->EndOfFile.u.LowPart = pFcb->entry.FileSize;
119 /* Make allocsize a rounded up multiple of BytesPerCluster */
120 pInfo->AllocationSize.u.HighPart = 0;
121 pInfo->AllocationSize.u.LowPart = ROUND_UP(pFcb->entry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
122 pInfo->FileAttributes = pFcb->entry.Attrib;
124 return STATUS_SUCCESS;
128 VfatGetFileFullDirectoryInformation (PVFATFCB pFcb,
129 PDEVICE_EXTENSION DeviceExt,
130 PFILE_FULL_DIRECTORY_INFORMATION pInfo,
134 Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
135 if ((sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length) > BufferLength)
136 return STATUS_BUFFER_OVERFLOW;
137 pInfo->FileNameLength = Length;
138 pInfo->NextEntryOffset =
139 DWORD_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length);
140 memcpy (pInfo->FileName, pFcb->ObjectName, Length);
141 // pInfo->FileIndex=;
142 FsdDosDateTimeToFileTime (pFcb->entry.CreationDate,
143 pFcb->entry.CreationTime, &pInfo->CreationTime);
144 FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0,
145 &pInfo->LastAccessTime);
146 FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
147 &pInfo->LastWriteTime);
148 pInfo->ChangeTime = pInfo->LastWriteTime;
149 pInfo->EndOfFile.u.HighPart = 0;
150 pInfo->EndOfFile.u.LowPart = pFcb->entry.FileSize;
151 /* Make allocsize a rounded up multiple of BytesPerCluster */
152 pInfo->AllocationSize.u.HighPart = 0;
153 pInfo->AllocationSize.u.LowPart = ROUND_UP(pFcb->entry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
154 pInfo->FileAttributes = pFcb->entry.Attrib;
156 return STATUS_SUCCESS;
160 VfatGetFileBothInformation (PVFATFCB pFcb,
161 PDEVICE_EXTENSION DeviceExt,
162 PFILE_BOTH_DIRECTORY_INFORMATION pInfo,
166 Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
167 if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength)
168 return STATUS_BUFFER_OVERFLOW;
169 pInfo->FileNameLength = Length;
170 pInfo->NextEntryOffset =
171 DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length);
173 * vfatGetDirEntryName must be called befor the long name is copyed.
174 * The terminating null will overwrite the first character from long name.
176 vfatGetDirEntryName(&pFcb->entry, pInfo->ShortName);
177 pInfo->ShortNameLength = wcslen(pInfo->ShortName) * sizeof(WCHAR);
178 memcpy (pInfo->FileName, pFcb->ObjectName, Length);
179 // pInfo->FileIndex=;
180 FsdDosDateTimeToFileTime (pFcb->entry.CreationDate,
181 pFcb->entry.CreationTime, &pInfo->CreationTime);
182 FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0,
183 &pInfo->LastAccessTime);
184 FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
185 &pInfo->LastWriteTime);
186 pInfo->ChangeTime = pInfo->LastWriteTime;
187 pInfo->EndOfFile.u.HighPart = 0;
188 pInfo->EndOfFile.u.LowPart = pFcb->entry.FileSize;
189 /* Make allocsize a rounded up multiple of BytesPerCluster */
190 pInfo->AllocationSize.u.HighPart = 0;
191 pInfo->AllocationSize.u.LowPart = ROUND_UP(pFcb->entry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
192 pInfo->FileAttributes = pFcb->entry.Attrib;
194 return STATUS_SUCCESS;
197 NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext)
199 NTSTATUS RC = STATUS_SUCCESS;
200 long BufferLength = 0;
201 PUNICODE_STRING pSearchPattern = NULL;
202 FILE_INFORMATION_CLASS FileInformationClass;
203 unsigned long FileIndex = 0;
204 unsigned char *Buffer = NULL;
205 PFILE_NAMES_INFORMATION Buffer0 = NULL;
209 BOOLEAN First = FALSE;
211 PEXTENDED_IO_STACK_LOCATION Stack = (PEXTENDED_IO_STACK_LOCATION) IrpContext->Stack;
213 pCcb = (PVFATCCB) IrpContext->FileObject->FsContext2;
214 pFcb = (PVFATFCB) IrpContext->FileObject->FsContext;
216 if (!ExAcquireResourceSharedLite(&pFcb->MainResource,
217 (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
219 return STATUS_PENDING;
222 // Obtain the callers parameters
223 BufferLength = Stack->Parameters.QueryDirectory.Length;
224 pSearchPattern = Stack->Parameters.QueryDirectory.FileName;
225 FileInformationClass =
226 Stack->Parameters.QueryDirectory.FileInformationClass;
227 FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
230 if (!pCcb->DirectorySearchPattern)
233 pCcb->DirectorySearchPattern =
234 ExAllocatePool(NonPagedPool, pSearchPattern->Length + sizeof(WCHAR));
235 if (!pCcb->DirectorySearchPattern)
237 ExReleaseResourceLite(&pFcb->MainResource);
238 return STATUS_INSUFFICIENT_RESOURCES;
240 memcpy(pCcb->DirectorySearchPattern, pSearchPattern->Buffer,
241 pSearchPattern->Length);
242 pCcb->DirectorySearchPattern[pSearchPattern->Length / sizeof(WCHAR)] = 0;
245 else if (!pCcb->DirectorySearchPattern)
248 pCcb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
249 if (!pCcb->DirectorySearchPattern)
251 ExReleaseResourceLite(&pFcb->MainResource);
252 return STATUS_INSUFFICIENT_RESOURCES;
254 pCcb->DirectorySearchPattern[0] = L'*';
255 pCcb->DirectorySearchPattern[1] = 0;
258 if (IrpContext->Stack->Flags & SL_INDEX_SPECIFIED)
260 pCcb->Entry = pCcb->CurrentByteOffset.u.LowPart;
262 else if (First || (IrpContext->Stack->Flags & SL_RESTART_SCAN))
266 // determine Buffer for result :
267 if (IrpContext->Irp->MdlAddress)
269 Buffer = MmGetSystemAddressForMdl (IrpContext->Irp->MdlAddress);
273 Buffer = IrpContext->Irp->UserBuffer;
275 DPRINT ("Buffer=%x tofind=%S\n", Buffer, pCcb->DirectorySearchPattern);
277 tmpFcb.ObjectName = tmpFcb.PathName;
278 while (RC == STATUS_SUCCESS && BufferLength > 0)
280 RC = FindFile (IrpContext->DeviceExt, &tmpFcb, pFcb,
281 pCcb->DirectorySearchPattern, &pCcb->Entry, NULL);
282 DPRINT ("Found %S, RC=%x, entry %x\n", tmpFcb.ObjectName, RC, pCcb->Entry);
285 switch (FileInformationClass)
287 case FileNameInformation:
288 RC = VfatGetFileNameInformation (&tmpFcb,
289 (PFILE_NAMES_INFORMATION) Buffer, BufferLength);
291 case FileDirectoryInformation:
292 RC = VfatGetFileDirectoryInformation (&tmpFcb, IrpContext->DeviceExt,
293 (PFILE_DIRECTORY_INFORMATION) Buffer, BufferLength);
295 case FileFullDirectoryInformation:
296 RC = VfatGetFileFullDirectoryInformation (&tmpFcb, IrpContext->DeviceExt,
297 (PFILE_FULL_DIRECTORY_INFORMATION) Buffer, BufferLength);
299 case FileBothDirectoryInformation:
300 RC = VfatGetFileBothInformation (&tmpFcb, IrpContext->DeviceExt,
301 (PFILE_BOTH_DIRECTORY_INFORMATION) Buffer, BufferLength);
304 RC = STATUS_INVALID_INFO_CLASS;
306 if (RC == STATUS_BUFFER_OVERFLOW)
310 Buffer0->NextEntryOffset = 0;
319 Buffer0->NextEntryOffset = 0;
323 RC = STATUS_NO_SUCH_FILE;
327 RC = STATUS_NO_MORE_FILES;
331 Buffer0 = (PFILE_NAMES_INFORMATION) Buffer;
332 Buffer0->FileIndex = FileIndex++;
334 if (IrpContext->Stack->Flags & SL_RETURN_SINGLE_ENTRY)
338 BufferLength -= Buffer0->NextEntryOffset;
339 Buffer += Buffer0->NextEntryOffset;
343 Buffer0->NextEntryOffset = 0;
349 ExReleaseResourceLite(&pFcb->MainResource);
354 NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT IrpContext)
356 * FUNCTION: directory control : read/write directory informations
359 NTSTATUS RC = STATUS_SUCCESS;
361 switch (IrpContext->MinorFunction)
363 case IRP_MN_QUERY_DIRECTORY:
364 RC = DoQuery (IrpContext);
366 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
367 DPRINT (" vfat, dir : change\n");
368 RC = STATUS_NOT_IMPLEMENTED;
372 DbgPrint ("unexpected minor function %x in VFAT driver\n",
373 IrpContext->MinorFunction);
374 RC = STATUS_INVALID_DEVICE_REQUEST;
377 if (RC == STATUS_PENDING)
379 RC = VfatQueueRequest(IrpContext);
383 IrpContext->Irp->IoStatus.Status = RC;
384 IrpContext->Irp->IoStatus.Information = 0;
385 IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
386 VfatFreeIrpContext(IrpContext);