Doxygen

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