304 lines
8.7 KiB
C
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;
|
||
|
}
|