Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendirctl.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS kernel 00003 * Copyright (C) 2002, 2004 ReactOS Team 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along 00016 * with this program; if not, write to the Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 /* $Id: dirctl.c 54072 2011-10-10 13:37:19Z khornicek $ 00020 * 00021 * COPYRIGHT: See COPYING in the top level directory 00022 * PROJECT: ReactOS kernel 00023 * FILE: services/fs/cdfs/dirctl.c 00024 * PURPOSE: CDROM (ISO 9660) filesystem driver 00025 * PROGRAMMER: Art Yerkes 00026 * Eric Kohl 00027 * UPDATE HISTORY: 00028 */ 00029 00030 /* INCLUDES *****************************************************************/ 00031 00032 #include "cdfs.h" 00033 00034 #define NDEBUG 00035 #include <debug.h> 00036 00037 /* FUNCTIONS ****************************************************************/ 00038 00039 #define ROUND_DOWN(N, S) (((N) / (S)) * (S)) 00040 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) 00041 00042 /* FUNCTIONS ****************************************************************/ 00043 00044 /* 00045 * FUNCTION: Retrieves the file name, be it in short or long file name format 00046 */ 00047 static NTSTATUS 00048 CdfsGetEntryName(PDEVICE_EXTENSION DeviceExt, 00049 PVOID *Context, 00050 PVOID *Block, 00051 PLARGE_INTEGER StreamOffset, 00052 ULONG DirLength, 00053 PVOID *Ptr, 00054 PWSTR Name, 00055 PULONG pIndex, 00056 PULONG CurrentOffset) 00057 { 00058 PDIR_RECORD Record = *Ptr; 00059 ULONG Index; 00060 00061 if (*CurrentOffset >= DirLength) 00062 return(STATUS_NO_MORE_ENTRIES); 00063 00064 if (*CurrentOffset == 0) 00065 { 00066 Index = 0; 00067 Record = (PDIR_RECORD)*Block; 00068 while (Index < *pIndex) 00069 { 00070 (*Ptr) = (PVOID)((ULONG_PTR)(*Ptr) + Record->RecordLength); 00071 (*CurrentOffset) += Record->RecordLength; 00072 Record = *Ptr; 00073 if ((ULONG_PTR)(*Ptr) - (ULONG_PTR)(*Block) >= BLOCKSIZE || Record->RecordLength == 0) 00074 { 00075 DPRINT("Map next sector\n"); 00076 CcUnpinData(*Context); 00077 StreamOffset->QuadPart += BLOCKSIZE; 00078 *CurrentOffset = ROUND_UP(*CurrentOffset, BLOCKSIZE); 00079 if (!CcMapData(DeviceExt->StreamFileObject, 00080 StreamOffset, 00081 BLOCKSIZE, TRUE, 00082 Context, Block)) 00083 { 00084 DPRINT("CcMapData() failed\n"); 00085 return(STATUS_UNSUCCESSFUL); 00086 } 00087 *Ptr = *Block; 00088 Record = (PDIR_RECORD)*Ptr; 00089 } 00090 if (*CurrentOffset >= DirLength) 00091 return(STATUS_NO_MORE_ENTRIES); 00092 00093 Index++; 00094 } 00095 } 00096 00097 if ((ULONG_PTR)(*Ptr) - (ULONG_PTR)(*Block) >= BLOCKSIZE || Record->RecordLength == 0) 00098 { 00099 DPRINT("Map next sector\n"); 00100 CcUnpinData(*Context); 00101 StreamOffset->QuadPart += BLOCKSIZE; 00102 *CurrentOffset = ROUND_UP(*CurrentOffset, BLOCKSIZE); 00103 if (!CcMapData(DeviceExt->StreamFileObject, 00104 StreamOffset, 00105 BLOCKSIZE, TRUE, 00106 Context, Block)) 00107 { 00108 DPRINT("CcMapData() failed\n"); 00109 return(STATUS_UNSUCCESSFUL); 00110 } 00111 *Ptr = *Block; 00112 Record = (PDIR_RECORD)*Ptr; 00113 } 00114 00115 if (*CurrentOffset >= DirLength) 00116 return STATUS_NO_MORE_ENTRIES; 00117 00118 DPRINT("Index %lu RecordLength %lu Offset %lu\n", 00119 *pIndex, Record->RecordLength, *CurrentOffset); 00120 00121 if (Record->FileIdLength == 1 && Record->FileId[0] == 0) 00122 { 00123 wcscpy(Name, L"."); 00124 } 00125 else if (Record->FileIdLength == 1 && Record->FileId[0] == 1) 00126 { 00127 wcscpy(Name, L".."); 00128 } 00129 else 00130 { 00131 if (DeviceExt->CdInfo.JolietLevel == 0) 00132 { 00133 ULONG i; 00134 00135 for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++) 00136 Name[i] = (WCHAR)Record->FileId[i]; 00137 Name[i] = 0; 00138 } 00139 else 00140 { 00141 CdfsSwapString(Name, Record->FileId, Record->FileIdLength); 00142 } 00143 } 00144 00145 DPRINT("Name '%S'\n", Name); 00146 00147 *Ptr = Record; 00148 00149 return(STATUS_SUCCESS); 00150 } 00151 00152 00153 /* 00154 * FUNCTION: Find a file 00155 */ 00156 static NTSTATUS 00157 CdfsFindFile(PDEVICE_EXTENSION DeviceExt, 00158 PFCB Fcb, 00159 PFCB Parent, 00160 PUNICODE_STRING FileToFind, 00161 PULONG pDirIndex, 00162 PULONG pOffset) 00163 { 00164 WCHAR name[256]; 00165 WCHAR ShortNameBuffer[13]; 00166 UNICODE_STRING TempString; 00167 UNICODE_STRING ShortName; 00168 UNICODE_STRING LongName; 00169 UNICODE_STRING FileToFindUpcase; 00170 PVOID Block; 00171 NTSTATUS Status; 00172 ULONG len; 00173 ULONG DirIndex; 00174 ULONG Offset = 0; 00175 BOOLEAN IsRoot; 00176 PVOID Context = NULL; 00177 ULONG DirSize; 00178 PDIR_RECORD Record; 00179 LARGE_INTEGER StreamOffset, OffsetOfEntry; 00180 00181 DPRINT("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n", 00182 Parent, FileToFind, pDirIndex ? *pDirIndex : 0); 00183 DPRINT("FindFile: old Pathname %x, old Objectname %x)\n", 00184 Fcb->PathName, Fcb->ObjectName); 00185 00186 IsRoot = FALSE; 00187 DirIndex = 0; 00188 00189 if (FileToFind == NULL || FileToFind->Length == 0) 00190 { 00191 RtlInitUnicodeString(&TempString, L"."); 00192 FileToFind = &TempString; 00193 } 00194 00195 if (Parent) 00196 { 00197 if (Parent->Entry.ExtentLocationL == DeviceExt->CdInfo.RootStart) 00198 { 00199 IsRoot = TRUE; 00200 } 00201 } 00202 else 00203 { 00204 IsRoot = TRUE; 00205 } 00206 00207 if (IsRoot == TRUE) 00208 { 00209 StreamOffset.QuadPart = (LONGLONG)DeviceExt->CdInfo.RootStart * (LONGLONG)BLOCKSIZE; 00210 DirSize = DeviceExt->CdInfo.RootSize; 00211 00212 00213 if (FileToFind->Buffer[0] == 0 || 00214 (FileToFind->Buffer[0] == '\\' && FileToFind->Buffer[1] == 0) || 00215 (FileToFind->Buffer[0] == '.' && FileToFind->Buffer[1] == 0)) 00216 { 00217 /* it's root : complete essentials fields then return ok */ 00218 RtlZeroMemory(Fcb, sizeof(FCB)); 00219 00220 Fcb->PathName[0] = '\\'; 00221 Fcb->ObjectName = &Fcb->PathName[1]; 00222 Fcb->Entry.ExtentLocationL = DeviceExt->CdInfo.RootStart; 00223 Fcb->Entry.DataLengthL = DeviceExt->CdInfo.RootSize; 00224 Fcb->Entry.FileFlags = 0x02; //FILE_ATTRIBUTE_DIRECTORY; 00225 00226 if (pDirIndex) 00227 *pDirIndex = 0; 00228 if (pOffset) 00229 *pOffset = 0; 00230 DPRINT("CdfsFindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName); 00231 return STATUS_SUCCESS; 00232 } 00233 } 00234 else 00235 { 00236 StreamOffset.QuadPart = (LONGLONG)Parent->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE; 00237 DirSize = Parent->Entry.DataLengthL; 00238 } 00239 00240 DPRINT("StreamOffset %I64u DirSize %lu\n", StreamOffset.QuadPart, DirSize); 00241 00242 if (pDirIndex && (*pDirIndex)) 00243 DirIndex = *pDirIndex; 00244 00245 if (pOffset && (*pOffset)) 00246 { 00247 Offset = *pOffset; 00248 StreamOffset.QuadPart += ROUND_DOWN(Offset, BLOCKSIZE); 00249 } 00250 00251 if (!CcMapData(DeviceExt->StreamFileObject, &StreamOffset, 00252 BLOCKSIZE, TRUE, &Context, &Block)) 00253 { 00254 DPRINT("CcMapData() failed\n"); 00255 return STATUS_UNSUCCESSFUL; 00256 } 00257 00258 Record = (PDIR_RECORD) ((ULONG_PTR)Block + Offset % BLOCKSIZE); 00259 if (Offset) 00260 { 00261 Offset += Record->RecordLength; 00262 Record = (PDIR_RECORD)((ULONG_PTR)Record + Record->RecordLength); 00263 } 00264 00265 /* Upper case the expression for FsRtlIsNameInExpression */ 00266 Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFind, TRUE); 00267 if (!NT_SUCCESS(Status)) 00268 { 00269 return Status; 00270 } 00271 00272 while(TRUE) 00273 { 00274 DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n", 00275 Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength); 00276 00277 Status = CdfsGetEntryName 00278 (DeviceExt, &Context, &Block, &StreamOffset, 00279 DirSize, (PVOID*)&Record, name, &DirIndex, &Offset); 00280 00281 if (Status == STATUS_NO_MORE_ENTRIES) 00282 { 00283 break; 00284 } 00285 else if (Status == STATUS_UNSUCCESSFUL) 00286 { 00287 /* Note: the directory cache has already been unpinned */ 00288 RtlFreeUnicodeString(&FileToFindUpcase); 00289 return Status; 00290 } 00291 00292 DPRINT("Name '%S'\n", name); 00293 00294 RtlInitUnicodeString(&LongName, name); 00295 ShortName.Length = 0; 00296 ShortName.MaximumLength = 26; 00297 ShortName.Buffer = ShortNameBuffer; 00298 00299 OffsetOfEntry.QuadPart = StreamOffset.QuadPart + Offset; 00300 CdfsShortNameCacheGet(Parent, &OffsetOfEntry, &LongName, &ShortName); 00301 00302 DPRINT("ShortName '%wZ'\n", &ShortName); 00303 00304 if (FsRtlIsNameInExpression(&FileToFindUpcase, &LongName, TRUE, NULL) || 00305 FsRtlIsNameInExpression(&FileToFindUpcase, &ShortName, TRUE, NULL)) 00306 { 00307 if (Parent && Parent->PathName) 00308 { 00309 len = wcslen(Parent->PathName); 00310 memcpy(Fcb->PathName, Parent->PathName, len*sizeof(WCHAR)); 00311 Fcb->ObjectName=&Fcb->PathName[len]; 00312 if (len != 1 || Fcb->PathName[0] != '\\') 00313 { 00314 Fcb->ObjectName[0] = '\\'; 00315 Fcb->ObjectName = &Fcb->ObjectName[1]; 00316 } 00317 } 00318 else 00319 { 00320 Fcb->ObjectName=Fcb->PathName; 00321 Fcb->ObjectName[0]='\\'; 00322 Fcb->ObjectName=&Fcb->ObjectName[1]; 00323 } 00324 00325 DPRINT("PathName '%S' ObjectName '%S'\n", Fcb->PathName, Fcb->ObjectName); 00326 00327 memcpy(&Fcb->Entry, Record, sizeof(DIR_RECORD)); 00328 wcsncpy(Fcb->ObjectName, name, min(wcslen(name) + 1, 00329 MAX_PATH - wcslen(Fcb->PathName) + wcslen(Fcb->ObjectName))); 00330 00331 /* Copy short name */ 00332 Fcb->ShortNameU.Length = ShortName.Length; 00333 Fcb->ShortNameU.MaximumLength = ShortName.Length; 00334 Fcb->ShortNameU.Buffer = Fcb->ShortNameBuffer; 00335 memcpy(Fcb->ShortNameBuffer, ShortName.Buffer, ShortName.Length); 00336 00337 if (pDirIndex) 00338 *pDirIndex = DirIndex; 00339 if (pOffset) 00340 *pOffset = Offset; 00341 00342 DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n", 00343 Fcb->PathName, Fcb->ObjectName, DirIndex); 00344 00345 RtlFreeUnicodeString(&FileToFindUpcase); 00346 CcUnpinData(Context); 00347 00348 return STATUS_SUCCESS; 00349 } 00350 00351 Offset += Record->RecordLength; 00352 Record = (PDIR_RECORD)((ULONG_PTR)Record + Record->RecordLength); 00353 DirIndex++; 00354 } 00355 00356 RtlFreeUnicodeString(&FileToFindUpcase); 00357 CcUnpinData(Context); 00358 00359 if (pDirIndex) 00360 *pDirIndex = DirIndex; 00361 00362 if (pOffset) 00363 *pOffset = Offset; 00364 00365 return STATUS_UNSUCCESSFUL; 00366 } 00367 00368 00369 static NTSTATUS 00370 CdfsGetNameInformation(PFCB Fcb, 00371 PDEVICE_EXTENSION DeviceExt, 00372 PFILE_NAMES_INFORMATION Info, 00373 ULONG BufferLength) 00374 { 00375 ULONG Length; 00376 00377 DPRINT("CdfsGetNameInformation() called\n"); 00378 00379 Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); 00380 if ((sizeof(FILE_NAMES_INFORMATION) + Length) > BufferLength) 00381 return(STATUS_BUFFER_OVERFLOW); 00382 00383 Info->FileNameLength = Length; 00384 Info->NextEntryOffset = 00385 ROUND_UP(sizeof(FILE_NAMES_INFORMATION) + Length, sizeof(ULONG)); 00386 RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length); 00387 00388 // Info->FileIndex=; 00389 00390 return(STATUS_SUCCESS); 00391 } 00392 00393 00394 static NTSTATUS 00395 CdfsGetDirectoryInformation(PFCB Fcb, 00396 PDEVICE_EXTENSION DeviceExt, 00397 PFILE_DIRECTORY_INFORMATION Info, 00398 ULONG BufferLength) 00399 { 00400 ULONG Length; 00401 00402 DPRINT("CdfsGetDirectoryInformation() called\n"); 00403 00404 Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); 00405 if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength) 00406 return(STATUS_BUFFER_OVERFLOW); 00407 00408 Info->FileNameLength = Length; 00409 Info->NextEntryOffset = 00410 ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION) + Length, sizeof(ULONG)); 00411 RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length); 00412 00413 /* Convert file times */ 00414 CdfsDateTimeToSystemTime(Fcb, 00415 &Info->CreationTime); 00416 Info->LastWriteTime = Info->CreationTime; 00417 Info->ChangeTime = Info->CreationTime; 00418 00419 /* Convert file flags */ 00420 CdfsFileFlagsToAttributes(Fcb, 00421 &Info->FileAttributes); 00422 if (CdfsFCBIsDirectory(Fcb)) 00423 { 00424 Info->EndOfFile.QuadPart = 0; 00425 Info->AllocationSize.QuadPart = 0; 00426 } 00427 else 00428 { 00429 Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL; 00430 00431 /* Make AllocSize a rounded up multiple of the sector size */ 00432 Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE); 00433 } 00434 00435 // Info->FileIndex=; 00436 00437 return(STATUS_SUCCESS); 00438 } 00439 00440 00441 static NTSTATUS 00442 CdfsGetFullDirectoryInformation(PFCB Fcb, 00443 PDEVICE_EXTENSION DeviceExt, 00444 PFILE_FULL_DIR_INFORMATION Info, 00445 ULONG BufferLength) 00446 { 00447 ULONG Length; 00448 00449 DPRINT("CdfsGetFullDirectoryInformation() called\n"); 00450 00451 Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); 00452 if ((sizeof (FILE_FULL_DIR_INFORMATION) + Length) > BufferLength) 00453 return(STATUS_BUFFER_OVERFLOW); 00454 00455 Info->FileNameLength = Length; 00456 Info->NextEntryOffset = 00457 ROUND_UP(sizeof(FILE_FULL_DIR_INFORMATION) + Length, sizeof(ULONG)); 00458 RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length); 00459 00460 /* Convert file times */ 00461 CdfsDateTimeToSystemTime(Fcb, 00462 &Info->CreationTime); 00463 Info->LastWriteTime = Info->CreationTime; 00464 Info->ChangeTime = Info->CreationTime; 00465 00466 /* Convert file flags */ 00467 CdfsFileFlagsToAttributes(Fcb, 00468 &Info->FileAttributes); 00469 00470 if (CdfsFCBIsDirectory(Fcb)) 00471 { 00472 Info->EndOfFile.QuadPart = 0; 00473 Info->AllocationSize.QuadPart = 0; 00474 } 00475 else 00476 { 00477 Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL; 00478 00479 /* Make AllocSize a rounded up multiple of the sector size */ 00480 Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE); 00481 } 00482 00483 // Info->FileIndex=; 00484 Info->EaSize = 0; 00485 00486 return(STATUS_SUCCESS); 00487 } 00488 00489 00490 static NTSTATUS 00491 CdfsGetBothDirectoryInformation(PFCB Fcb, 00492 PDEVICE_EXTENSION DeviceExt, 00493 PFILE_BOTH_DIR_INFORMATION Info, 00494 ULONG BufferLength) 00495 { 00496 ULONG Length; 00497 00498 DPRINT("CdfsGetBothDirectoryInformation() called\n"); 00499 00500 Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); 00501 if ((sizeof (FILE_BOTH_DIR_INFORMATION) + Length) > BufferLength) 00502 return(STATUS_BUFFER_OVERFLOW); 00503 00504 Info->FileNameLength = Length; 00505 Info->NextEntryOffset = 00506 ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) + Length, sizeof(ULONG)); 00507 RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length); 00508 00509 /* Convert file times */ 00510 CdfsDateTimeToSystemTime(Fcb, 00511 &Info->CreationTime); 00512 Info->LastWriteTime = Info->CreationTime; 00513 Info->ChangeTime = Info->CreationTime; 00514 00515 /* Convert file flags */ 00516 CdfsFileFlagsToAttributes(Fcb, 00517 &Info->FileAttributes); 00518 00519 if (CdfsFCBIsDirectory(Fcb)) 00520 { 00521 Info->EndOfFile.QuadPart = 0; 00522 Info->AllocationSize.QuadPart = 0; 00523 } 00524 else 00525 { 00526 Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL; 00527 00528 /* Make AllocSize a rounded up multiple of the sector size */ 00529 Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE); 00530 } 00531 00532 // Info->FileIndex=; 00533 Info->EaSize = 0; 00534 00535 /* Copy short name */ 00536 ASSERT(Fcb->ShortNameU.Length / sizeof(WCHAR) <= 12); 00537 Info->ShortNameLength = (CCHAR)Fcb->ShortNameU.Length; 00538 RtlCopyMemory(Info->ShortName, Fcb->ShortNameU.Buffer, Fcb->ShortNameU.Length); 00539 00540 return(STATUS_SUCCESS); 00541 } 00542 00543 00544 static NTSTATUS 00545 CdfsQueryDirectory(PDEVICE_OBJECT DeviceObject, 00546 PIRP Irp) 00547 { 00548 PDEVICE_EXTENSION DeviceExtension; 00549 LONG BufferLength = 0; 00550 PUNICODE_STRING SearchPattern = NULL; 00551 FILE_INFORMATION_CLASS FileInformationClass; 00552 ULONG FileIndex = 0; 00553 PUCHAR Buffer = NULL; 00554 PFILE_NAMES_INFORMATION Buffer0 = NULL; 00555 PFCB Fcb; 00556 PCCB Ccb; 00557 FCB TempFcb; 00558 BOOLEAN First = FALSE; 00559 PIO_STACK_LOCATION Stack; 00560 PFILE_OBJECT FileObject; 00561 NTSTATUS Status = STATUS_SUCCESS; 00562 00563 DPRINT("CdfsQueryDirectory() called\n"); 00564 00565 DeviceExtension = DeviceObject->DeviceExtension; 00566 Stack = IoGetCurrentIrpStackLocation(Irp); 00567 FileObject = Stack->FileObject; 00568 00569 Ccb = (PCCB)FileObject->FsContext2; 00570 Fcb = (PFCB)FileObject->FsContext; 00571 00572 /* Obtain the callers parameters */ 00573 BufferLength = Stack->Parameters.QueryDirectory.Length; 00574 SearchPattern = Stack->Parameters.QueryDirectory.FileName; 00575 FileInformationClass = 00576 Stack->Parameters.QueryDirectory.FileInformationClass; 00577 FileIndex = Stack->Parameters.QueryDirectory.FileIndex; 00578 00579 /* Determine Buffer for result */ 00580 if (Irp->MdlAddress) 00581 { 00582 Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); 00583 } 00584 else 00585 { 00586 Buffer = Irp->UserBuffer; 00587 } 00588 00589 if (SearchPattern != NULL) 00590 { 00591 if (Ccb->DirectorySearchPattern.Buffer == NULL) 00592 { 00593 First = TRUE; 00594 Ccb->DirectorySearchPattern.Buffer = 00595 ExAllocatePoolWithTag(NonPagedPool, SearchPattern->Length + sizeof(WCHAR), TAG_CCB); 00596 if (Ccb->DirectorySearchPattern.Buffer == NULL) 00597 { 00598 return STATUS_INSUFFICIENT_RESOURCES; 00599 } 00600 Ccb->DirectorySearchPattern.MaximumLength = SearchPattern->Length + sizeof(WCHAR); 00601 RtlCopyUnicodeString(&Ccb->DirectorySearchPattern, SearchPattern); 00602 Ccb->DirectorySearchPattern.Buffer[SearchPattern->Length / sizeof(WCHAR)] = 0; 00603 } 00604 } 00605 else if (Ccb->DirectorySearchPattern.Buffer == NULL) 00606 { 00607 First = TRUE; 00608 Ccb->DirectorySearchPattern.Buffer = ExAllocatePoolWithTag(NonPagedPool, 2 * sizeof(WCHAR), TAG_CCB); 00609 if (Ccb->DirectorySearchPattern.Buffer == NULL) 00610 { 00611 return STATUS_INSUFFICIENT_RESOURCES; 00612 } 00613 00614 Ccb->DirectorySearchPattern.Length = sizeof(WCHAR); 00615 Ccb->DirectorySearchPattern.MaximumLength = 2 * sizeof(WCHAR); 00616 Ccb->DirectorySearchPattern.Buffer[0] = L'*'; 00617 Ccb->DirectorySearchPattern.Buffer[1] = 0; 00618 } 00619 DPRINT("Search pattern '%wZ'\n", &Ccb->DirectorySearchPattern); 00620 00621 /* Determine directory index */ 00622 if (Stack->Flags & SL_INDEX_SPECIFIED) 00623 { 00624 Ccb->Entry = Stack->Parameters.QueryDirectory.FileIndex; 00625 Ccb->Offset = Ccb->CurrentByteOffset.u.LowPart; 00626 } 00627 else if (First || (Stack->Flags & SL_RESTART_SCAN)) 00628 { 00629 Ccb->Entry = 0; 00630 Ccb->Offset = 0; 00631 } 00632 DPRINT("Buffer = %p tofind = %wZ\n", Buffer, &Ccb->DirectorySearchPattern); 00633 00634 TempFcb.ObjectName = TempFcb.PathName; 00635 while (Status == STATUS_SUCCESS && BufferLength > 0) 00636 { 00637 Status = CdfsFindFile(DeviceExtension, 00638 &TempFcb, 00639 Fcb, 00640 &Ccb->DirectorySearchPattern, 00641 &Ccb->Entry, 00642 &Ccb->Offset); 00643 DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry); 00644 00645 if (NT_SUCCESS(Status)) 00646 { 00647 switch (FileInformationClass) 00648 { 00649 case FileNameInformation: 00650 Status = CdfsGetNameInformation(&TempFcb, 00651 DeviceExtension, 00652 (PFILE_NAMES_INFORMATION)Buffer, 00653 BufferLength); 00654 break; 00655 00656 case FileDirectoryInformation: 00657 Status = CdfsGetDirectoryInformation(&TempFcb, 00658 DeviceExtension, 00659 (PFILE_DIRECTORY_INFORMATION)Buffer, 00660 BufferLength); 00661 break; 00662 00663 case FileFullDirectoryInformation: 00664 Status = CdfsGetFullDirectoryInformation(&TempFcb, 00665 DeviceExtension, 00666 (PFILE_FULL_DIR_INFORMATION)Buffer, 00667 BufferLength); 00668 break; 00669 00670 case FileBothDirectoryInformation: 00671 Status = CdfsGetBothDirectoryInformation(&TempFcb, 00672 DeviceExtension, 00673 (PFILE_BOTH_DIR_INFORMATION)Buffer, 00674 BufferLength); 00675 break; 00676 00677 default: 00678 Status = STATUS_INVALID_INFO_CLASS; 00679 } 00680 00681 if (Status == STATUS_BUFFER_OVERFLOW) 00682 { 00683 if (Buffer0) 00684 { 00685 Buffer0->NextEntryOffset = 0; 00686 } 00687 break; 00688 } 00689 } 00690 else 00691 { 00692 if (Buffer0) 00693 { 00694 Buffer0->NextEntryOffset = 0; 00695 } 00696 00697 if (First) 00698 { 00699 Status = STATUS_NO_SUCH_FILE; 00700 } 00701 else 00702 { 00703 Status = STATUS_NO_MORE_FILES; 00704 } 00705 break; 00706 } 00707 00708 Buffer0 = (PFILE_NAMES_INFORMATION)Buffer; 00709 Buffer0->FileIndex = FileIndex++; 00710 Ccb->Entry++; 00711 00712 if (Stack->Flags & SL_RETURN_SINGLE_ENTRY) 00713 { 00714 break; 00715 } 00716 BufferLength -= Buffer0->NextEntryOffset; 00717 Buffer += Buffer0->NextEntryOffset; 00718 } 00719 00720 if (Buffer0) 00721 { 00722 Buffer0->NextEntryOffset = 0; 00723 } 00724 00725 if (FileIndex > 0) 00726 { 00727 Status = STATUS_SUCCESS; 00728 } 00729 00730 return(Status); 00731 } 00732 00733 00734 00735 NTSTATUS NTAPI 00736 CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject, 00737 PIRP Irp) 00738 { 00739 PIO_STACK_LOCATION Stack; 00740 NTSTATUS Status; 00741 00742 DPRINT("CdfsDirectoryControl() called\n"); 00743 FsRtlEnterFileSystem(); 00744 00745 Stack = IoGetCurrentIrpStackLocation(Irp); 00746 00747 switch (Stack->MinorFunction) 00748 { 00749 case IRP_MN_QUERY_DIRECTORY: 00750 Status = CdfsQueryDirectory(DeviceObject, 00751 Irp); 00752 break; 00753 00754 case IRP_MN_NOTIFY_CHANGE_DIRECTORY: 00755 DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n"); 00756 Status = STATUS_NOT_IMPLEMENTED; 00757 break; 00758 00759 default: 00760 DPRINT1("CDFS: MinorFunction %d\n", Stack->MinorFunction); 00761 Status = STATUS_INVALID_DEVICE_REQUEST; 00762 break; 00763 } 00764 00765 Irp->IoStatus.Status = Status; 00766 Irp->IoStatus.Information = 0; 00767 00768 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00769 FsRtlExitFileSystem(); 00770 00771 return(Status); 00772 } 00773 00774 /* EOF */ Generated on Mon May 28 2012 04:27:21 for ReactOS by
1.7.6.1
|