/* findfile.c -- scan directory for contents including volume information Copyright (C) 1999-2000 Wojciech Galazka This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "lfnsrv.h" HANDLE hFindFile[MAX_HANDLES]; BYTE tnSearchAttr[MAX_HANDLES]; BYTE tnMustMatchAttr[MAX_HANDLES]; BYTE nHandlesUsed; #ifndef FILE_ATTRIBUTE_VOLUME_LABEL #define FILE_ATTRIBUTE_VOLUME_LABEL FILE_ATTR_VOLUME_LABEL #endif WORD TranslateDateTime( IN OUT PFILETIME p, IN WORD wDateType); WORD process_find_first( IN LPCSTR lpPathName, IN BYTE nSearchAttr, IN BYTE nMustMatchAttr, IN WORD wDateType, OUT PWIN32_FIND_DATA pFindStruct, OUT PBYTE pnUnicode, OUT PWORD phandle) { BYTE i; HANDLE hTmp; WORD result ; BYTE nFoundAttr ; BOOL bSearch = TRUE; PROLOG(process_find_first); IS_NULL(pFindStruct, ERROR_NO_MORE_FILES); if (wDateType != LONG_FIND_DATE_FILE && wDateType != LONG_FIND_DATE_DOS) { result = ERROR_NO_MORE_FILES; EPILOG(process_find_first,TRUE); return result; } IS_NULL(lpPathName, ERROR_FILE_NOT_FOUND); IS_MAX_PATH_SIZE(lpPathName); ISNULL(phandle); DBGVALUE(lpPathName, "%s"); DBGVALUE(nSearchAttr, "%d"); DBGVALUE(nMustMatchAttr, "%d"); DBGVALUE(wDateType,"%d"); if (nHandlesUsed >= MAX_HANDLES) { result = ERROR_NO_MORE_FILES; DBGMSG("FindFirst #2, Not enough handles"); EPILOG(process_find_first,FALSE); return result; } *phandle =0; nSearchAttr &= (FILE_ATTR_READONLY|FILE_ATTR_HIDDEN| FILE_ATTR_SYSTEM|FILE_ATTR_ARCHIVE| FILE_ATTR_DIRECTORY|FILE_ATTR_VOLUME_LABEL); nMustMatchAttr &= (FILE_ATTR_READONLY|FILE_ATTR_HIDDEN| FILE_ATTR_SYSTEM|FILE_ATTR_ARCHIVE| FILE_ATTR_DIRECTORY|FILE_ATTR_VOLUME_LABEL); DBGVALUE(lpPathName, "%s"); DBGVALUE(nSearchAttr,"%d"); DBGVALUE(nMustMatchAttr,"%d"); DBGMSG("#1"); #if 0 memset(pFindStruct, 0, sizeof (WIN32_FIND_DATA)); #endif if (nSearchAttr == FILE_ATTR_VOLUME_LABEL ) { if (nMustMatchAttr == FILE_ATTR_VOLUME_LABEL || nMustMatchAttr == 0) { char RootName[4]; // "X:\*.*" if ( lstrlen(lpPathName) < 6 || !(lpPathName[1] == ':' && lpPathName[2]== '\\' && lpPathName[3] == '*' && lpPathName[4] == '.' && lpPathName[5] == '*')) { result = ERROR_PATH_NOT_FOUND; DBGMSG("Volume Information not available 1"); DBGVALUE(lpPathName,"%s"); EPILOG(process_find_first,TRUE); return result; } RootName[0] = lpPathName[0]; // "X:\\" RootName[1] = lpPathName[1]; RootName[2] = lpPathName[2]; RootName[3] = '\0'; SetErrorMode(SEM_FAILCRITICALERRORS); if (!GetVolumeInformation(RootName, pFindStruct->cFileName, MAX_PATH, NULL, NULL, NULL, NULL, 0)) { result = ERROR_PATH_NOT_FOUND; DBGMSG("Volume Information not available 2"); DBGVALUE(lpPathName,"%s"); EPILOG(process_find_first,TRUE); return result; } // other fields already zeroed by memset lstrcpy(pFindStruct->cAlternateFileName, pFindStruct->cFileName); pFindStruct->dwFileAttributes = FILE_ATTRIBUTE_VOLUME_LABEL; nSearchAttr = FILE_ATTRIBUTE_VOLUME_LABEL; nMustMatchAttr = RootName[0]; hTmp = NULL; } else { result = ERROR_PATH_NOT_FOUND; DBGMSG("Strange attribs specified for vol info"); DBGVALUE(nMustMatchAttr,"%d"); EPILOG(process_find_first,TRUE); return result; } } else { // not FILE_ATTR_VOLUME_LABEL DBGMSG("#2"); DBGVALUE(lpPathName, "%s"); if ((hTmp = FindFirstFile(lpPathName, pFindStruct)) == INVALID_HANDLE_VALUE) { result = (WORD)GetLastError(); if (result != ERROR_NO_MORE_FILES && result != ERROR_PATH_NOT_FOUND && result != ERROR_FILE_NOT_FOUND) { DBGMSG("FindNextFile failed 3"); DBGVALUE(lpPathName,"%s"); } EPILOG(process_find_first,TRUE); return result; } DBGMSG("#3"); nFoundAttr = LOBYTE(LOWORD(pFindStruct->dwFileAttributes)); nFoundAttr &= (FILE_ATTR_READONLY|FILE_ATTR_HIDDEN| FILE_ATTR_SYSTEM|FILE_ATTR_ARCHIVE| FILE_ATTR_DIRECTORY|FILE_ATTR_VOLUME_LABEL); while (bSearch) { if ((((nMustMatchAttr & ~nFoundAttr) & 0x3F) == 0) && (((~nSearchAttr & nFoundAttr) & 0x1E) == 0)) { bSearch = FALSE; } else { if (FindNextFile(hTmp, pFindStruct)) { nFoundAttr = LOBYTE(LOWORD(pFindStruct->dwFileAttributes)); nFoundAttr &= (FILE_ATTR_READONLY|FILE_ATTR_HIDDEN| FILE_ATTR_SYSTEM|FILE_ATTR_ARCHIVE| FILE_ATTR_DIRECTORY|FILE_ATTR_VOLUME_LABEL); } else { result = (WORD)GetLastError(); FindClose(hTmp); if (result != ERROR_NO_MORE_FILES && result != ERROR_PATH_NOT_FOUND && result != ERROR_FILE_NOT_FOUND) DBGMSG("FindNextFile failed"); EPILOG(process_find_first,TRUE); return result; } } } pFindStruct->dwFileAttributes = nFoundAttr; if (TranslateDateTime(&pFindStruct->ftCreationTime, wDateType)) DBGMSG("Bad Creation Time"); if (TranslateDateTime(&pFindStruct->ftLastWriteTime, wDateType)) DBGMSG("Bad Last Write Time"); if (TranslateDateTime(&pFindStruct->ftLastAccessTime, wDateType)) { DBGMSG("Bad Last Access Time"); memcpy(&pFindStruct->ftLastAccessTime, &pFindStruct->ftLastWriteTime, sizeof(FILETIME)); } } DBGVALUE(pFindStruct->cFileName,"%s"); DBGVALUE(pFindStruct->cAlternateFileName,"%s"); DBGVALUE(pFindStruct->dwFileAttributes,"%ld"); for (i = MIN_HANDLES; i < MAX_HANDLES; i++) { if (hFindFile[i] != INVALID_HANDLE_VALUE) continue; hFindFile[i] = hTmp; tnSearchAttr[i] = nSearchAttr; tnMustMatchAttr[i] = nMustMatchAttr; *phandle = i; break; } if (*phandle == 0) { result = ERROR_NO_MORE_FILES; DBGMSG("FindFirst 2 Not enough handles"); EPILOG(process_find_first, TRUE); return result; } nHandlesUsed++; if (pnUnicode) { *pnUnicode = LONG_FIND_UNICODE_NONE; DBGVALUE(*pnUnicode,"%d"); } DBGVALUE(*phandle,"%d"); DBGVALUE(nHandlesUsed,"%d"); EPILOG(process_find_first,TRUE); return ERROR_SUCCESS; } WORD process_find_next( IN WORD wFind, IN WORD wDateType, OUT PWIN32_FIND_DATA pFindStruct, OUT PBYTE pnUnicode) { BYTE nSearchAttr; BYTE nMustMatchAttr; BYTE nFlag; BYTE nFoundAttr = 0; HANDLE hTmp; BOOL bSearch = TRUE; WORD result ; PROLOG(process_find_next); IS_NULL(pFindStruct, ERROR_NO_MORE_FILES); DBGVALUE(wFind,"%d"); DBGVALUE(wDateType,"%d"); if (wDateType != LONG_FIND_DATE_FILE && wDateType != LONG_FIND_DATE_DOS) { result = ERROR_INVALID_FUNCTION; DBGMSG("FindNext #1"); EPILOG(process_find_next,FALSE); return result; } if (wFind < MIN_HANDLES || wFind >=MAX_HANDLES) { result = ERROR_INVALID_HANDLE; DBGMSG("FindNext #2, Wrong handle"); EPILOG(process_find_next,FALSE); return result; } hTmp = hFindFile[wFind]; nSearchAttr = tnSearchAttr[wFind]; nMustMatchAttr = tnMustMatchAttr[wFind]; if (hTmp == INVALID_HANDLE_VALUE) { result = ERROR_INVALID_HANDLE; DBGMSG("FindNext #3,Invalid handle"); EPILOG(process_find_next,FALSE); return result; } #if 0 memset(pFindStruct, 0, sizeof (WIN32_FIND_DATA)); #endif if ( nSearchAttr == FILE_ATTRIBUTE_VOLUME_LABEL ) { // "X:\" char RootName[4]; RootName[0] = nMustMatchAttr; RootName[1] = ':'; RootName[2] = '\\'; RootName[3] = '\0'; SetErrorMode(SEM_FAILCRITICALERRORS); if (!GetVolumeInformation(RootName, pFindStruct->cFileName, MAX_PATH, NULL, NULL, NULL, NULL, 0)) { result = ERROR_PATH_NOT_FOUND; DBGMSG("Volume Information not available 3"); DBGVALUE(RootName,"%s"); EPILOG(process_find_next,TRUE); return result; } // date and size already zeroed by memset lstrcpy(pFindStruct->cAlternateFileName, pFindStruct->cFileName); pFindStruct->dwFileAttributes = FILE_ATTRIBUTE_VOLUME_LABEL; hTmp = NULL; } else { do { if (!FindNextFile(hTmp, pFindStruct)) { result = (WORD)GetLastError(); if (result != ERROR_NO_MORE_FILES && result != ERROR_PATH_NOT_FOUND && result != ERROR_FILE_NOT_FOUND) DBGMSG("FindNextFile failed"); EPILOG(process_find_next,TRUE); return result; } nFoundAttr = LOBYTE(LOWORD(pFindStruct->dwFileAttributes)); nFoundAttr &= (FILE_ATTR_READONLY|FILE_ATTR_HIDDEN| FILE_ATTR_SYSTEM|FILE_ATTR_ARCHIVE| FILE_ATTR_DIRECTORY|FILE_ATTR_VOLUME_LABEL); if ((((nMustMatchAttr & ~nFoundAttr) & 0x3F) == 0) && (((~nSearchAttr & nFoundAttr) & 0x1E) == 0)) bSearch = FALSE; } while (bSearch); pFindStruct->dwFileAttributes = nFoundAttr; if (TranslateDateTime(&pFindStruct->ftCreationTime, wDateType)) DBGMSG("Bad Creation Time"); if (TranslateDateTime(&pFindStruct->ftLastWriteTime, wDateType)) DBGMSG("Bad Last Write Time"); if (TranslateDateTime(&pFindStruct->ftLastAccessTime, wDateType)) { DBGMSG("Bad Last Access Time"); memcpy(&pFindStruct->ftLastAccessTime, &pFindStruct->ftLastWriteTime, sizeof(FILETIME)); } } DBGVALUE(pFindStruct->cFileName,"%s"); DBGVALUE(pFindStruct->cAlternateFileName,"%s"); DBGVALUE(pFindStruct->dwFileAttributes,"%ld"); if (pnUnicode) { *pnUnicode = LONG_FIND_UNICODE_NONE; DBGVALUE(*pnUnicode,"%d"); } EPILOG(process_find_next,TRUE); return ERROR_SUCCESS; } WORD process_find_close( IN WORD wFind) { HANDLE hTmp; BYTE nSearchAttr; BYTE nMustMatchAttr; WORD result; PROLOG(process_find_close); DBGVALUE(wFind,"%d"); if (wFind < MIN_HANDLES || wFind >=MAX_HANDLES) { result = ERROR_INVALID_HANDLE; DBGMSG("FindClose #1,Wrong handle"); EPILOG(process_find_close,FALSE); return result; } hTmp = hFindFile[wFind]; nSearchAttr = tnSearchAttr[wFind]; nMustMatchAttr = tnMustMatchAttr[wFind]; nHandlesUsed--; if (hTmp == INVALID_HANDLE_VALUE) { result = ERROR_INVALID_HANDLE; DBGMSG("FindClose #2,Invalid handle"); EPILOG(process_find_close,TRUE); return result; } result = ERROR_SUCCESS; if (nSearchAttr != FILE_ATTRIBUTE_VOLUME_LABEL ) if (!FindClose(hTmp)) { result = (WORD)GetLastError(); DBGMSG("FindClose #3, FindClose failed"); } hFindFile[wFind] = INVALID_HANDLE_VALUE; EPILOG(process_find_close,TRUE); return result; } WORD TranslateDateTime( IN OUT PFILETIME p, IN WORD wDateType) { #define MAKEDATE(date, time) (((date) << 16)| (time)) WORD wDate, wTime; WORD result; FILETIME q; ISNULL(p); if (!FileTimeToLocalFileTime(p, &q)) { result = (WORD)GetLastError(); DBGMSG("FFCD 1"); return result; } else result = ERROR_SUCCESS; if (wDateType == LONG_FIND_DATE_DOS) { if (!FileTimeToDosDateTime(&q, &wDate, &wTime)) { q.dwLowDateTime = MAKEDATE(0, 0); result = (WORD)GetLastError(); DBGMSG("FFCD 2"); } else { q.dwLowDateTime = MAKEDATE(wDate, wTime); result = ERROR_SUCCESS; } } memcpy(p, &q, sizeof(FILETIME)); return result; }