/*++ 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()); }