windows-nt/Source/XPSP1/NT/base/cmd/ffirst.c
2020-09-26 16:20:57 +08:00

364 lines
8.6 KiB
C

/*++
Copyright (c) 1988-1999 Microsoft Corporation
Module Name:
ffirst.c
Abstract:
Wrappers for file enumeration
--*/
#include "cmd.h"
PHANDLE FFhandles = NULL;
unsigned FFhndlsaved = 0;
extern unsigned DosErr ;
BOOLEAN FindFirstNt( PTCHAR, PWIN32_FIND_DATA, PHANDLE );
BOOLEAN FindNextNt ( PWIN32_FIND_DATA, HANDLE );
BOOLEAN FindFirst(
BOOL(* fctAttribMatch) (PWIN32_FIND_DATA pffBuf, ULONG attr),
PTCHAR fspec,
ULONG attr,
PWIN32_FIND_DATA pffBuf,
PHANDLE phandle );
BOOLEAN FindNext (
BOOL(* fctAttribMatch) (PWIN32_FIND_DATA pffBuf, ULONG attr),
PWIN32_FIND_DATA pffBuf,
ULONG attr,
HANDLE handle
);
BOOL IsDosAttribMatch( PWIN32_FIND_DATA, ULONG );
BOOL IsNtAttribMatch( PWIN32_FIND_DATA, ULONG );
int findclose( HANDLE );
//
// Under OS/2, we always return entries that are normal, archived or
// read-only (god knows why).
//
// SRCHATTR contains those attribute bits that are used for matching.
//
#define SRCHATTR (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)
/*** IsDosAttribMatch - Simulates the attribute matching from OS/2
*
* Purpose:
* This function determines if the passed in find file buffer has a
* match under the OS/2 find file rules.
*
* Args:
* ffbuf: Buffer returned from FileFirst or Findnext
* attr: Attributes to qualify search
*
* Returns:
* TRUE: if buffer has a attribute match
* FALSE: if not
*/
BOOL
IsDosAttribMatch(
IN PWIN32_FIND_DATA pffBuf,
IN ULONG attr
) {
//
// We emulate the OS/2 behaviour of attribute matching. The semantics
// are evil, so I provide no explanation.
//
pffBuf->dwFileAttributes &= (0x000000FF & ~(FILE_ATTRIBUTE_NORMAL));
if (! ((pffBuf->dwFileAttributes & SRCHATTR) & ~(attr))) {
return TRUE;
} else {
return FALSE;
}
}
BOOL
IsNtAttribMatch(
PWIN32_FIND_DATA pffBuf,
ULONG attr
) {
UNREFERENCED_PARAMETER( pffBuf );
UNREFERENCED_PARAMETER( attr );
//
// for nt calls always return entry. selection should
// should be based upon callers needs. This is primarily used
// in DIR.
return( TRUE );
}
/*** f_how_many - find how many files are there per fspec with given attr
*
* Args:
* fspec: String pointer to file specification.
* attr: Attributes to qualify search
*
* Returns:
* number of files found or -1 if a file is a directory.
*/
int
f_how_many(
PTCHAR fspec,
ULONG attr
) {
WIN32_FIND_DATA ffBuf;
PWIN32_FIND_DATA pffBuf;
PHANDLE phandle;
HANDLE hnFirst ;
unsigned rc;
int cnt=0;
pffBuf = &ffBuf;
if ( ! ffirst (fspec, attr, pffBuf, &hnFirst )) {
if ( ! ffirst (fspec, FILE_ATTRIBUTE_DIRECTORY, pffBuf, &hnFirst )) {
return (0);
}
else {
findclose(hnFirst);
return (f_RET_DIR);
}
}
do {
cnt++;
} while ( fnext (pffBuf, attr, hnFirst ));
findclose(hnFirst) ;
return (cnt);
}
/*** ffirst - find first file/directory and set up find handles
*
* Purpose:
* This function opens a find first handle. I also returns the first
* qualified file/directory. It simulates the DosFindFirst behavior.
*
* Args:
* fspec: String pointer to file specification.
* attr: Attributes to qualify search
* ffbuf: Buffer to hold inforation on found file/directory
* handle: Find first handle
*
* Returns:
* TRUE: If match found
* FALSE: if not
* DosErr: Contains return code if FALSE function return
*/
BOOLEAN
FindFirst(
IN BOOL(* fctAttribMatch) (PWIN32_FIND_DATA pffBuf, ULONG attr),
IN PTCHAR fspec,
IN ULONG attr,
IN PWIN32_FIND_DATA pffBuf,
OUT PHANDLE phandle
) {
BOOLEAN rcode = FALSE;
//
// Loop through looking for a file that matching attributes
//
*phandle = FindFirstFile(fspec, pffBuf);
while (*phandle != (HANDLE) -1) {
if (fctAttribMatch(pffBuf, attr)) {
DosErr = 0;
rcode = TRUE;
break;
}
if (!FindNextFile( *phandle, pffBuf )) {
FindClose( *phandle );
*phandle = (HANDLE)-1;
break;
}
}
//
// If we did find a file (have a handle to prove it) then
// setup a table of saved open find first handles. If we have
// to clean up then these handle can all be closed.
//
if (*phandle != (HANDLE)-1) {
//
// Check if we already created the table. If we have not
// then allocate space for table.
//
if (FFhandles == NULL) {
FFhandles = (PHANDLE)HeapAlloc(GetProcessHeap(), 0, 5 * sizeof(PHANDLE));
} else {
//
// Check if we have space to hold new handle entry
//
if (((FFhndlsaved + 1)* sizeof(PHANDLE)) > HeapSize(GetProcessHeap(), 0, FFhandles)) {
FFhandles = (PHANDLE)HeapReAlloc(GetProcessHeap(), 0, (void*)FFhandles, (FFhndlsaved+1)*sizeof(PHANDLE));
}
}
if (FFhandles != NULL) {
FFhandles[FFhndlsaved++] = *phandle;
}
rcode = TRUE;
}
if (!rcode) {
DosErr = GetLastError();
}
return(rcode);
}
BOOLEAN
FindFirstNt(
IN PTCHAR fspec,
IN PWIN32_FIND_DATA pffBuf,
OUT PHANDLE phandle
)
{
return(FindFirst(IsNtAttribMatch, fspec, 0, pffBuf, phandle));
}
BOOLEAN
ffirst(
PTCHAR fspec,
ULONG attr,
PWIN32_FIND_DATA pffBuf,
PHANDLE phandle
)
{
return(FindFirst(IsDosAttribMatch, fspec, attr, pffBuf, phandle));
}
/*** fnext - find next file/directory
*
* Purpose:
* This function search for the next qualified file or directory.
* ffirst should have been called first and the returned file handle
* should be passed into fnext.
* Args:
* handle: Find first handle
* attr: Attributes to qualify search
* ffbuf: Buffer to hold information on found file/directory
*
* Returns:
* TRUE: If match found
* FALSE: if not
* DosErr: Contains return code if FALSE function return
*/
BOOLEAN
FindNextNt (
IN PWIN32_FIND_DATA pffBuf,
IN HANDLE handle
) {
//
// attributes are ignored for this kind of call
//
return( FindNext( IsNtAttribMatch, pffBuf, 0, handle) );
}
BOOLEAN
fnext (
IN PWIN32_FIND_DATA pffBuf,
IN ULONG attr,
IN HANDLE handle
) {
return( FindNext( IsDosAttribMatch, pffBuf, attr, handle) );
}
BOOLEAN
FindNext (
IN BOOL(* fctAttribMatch) (PWIN32_FIND_DATA pffBuf, ULONG attr),
IN PWIN32_FIND_DATA pffBuf,
IN ULONG attr,
IN HANDLE handle
) {
//
// Loop through looking for a file that matching attributes
//
while (FindNextFile( handle, pffBuf )) {
if (fctAttribMatch( pffBuf, attr )) {
DosErr = 0;
return(TRUE);
}
}
DosErr = GetLastError();
return(FALSE);
}
int findclose(hn)
HANDLE hn;
{
unsigned cnt;
unsigned cnt2;
DEBUG((CTGRP, COLVL, "findclose: handle %lx",hn)) ;
// Locate handle in table
//
for (cnt = 0; (cnt < FFhndlsaved) && FFhandles[cnt] != hn ; cnt++ ) {
;
}
//
// Remove handle from table
//
DEBUG((CTGRP, COLVL, "\t found handle in table at %d",cnt)) ;
if (cnt < FFhndlsaved) {
for (cnt2 = cnt; cnt2 < (FFhndlsaved - 1) ; cnt2++) {
FFhandles[cnt2] = FFhandles[cnt2 + 1];
}
FFhndlsaved--;
//
// Shrink memory
//
if (HeapSize(GetProcessHeap(), 0, FFhandles) > 5*sizeof(PHANDLE)) {
FFhandles = (PHANDLE)HeapReAlloc(GetProcessHeap(), 0, (void*)FFhandles,FFhndlsaved*sizeof(PHANDLE));
}
}
//
// Close even if we couldn't find it in table
//
DEBUG((CTGRP, COLVL, "\t closing handle %lx ",hn)) ;
if (FindClose(hn)) /* Close even if we couldn't find it in table */
return(0);
else
DEBUG((CTGRP, COLVL, "\t Error closing handle %lx ",hn)) ;
return(GetLastError());
}