int far pascal __loadds FS_FINDFIRST(struct cdfsi far * pcdfsi, /* pcdfsi */ struct cdfsd far * pcdfsd, /* pcdfsd */ char far * pName, /* pName */ unsigned short usCurDirEnd, /* iCurDirEnd */ unsigned short usAttr, /* attr */ struct fsfsi far * pfsfsi, /* pfsfsi */ struct fsfsd far * pfsfsd, /* pfsfsd */ char far * pData, /* pData */ unsigned short cbData, /* cbData */ unsigned short far * pcMatch, /* pcMatch */ unsigned short usLevel, /* level */ unsigned short usFlags) /* flags */ { PVOLINFO pVolInfo; PFINDINFO pFindInfo = (PFINDINFO)pfsfsd; USHORT rc; USHORT usIndex; USHORT usNeededLen; USHORT usNumClusters; ULONG ulCluster; ULONG ulDirCluster; PSZ pSearch; PFINFO pNext; ULONG ulNeededSpace; USHORT usEntriesWanted; EAOP EAOP; PROCINFO ProcInfo; if (f32Parms.fMessageActive & LOG_FS) Message("FS_FINDFIRST for %s attr %X, Level %d, cbData %u, MaxEntries %u", pName, usAttr, usLevel, cbData, *pcMatch); usEntriesWanted = *pcMatch; *pcMatch = 0; if (strlen(pName) > FAT32MAXPATH) { rc = ERROR_FILENAME_EXCED_RANGE; goto FS_FINDFIRSTEXIT; } memset(pfsfsd, 0, sizeof (struct fsfsd)); pVolInfo = GetVolInfo(pfsfsi->fsi_hVPB); if (IsDriveLocked(pVolInfo)) { rc = ERROR_DRIVE_LOCKED; goto FS_FINDFIRSTEXIT; } switch (usLevel) { case FIL_STANDARD : usNeededLen = sizeof (FILEFNDBUF) - CCHMAXPATHCOMP; break; case FIL_QUERYEASIZE : usNeededLen = sizeof (FILEFNDBUF2) - CCHMAXPATHCOMP; break; case FIL_QUERYEASFROMLIST : usNeededLen = sizeof (EAOP) + sizeof (FILEFNDBUF3) + sizeof (ULONG); break; default : rc = ERROR_NOT_SUPPORTED; goto FS_FINDFIRSTEXIT; } if (usFlags == FF_GETPOS) usNeededLen += sizeof (ULONG); if (cbData < usNeededLen) { rc = ERROR_BUFFER_OVERFLOW; goto FS_FINDFIRSTEXIT; } rc = MY_PROBEBUF(PB_OPWRITE, pData, cbData); if (rc) { Message("FAT32: Protection VIOLATION in FS_FINDFIRST! (SYS%d)", rc); return rc; } if (usLevel == FIL_QUERYEASFROMLIST) { memcpy(&EAOP, pData, sizeof (EAOP)); rc = MY_PROBEBUF(PB_OPREAD, (PBYTE)EAOP.fpGEAList, (USHORT)EAOP.fpGEAList->cbList); if (rc) goto FS_FINDFIRSTEXIT; } memset(pData, 0, cbData); usNumClusters = 0; ulDirCluster = FindDirCluster(pVolInfo, pcdfsi, pcdfsd, pName, usCurDirEnd, RETURN_PARENT_DIR, &pSearch); if (ulDirCluster == FAT_EOF) { rc = ERROR_PATH_NOT_FOUND; goto FS_FINDFIRSTEXIT; } ulCluster = ulDirCluster; while (ulCluster && ulCluster != FAT_EOF) { usNumClusters++; ulCluster = GetNextCluster( pVolInfo, ulCluster); } ulNeededSpace = sizeof (FINFO) + (usNumClusters - 1) * sizeof (ULONG); ulNeededSpace += pVolInfo->usClusterSize; GetProcInfo(&ProcInfo, sizeof ProcInfo); pFindInfo->pInfo = (PFINFO)malloc((size_t)ulNeededSpace); if (!pFindInfo->pInfo) { rc = ERROR_NOT_ENOUGH_MEMORY; goto FS_FINDFIRSTEXIT; } memset(pFindInfo->pInfo, 0, (size_t)ulNeededSpace); if (!pVolInfo->pFindInfo) pVolInfo->pFindInfo = pFindInfo->pInfo; else { pNext = (PFINFO)pVolInfo->pFindInfo; while (pNext->pNextEntry) pNext = (PFINFO)pNext->pNextEntry; pNext->pNextEntry = pFindInfo->pInfo; } memcpy(&pFindInfo->pInfo->EAOP, &EAOP, sizeof (EAOP)); pFindInfo->usEntriesPerCluster = pVolInfo->usClusterSize / sizeof (DIRENTRY); pFindInfo->usClusterIndex = 0; pFindInfo->pInfo->rgClusters[0] = ulDirCluster; pFindInfo->usTotalClusters = usNumClusters; pFindInfo->pInfo->pDirEntries = (PDIRENTRY)(&pFindInfo->pInfo->rgClusters[usNumClusters]); if (f32Parms.fMessageActive & LOG_FIND) Message("pInfo at %lX, pDirEntries at %lX", pFindInfo->pInfo, pFindInfo->pInfo->pDirEntries); pFindInfo->pInfo->pNextEntry = NULL; memcpy(&pFindInfo->pInfo->ProcInfo, &ProcInfo, sizeof (PROCINFO)); strcpy(pFindInfo->pInfo->szSearch, pSearch); FSH_UPPERCASE(pFindInfo->pInfo->szSearch, sizeof pFindInfo->pInfo->szSearch, pFindInfo->pInfo->szSearch); pFindInfo->ulMaxEntry = ((ULONG)pVolInfo->usClusterSize / sizeof (DIRENTRY)) * usNumClusters; if (!GetCluster(pVolInfo, pFindInfo, 0)) { rc = ERROR_SYS_INTERNAL; goto FS_FINDFIRSTEXIT; } pFindInfo->ulCurEntry = 0; if (usAttr & 0x0040) { pFindInfo->fLongNames = TRUE; usAttr &= ~0x0040; } else pFindInfo->fLongNames = FALSE; pFindInfo->bMustAttr = (BYTE)(usAttr >> 8); usAttr |= (FILE_READONLY | FILE_ARCHIVED); usAttr &= (FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED); pFindInfo->bAttr = (BYTE)~usAttr; if (usLevel == FIL_QUERYEASFROMLIST) { memcpy(pData, &pFindInfo->pInfo->EAOP, sizeof (EAOP)); pData += sizeof (EAOP); cbData -= sizeof (EAOP); } rc = 0; for (usIndex = 0; usIndex < usEntriesWanted; usIndex++) { PULONG pulOrdinal; if (usFlags == FF_GETPOS) { if (cbData < sizeof (ULONG)) { rc = ERROR_BUFFER_OVERFLOW; break; } pulOrdinal = (PULONG)pData; pData += sizeof (ULONG); cbData -= sizeof (ULONG); } rc = FillDirEntry(pVolInfo, &pData, &cbData, pFindInfo, usLevel); if (!rc || (rc == ERROR_EAS_DIDNT_FIT && usIndex == 0)) { if (usFlags == FF_GETPOS) *pulOrdinal = pFindInfo->ulCurEntry - 1; } if (rc) break; } if ((rc == ERROR_NO_MORE_FILES || rc == ERROR_BUFFER_OVERFLOW || rc == ERROR_EAS_DIDNT_FIT) && usIndex > 0) rc = 0; if (rc == ERROR_EAS_DIDNT_FIT && usIndex == 0) usIndex = 1; *pcMatch = usIndex; FS_FINDFIRSTEXIT: if (f32Parms.fMessageActive & LOG_FS) Message("FS_FINDFIRST returned %d (%d entries)", rc, *pcMatch); if (rc && rc != ERROR_EAS_DIDNT_FIT) { FS_FINDCLOSE(pfsfsi, pfsfsd); } return rc; }
USHORT FillDirEntry(PVOLINFO pVolInfo, PBYTE * ppData, PUSHORT pcbData, PFINDINFO pFindInfo, USHORT usLevel) { BYTE szLongName[FAT32MAXPATHCOMP]; BYTE szUpperName[FAT32MAXPATHCOMP]; BYTE szShortName[14]; PBYTE pStart = *ppData; USHORT rc; DIRENTRY _huge * pDir; BYTE bCheck1; USHORT usClusterIndex; memset(szLongName, 0, sizeof szLongName); pDir = &pFindInfo->pInfo->pDirEntries[pFindInfo->ulCurEntry % pFindInfo->usEntriesPerCluster]; bCheck1 = 0; while (pFindInfo->ulCurEntry < pFindInfo->ulMaxEntry) { memset(szShortName, 0, sizeof(szShortName)); // vs usClusterIndex = (USHORT)(pFindInfo->ulCurEntry / pFindInfo->usEntriesPerCluster); if (usClusterIndex != pFindInfo->usClusterIndex) { if (!GetCluster(pVolInfo, pFindInfo, usClusterIndex)) return ERROR_SYS_INTERNAL; pDir = &pFindInfo->pInfo->pDirEntries[pFindInfo->ulCurEntry % pFindInfo->usEntriesPerCluster]; } if (pDir->bFileName[0] && pDir->bFileName[0] != DELETED_ENTRY) { if (pDir->bAttr == FILE_LONGNAME) { fGetLongName(pDir, szLongName, sizeof szLongName, &bCheck1); } else if ((pDir->bAttr & FILE_VOLID) != FILE_VOLID) { if (!(pDir->bAttr & pFindInfo->bAttr)) { BYTE bCheck2 = GetVFATCheckSum(pDir); MakeName(pDir, szShortName, sizeof szShortName); FSH_UPPERCASE(szShortName, sizeof szShortName, szShortName); rc = 0; if (f32Parms.fEAS && bCheck2 == bCheck1 && strlen(szLongName)) if (IsEASFile(szLongName)) rc = 1; if (f32Parms.fMessageActive & LOG_FIND) { if (bCheck2 != bCheck1 && strlen(szLongName)) Message("Invalid LFN entry found: %s", szLongName); } if (bCheck2 != bCheck1 || !strlen(szLongName)) { strcpy(szLongName, szShortName); /* support for the FAT32 variation of WinNT family */ if( HAS_WINNT_EXT( pDir->fEAS )) { PBYTE pDot = strchr( szLongName, '.' );; if( HAS_WINNT_EXT_NAME( pDir->fEAS )) /* name part is lower case */ { if( pDot ) *pDot = 0; strlwr( szLongName ); if( pDot ) *pDot = '.'; } if( pDot && HAS_WINNT_EXT_EXT( pDir->fEAS )) /* ext part is lower case */ strlwr( pDot + 1 ); } } if (f32Parms.fEAS && IsEASFile(szLongName)) rc = 1; strcpy(szUpperName, szLongName); FSH_UPPERCASE(szUpperName, sizeof szUpperName, szUpperName); if( !pFindInfo->fLongNames ) strcpy( szLongName, szShortName ); /* Check for MUST HAVE attributes */ if (!rc && pFindInfo->bMustAttr) { if ((pDir->bAttr & pFindInfo->bMustAttr) != pFindInfo->bMustAttr) rc = 1; } if (!rc && strlen(pFindInfo->pInfo->szSearch)) { rc = FSH_WILDMATCH(pFindInfo->pInfo->szSearch, szUpperName); if (rc && stricmp(szShortName, szUpperName)) rc = FSH_WILDMATCH(pFindInfo->pInfo->szSearch, szShortName); } if (!rc && f32Parms.fMessageActive & LOG_FIND) Message("%lu : %s, %s", pFindInfo->ulCurEntry, szLongName, szShortName ); if (!rc && usLevel == FIL_STANDARD) { PFILEFNDBUF pfFind = (PFILEFNDBUF)*ppData; if (*pcbData < sizeof (FILEFNDBUF) - CCHMAXPATHCOMP + strlen(szLongName) + 1) return ERROR_BUFFER_OVERFLOW; pfFind->fdateCreation = pDir->wCreateDate; pfFind->ftimeCreation = pDir->wCreateTime; pfFind->fdateLastAccess = pDir->wAccessDate; pfFind->fdateLastWrite = pDir->wLastWriteDate; pfFind->ftimeLastWrite = pDir->wLastWriteTime; pfFind->cbFile = pDir->ulFileSize; pfFind->cbFileAlloc = (pfFind->cbFile / pVolInfo->usClusterSize) * pVolInfo->usClusterSize + (pfFind->cbFile % pVolInfo->usClusterSize ? pVolInfo->usClusterSize : 0); pfFind->attrFile = (USHORT)pDir->bAttr; pfFind->cchName = (BYTE)strlen(szLongName); strcpy(pfFind->achName, szLongName); *ppData = pfFind->achName + pfFind->cchName + 1; (*pcbData) -= *ppData - pStart; pFindInfo->ulCurEntry++; return 0; } else if (!rc && usLevel == FIL_QUERYEASIZE) { PFILEFNDBUF2 pfFind = (PFILEFNDBUF2)*ppData; if (*pcbData < sizeof (FILEFNDBUF2) - CCHMAXPATHCOMP + strlen(szLongName) + 1) return ERROR_BUFFER_OVERFLOW; pfFind->fdateCreation = pDir->wCreateDate; pfFind->ftimeCreation = pDir->wCreateTime; pfFind->fdateLastAccess = pDir->wAccessDate; pfFind->fdateLastWrite = pDir->wLastWriteDate; pfFind->ftimeLastWrite = pDir->wLastWriteTime; pfFind->cbFile = pDir->ulFileSize; pfFind->cbFileAlloc = (pfFind->cbFile / pVolInfo->usClusterSize) + (pfFind->cbFile % pVolInfo->usClusterSize ? 1 : 0); if (!f32Parms.fEAS || !HAS_EAS( pDir->fEAS )) pfFind->cbList = sizeof pfFind->cbList; else { rc = usGetEASize(pVolInfo, pFindInfo->pInfo->rgClusters[0], szLongName, &pfFind->cbList); if (rc) pfFind->cbList = 4; rc = 0; } pfFind->attrFile = (USHORT)pDir->bAttr; pfFind->cchName = (BYTE)strlen(szLongName); strcpy(pfFind->achName, szLongName); *ppData = pfFind->achName + pfFind->cchName + 1; (*pcbData) -= *ppData - pStart; pFindInfo->ulCurEntry++; return 0; } else if (!rc && usLevel == FIL_QUERYEASFROMLIST) { PFILEFNDBUF3 pfFind = (PFILEFNDBUF3)*ppData; ULONG ulFeaSize; if (*pcbData < sizeof (FILEFNDBUF3) + sizeof (ULONG) + strlen(szLongName) + 2) return ERROR_BUFFER_OVERFLOW; pfFind->fdateCreation = pDir->wCreateDate; pfFind->ftimeCreation = pDir->wCreateTime; pfFind->fdateLastAccess = pDir->wAccessDate; pfFind->fdateLastWrite = pDir->wLastWriteDate; pfFind->ftimeLastWrite = pDir->wLastWriteTime; pfFind->cbFile = pDir->ulFileSize; pfFind->cbFileAlloc = (pfFind->cbFile / pVolInfo->usClusterSize) * pVolInfo->usClusterSize + (pfFind->cbFile % pVolInfo->usClusterSize ? pVolInfo->usClusterSize : 0); pfFind->attrFile = (USHORT)pDir->bAttr; *ppData = (PBYTE)(pfFind + 1); (*pcbData) -= *ppData - pStart; if (f32Parms.fEAS && HAS_EAS( pDir->fEAS )) { pFindInfo->pInfo->EAOP.fpFEAList = (PFEALIST)*ppData; pFindInfo->pInfo->EAOP.fpFEAList->cbList = *pcbData - (strlen(szLongName) + 2); rc = usGetEAS(pVolInfo, FIL_QUERYEASFROMLIST, pFindInfo->pInfo->rgClusters[0], szLongName, &pFindInfo->pInfo->EAOP); if (rc && rc != ERROR_BUFFER_OVERFLOW) return rc; if (rc) { rc = ERROR_EAS_DIDNT_FIT; ulFeaSize = sizeof (ULONG); } else ulFeaSize = pFindInfo->pInfo->EAOP.fpFEAList->cbList; } else { pFindInfo->pInfo->EAOP.fpFEAList = (PFEALIST)*ppData; pFindInfo->pInfo->EAOP.fpFEAList->cbList = *pcbData - (strlen(szLongName) + 2); rc = usGetEmptyEAS(szLongName,&pFindInfo->pInfo->EAOP); if (rc && (rc != ERROR_EAS_DIDNT_FIT)) return rc; else if (rc == ERROR_EAS_DIDNT_FIT) ulFeaSize = sizeof(pFindInfo->pInfo->EAOP.fpFEAList->cbList); else ulFeaSize = pFindInfo->pInfo->EAOP.fpFEAList->cbList; } (*ppData) += ulFeaSize; (*pcbData) -= ulFeaSize; /* Length and longname */ *(*ppData)++ = (BYTE)strlen(szLongName); (*pcbData)--; strcpy(*ppData, szLongName); (*ppData) += strlen(szLongName) + 1; (*pcbData) -= (strlen(szLongName) + 1); pFindInfo->ulCurEntry++; return rc; } } memset(szLongName, 0, sizeof szLongName); } } pFindInfo->ulCurEntry++; pDir++; } return ERROR_NO_MORE_FILES; }
int far pascal _loadds FS_FINDFIRST( struct cdfsi far *pcdfsi, struct cdfsd far *pcdfsd, char far *pName, unsigned short iCurDirEnd, unsigned short attr, struct fsfsi far *pfsfsi, struct fsfsd far *pfsfsd, char far *pData, unsigned short cbData, unsigned short far *pcMatch, unsigned short level, unsigned short flags ) { int rc; unsigned long size; char far *p; FILEFINDBUF2 far *ff; char buf[0x100]; kprintf("**** FS_FINDFIRST(\"%s\"), level=%u, flags=%u, curdir=%s, iCurDirEnd=%d\n", pName, level, flags, pcdfsi->cdi_curdir, iCurDirEnd); p = pName; // skip a drive letter if (p[1] == ':' && p[2] == '\\') p += 2; /* find by trying to open */ *pcMatch = 0; rc = 2; // file not found if (!MFS_OPEN(p, &size)) { // file found switch (level) { case 1: *pcMatch = 1; break; case 2: // query EA size, specially for *.cmd // query write access to the buffer if (!FSH_PROBEBUF(1, pData, cbData)) { // fill in the position field *((unsigned long far *)pData) = 0; // sizeof(FILEFINDBUF2) - CCHMAXPATHCOMP; pData += sizeof(unsigned long); ff = (FILEFINDBUF2 far *)pData; ff->cbFile = size; ff->cbFileAlloc = size; ff->cbList = 0; // sizeof(unsigned long); // for files in root dir. or files in first-level dirs, return the // full pathname; for deeper files, return a filename with last dir // i.e.: s:\tools\netdrive\ndctl.exe -> netdrive\ndctl.exe for (p = pName + strlen(pName) - 1; p > pName && *p != '\\'; p--) ; if (p - pName > 2) { p--; for (; p > pName && *p != '\\'; p--) ; } if (p - pName > 2) p++; else p = pName; ff->cchName = strlen(p); if (attr & 0x0040) { strcpy(ff->achName, p); attr &= ~0x0040; } else FSH_UPPERCASE(p, ff->cchName, ff->achName); kprintf("achName=%s, curdir=%s, cdi_end=%d\n", ff->achName, pcdfsi->cdi_curdir, pcdfsi->cdi_end); } else kprintf("FSH_PROBEBUF failed!\n"); break; default: break; } rc = 0; } return rc; }