xbox-kernel/private/ntos/xapi/k32/filefind.c
2020-09-30 17:17:25 +02:00

304 lines
8.7 KiB
C

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
filefind.c
Abstract:
This module implements Win32 FindFirst/FindNext
Author:
Mark Lucovsky (markl) 26-Sep-1990
Revision History:
--*/
#include "basedll.h"
VOID
XapiDirectoryInformationToFindData(
IN PFILE_DIRECTORY_INFORMATION DirInfo,
OUT LPWIN32_FIND_DATA lpFindFileData
)
{
lpFindFileData->dwFileAttributes = DirInfo->FileAttributes;
lpFindFileData->ftCreationTime = *(LPFILETIME)&DirInfo->CreationTime;
lpFindFileData->ftLastAccessTime = *(LPFILETIME)&DirInfo->LastAccessTime;
lpFindFileData->ftLastWriteTime = *(LPFILETIME)&DirInfo->LastWriteTime;
lpFindFileData->nFileSizeHigh = DirInfo->EndOfFile.HighPart;
lpFindFileData->nFileSizeLow = DirInfo->EndOfFile.LowPart;
RtlCopyMemory(lpFindFileData->cFileName, DirInfo->FileName,
DirInfo->FileNameLength);
lpFindFileData->cFileName[DirInfo->FileNameLength / sizeof(OCHAR)] = OBJECT_NULL;
lpFindFileData->cAlternateFileName[0] = OBJECT_NULL;
}
HANDLE
APIENTRY
FindFirstFile(
PCOSTR lpFileName,
LPWIN32_FIND_DATA lpFindFileData
)
/*++
Routine Description:
A directory can be searched for the first entry whose name and
attributes match the specified name using FindFirstFile.
This API is provided to open a find file handle and return
information about the first file whose name match the specified
pattern. Once established, the find file handle can be used to
search for other files that match the same pattern. When the find
file handle is no longer needed, it should be closed.
Note that while this interface only returns information for a single
file, an implementation is free to buffer several matching files
that can be used to satisfy subsequent calls to FindNextFile. Also
not that matches are done by name only. This API does not do
attribute based matching.
This API is similar to DOS (int 21h, function 4Eh), and OS/2's
DosFindFirst. For portability reasons, its data structures and
parameter passing is somewhat different.
Arguments:
lpFileName - Supplies the file name of the file to find. The file name
may contain the DOS wild card characters '*' and '?'.
lpFindFileData - On a successful find, this parameter returns information
about the located file:
WIN32_FIND_DATA Structure:
DWORD dwFileAttributes - Returns the file attributes of the found
file.
FILETIME ftCreationTime - Returns the time that the file was created.
A value of 0,0 specifies that the file system containing the
file does not support this time field.
FILETIME ftLastAccessTime - Returns the time that the file was last
accessed. A value of 0,0 specifies that the file system
containing the file does not support this time field.
FILETIME ftLastWriteTime - Returns the time that the file was last
written. A file systems support this time field.
DWORD nFileSizeHigh - Returns the high order 32 bits of the
file's size.
DWORD nFileSizeLow - Returns the low order 32-bits of the file's
size in bytes.
UCHAR cFileName[MAX_PATH] - Returns the null terminated name of
the file.
Return Value:
Not -1 - Returns a find first handle
that can be used in a subsequent call to FindNextFile or FindClose.
0xffffffff - The operation failed. Extended error status is available
using GetLastError.
--*/
{
NTSTATUS Status;
OBJECT_ATTRIBUTES Obja;
HANDLE Handle;
ULONG EndingIndex;
OBJECT_STRING FileName;
OBJECT_STRING SearchName;
IO_STATUS_BLOCK IoStatusBlock;
struct {
FILE_DIRECTORY_INFORMATION DirInfo;
OCHAR FileName[256];
} FullDirInfo;
RtlInitObjectString(&FileName, lpFileName);
InitializeObjectAttributes(
&Obja,
&FileName,
OBJ_CASE_INSENSITIVE,
ObDosDevicesDirectory(),
NULL
);
//
// Strip off the search specification from the file name.
//
EndingIndex = (FileName.Length / sizeof(OCHAR));
while (EndingIndex > 0) {
if (FileName.Buffer[EndingIndex - 1] == OTEXT('\\')) {
break;
}
EndingIndex--;
}
SearchName.Length = (USHORT)(FileName.Length - (EndingIndex * sizeof(OCHAR)));
SearchName.MaximumLength = SearchName.Length;
SearchName.Buffer = &FileName.Buffer[EndingIndex];
FileName.Length = (USHORT)(EndingIndex * sizeof(OCHAR));
FileName.MaximumLength = FileName.Length;
//
// Make sure that we didn't consume the entire string while searching for
// the search specification and that the search specification is not empty.
//
if ((FileName.Length == 0) || (SearchName.Length == 0)) {
SetLastError(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
//
// If the search name is "*.*", then convert it to an empty string so that
// we end up matching all names, not just those with an extension.
//
if (SearchName.Length == sizeof(OCHAR) * 3 &&
SearchName.Buffer[0] == OTEXT('*') && SearchName.Buffer[1] == OTEXT('.') &&
SearchName.Buffer[2] == OTEXT('*')) {
SearchName.Length = 0;
}
//
// Open the directory for list access.
//
Status = NtOpenFile(
&Handle,
FILE_LIST_DIRECTORY | SYNCHRONIZE,
&Obja,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT
);
if ( !NT_SUCCESS(Status) ) {
XapiSetLastNTError(Status);
return INVALID_HANDLE_VALUE;
}
//
// Get the first entry from the directory.
//
Status = NtQueryDirectoryFile(
Handle,
NULL,
NULL,
NULL,
&IoStatusBlock,
&FullDirInfo,
sizeof(FullDirInfo),
FileDirectoryInformation,
&SearchName,
FALSE
);
if ( !NT_SUCCESS(Status) ) {
NtClose(Handle);
XapiSetLastNTError(Status);
return INVALID_HANDLE_VALUE;
}
XapiDirectoryInformationToFindData(&FullDirInfo.DirInfo, lpFindFileData);
return Handle;
}
BOOL
APIENTRY
FindNextFile(
HANDLE hFindFile,
LPWIN32_FIND_DATA lpFindFileData
)
/*++
Routine Description:
Once a successful call has been made to FindFirstFile, subsequent
matching files can be located using FindNextFile.
This API is used to continue a file search from a previous call to
FindFirstFile. This API returns successfully with the next file
that matches the search pattern established in the original
FindFirstFile call. If no file match can be found NO_MORE_FILES is
returned.
Note that while this interface only returns information for a single
file, an implementation is free to buffer several matching files
that can be used to satisfy subsequent calls to FindNextFile. Also
not that matches are done by name only. This API does not do
attribute based matching.
This API is similar to DOS (int 21h, function 4Fh), and OS/2's
DosFindNext. For portability reasons, its data structures and
parameter passing is somewhat different.
Arguments:
hFindFile - Supplies a find file handle returned in a previous call
to FindFirstFile.
lpFindFileData - On a successful find, this parameter returns information
about the located file.
Return Value:
TRUE - The operation was successful.
FALSE/NULL - The operation failed. Extended error status is available
using GetLastError.
--*/
{
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
struct {
FILE_DIRECTORY_INFORMATION DirInfo;
OCHAR FileName[256];
} FullDirInfo;
Status = NtQueryDirectoryFile(
hFindFile,
NULL,
NULL,
NULL,
&IoStatusBlock,
&FullDirInfo,
sizeof(FullDirInfo),
FileDirectoryInformation,
NULL,
FALSE
);
if ( !NT_SUCCESS(Status) ) {
XapiSetLastNTError(Status);
return FALSE;
}
XapiDirectoryInformationToFindData(&FullDirInfo.DirInfo, lpFindFileData);
return TRUE;
}