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;
|
|
}
|