Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

927 lines
28 KiB

4 years ago
  1. #include "cmd.h"
  2. extern TCHAR CurDrvDir[] ;
  3. extern TCHAR *SaveDir ;
  4. extern DWORD DosErr ;
  5. extern BOOL CtrlCSeen;
  6. PTCHAR SetWildCards( PTCHAR, BOOLEAN );
  7. BOOLEAN IsFATDrive( PTCHAR );
  8. VOID FreeStr( PTCHAR );
  9. VOID SortFileList( PFS, PSORTDESC, ULONG);
  10. BOOLEAN FindFirstNt( PTCHAR, PWIN32_FIND_DATA, PHANDLE );
  11. BOOLEAN FindNextNt ( PWIN32_FIND_DATA, HANDLE );
  12. STATUS SetSearchPath ( PFS, PPATDSC, PTCHAR, ULONG);
  13. STATUS
  14. BuildFSFromPatterns (
  15. IN PDRP pdpr,
  16. IN BOOLEAN fAddWild,
  17. OUT PFS * ppfs
  18. )
  19. {
  20. struct cpyinfo * pcisFile;
  21. TCHAR szCurDir[MAX_PATH + 2];
  22. TCHAR szFilePattern[MAX_PATH + 2];
  23. PTCHAR pszPatternCur;
  24. PPATDSC ppatdscCur;
  25. PFS pfsFirst;
  26. PFS pfsCur;
  27. ULONG cbPath;
  28. BOOLEAN fFatDrive;
  29. ULONG i;
  30. PTCHAR pszT;
  31. //
  32. // determine FAT drive from original pattern.
  33. // Used in several places to control name format etc.
  34. //
  35. DosErr = 0;
  36. //
  37. // Run through each pattern making all sorts of FAT etc. specific
  38. // changes to it and creating the directory list for it. Then
  39. // combine groups of patterns into common directories and recurse
  40. // for each directory group.
  41. //
  42. *ppfs = pfsFirst = (PFS)gmkstr(sizeof(FS));
  43. pfsFirst->pfsNext = NULL;
  44. pfsFirst->pszDir = NULL;
  45. pfsCur = pfsFirst;
  46. pfsCur->cpatdsc = 1;
  47. for(i = 1, ppatdscCur = &(pdpr->patdscFirst);
  48. i <= pdpr->cpatdsc;
  49. i++, ppatdscCur = ppatdscCur->ppatdscNext) {
  50. pszPatternCur = ppatdscCur->pszPattern;
  51. if (!(fFatDrive = IsFATDrive(pszPatternCur)) && DosErr) {
  52. //
  53. // Error in determining file system type so get out.
  54. //
  55. PutStdErr(DosErr, NOARGS);
  56. return( FAILURE );
  57. }
  58. ppatdscCur->fIsFat = fFatDrive;
  59. //
  60. // Do any alterations that require wild cards for searching
  61. // such as change .xxx to *.xxx for FAT file system requests
  62. //
  63. // Note that if the return values is a different buffer then
  64. // the input the input will be freed when we are done with the
  65. // Dir command.
  66. //
  67. //
  68. // Note that though SetWildCards will allocate heap for the
  69. // modified pattern this will get freed when FreeStack is
  70. // called at the end of the Dir call.
  71. //
  72. // An out of memory is the only reason to fail and we would not
  73. // return from that but go through the abort call in gmstr
  74. //
  75. if (fAddWild) {
  76. pszT = SetWildCards(pszPatternCur, fFatDrive);
  77. FreeStr(pszPatternCur);
  78. pszPatternCur = pszT;
  79. }
  80. //
  81. // Convert the current pattern into a path and file part
  82. //
  83. // Save the current directory in SaveDir, change to new directory
  84. // and parse pattern into a copy information structure. This also
  85. // converts pszPatternCur into the current directory which also produces
  86. // a fully qualified name.
  87. //
  88. DosErr = 0;
  89. DEBUG((ICGRP, DILVL, "PrintPattern pattern `%ws'", pszPatternCur));
  90. if ((pcisFile = SetFsSetSaveDir(pszPatternCur)) == (struct cpyinfo *) FAILURE) {
  91. //
  92. // DosErr is set in SetFs.. from GetLastError
  93. //
  94. // BUGBUG map to DIR error code
  95. //
  96. PutStdErr(DosErr, NOARGS);
  97. return( FAILURE );
  98. }
  99. DEBUG((ICGRP, DILVL, "PrintPattern fullname `%ws'", pcisFile->fnptr));
  100. //
  101. // CurDrvDir ends in '\' (old code also and a DOT but I do not
  102. // understand where this would come from I will leave it in for now.
  103. // Remove the final '\' from a copy of the current directory and
  104. // print that version out.
  105. //
  106. mystrcpy(szCurDir,CurDrvDir);
  107. //
  108. // SetFsSetSaveDir changes directories as a side effect. Since all
  109. // work will be in fully qualified paths we do not need this. Also
  110. // since we will change directories for each pattern that is examined
  111. // we will force the directory back to the original each time.
  112. //
  113. // This can not be done until after all use of the current directory
  114. // is made.
  115. //
  116. if (SaveDir) {
  117. mystrcpy(CurDrvDir,SaveDir);
  118. SaveDir = NULL;
  119. }
  120. DEBUG((ICGRP, DILVL, "PrintPattern Current Drive `%ws'", szCurDir));
  121. cbPath = mystrlen(szCurDir);
  122. //
  123. // BUGBUG this is BS. it will not work for
  124. // dbcs. It is assuming character widths.
  125. //
  126. if (cbPath > 3) {
  127. if (fFatDrive && *penulc(szCurDir) == DOT) {
  128. szCurDir[cbPath-2] = NULLC;
  129. } else {
  130. szCurDir[cbPath-1] = NULLC;
  131. }
  132. }
  133. //
  134. // If no room for filename then return
  135. //
  136. if (cbPath >= MAX_PATH -1) {
  137. PutStdErr(ERROR_FILE_NOT_FOUND, NOARGS);
  138. return(FAILURE);
  139. }
  140. //
  141. // Add filename and possibly ext to szSearchPath
  142. // if no filename or ext, use "*"
  143. //
  144. // If pattern was just extension the SetWildCard had already
  145. // added * to front of extension.
  146. //
  147. if (*(pcisFile->fnptr) == NULLC) {
  148. mystrcpy(szFilePattern, TEXT("*"));
  149. } else {
  150. mystrcpy(szFilePattern, pcisFile->fnptr);
  151. }
  152. DEBUG((ICGRP, DILVL, "DIR:PrintPattern Pattern to search for `%ws'", szFilePattern));
  153. //
  154. // Is name too long
  155. //
  156. if ((cbPath + mystrlen(szFilePattern) + 1) > MAX_PATH ) {
  157. PutStdErr(ERROR_BUFFER_OVERFLOW, NOARGS);
  158. return( FAILURE );
  159. } else {
  160. //
  161. // If this is a FAT drive and there was a filename with
  162. // no extension then add '.*' (and there is room)
  163. //
  164. if (*pcisFile->fnptr && (!pcisFile->extptr || !*pcisFile->extptr) &&
  165. ((mystrlen(szFilePattern) + 2) < MAX_PATH) && fFatDrive && fAddWild) {
  166. mystrcat(szFilePattern, TEXT(".*")) ;
  167. }
  168. }
  169. //
  170. // ppatdscCur->pszPattern will be freed at end of command when everything
  171. // else is freed.
  172. //
  173. ppatdscCur->pszPattern = (PTCHAR)gmkstr(_tcslen(szFilePattern)*sizeof(TCHAR) + sizeof(TCHAR));
  174. mystrcpy(ppatdscCur->pszPattern, szFilePattern);
  175. ppatdscCur->pszDir = (PTCHAR)gmkstr(_tcslen(szCurDir)*sizeof(TCHAR) + sizeof(TCHAR));
  176. mystrcpy(ppatdscCur->pszDir, szCurDir);
  177. if (pfsCur->pszDir) {
  178. //
  179. // changing directories so change directory grouping.
  180. //
  181. if (_tcsicmp(pfsCur->pszDir, ppatdscCur->pszDir)) {
  182. pfsCur->pfsNext = (PFS)gmkstr(sizeof(FS));
  183. pfsCur = pfsCur->pfsNext;
  184. pfsCur->pszDir = (PTCHAR)gmkstr(_tcslen(ppatdscCur->pszDir)*sizeof(TCHAR) + sizeof(TCHAR));
  185. mystrcpy(pfsCur->pszDir, ppatdscCur->pszDir);
  186. pfsCur->pfsNext = NULL;
  187. pfsCur->fIsFat = ppatdscCur->fIsFat;
  188. pfsCur->ppatdsc = ppatdscCur;
  189. pfsCur->cpatdsc = 1;
  190. } else {
  191. pfsCur->cpatdsc++;
  192. }
  193. } else {
  194. //
  195. // Have not filled in current fs descriptor yet.
  196. //
  197. pfsCur->pszDir = (PTCHAR)gmkstr(_tcslen(ppatdscCur->pszDir)*sizeof(TCHAR) + 2*sizeof(TCHAR));
  198. mystrcpy(pfsCur->pszDir, ppatdscCur->pszDir);
  199. pfsCur->fIsFat = ppatdscCur->fIsFat;
  200. pfsCur->ppatdsc = ppatdscCur;
  201. }
  202. } // while for running through pattern list
  203. return( SUCCESS );
  204. }
  205. STATUS
  206. DirWalkAndProcess(
  207. IN STATUS (* pfctProcessFiles) ( PSCREEN, PULONG, PLARGE_INTEGER, ULONG, ULONG, PFS ),
  208. IN STATUS (* pfctProcessDir) (PFS, PULONG),
  209. IN PSCREEN pscr,
  210. OUT PULONG pcffTotal,
  211. OUT PLARGE_INTEGER pcbFileTotal,
  212. IN PFS pfsFiles,
  213. IN PDRP pdpr,
  214. IN BOOLEAN fMustExist,
  215. IN BOOLEAN (*pfctPrintErr) (STATUS, PTCHAR)
  216. )
  217. /*++
  218. Routine Description:
  219. Arguments:
  220. Return Value:
  221. Return:
  222. --*/
  223. {
  224. FS fsDirs;
  225. FS fsFilesNext;
  226. ULONG irgpffDirsCur;
  227. TCHAR szDirNew[MAX_PATH + 2];
  228. PTCHAR pszDirName;
  229. BOOLEAN fFatDrive;
  230. BOOLEAN fRecurse;
  231. STATUS rc;
  232. STATUS (* pfctProcessFilesForGetFS) ( PSCREEN, ULONG, ULONG, PLARGE_INTEGER, PFS, PFF );
  233. //
  234. // Turn the file name pattern into a list of files pointed to
  235. // by fsnode. The list of files will be qualified by rgfAttribs
  236. // which come from the attribute switch on the command line.
  237. //
  238. // After getting the file list then sort it and finally print
  239. // it out in the specified format.
  240. //
  241. // Last free the file list since we don't need it.
  242. //
  243. // Keep the directory since we have to use it to get the
  244. // file list.
  245. //
  246. // Check if there are more directories.
  247. //
  248. if (CtrlCSeen) {
  249. return( FAILURE );
  250. }
  251. fFatDrive = pfsFiles->fIsFat;
  252. fRecurse = (BOOLEAN)(pdpr->rgfSwitchs & RECURSESWITCH);
  253. //
  254. // Even though there may be no function to process file list
  255. // still fetch to determine of any patterns qualify. In the case
  256. // of rmdir we are not to process of there is no pattern match
  257. // at the top level.
  258. //
  259. pfctProcessFilesForGetFS = NULL;
  260. if ((pdpr->rgfSwitchs & DELPROCESSEARLY)) {
  261. pfctProcessFilesForGetFS = EraseFile;
  262. }
  263. else
  264. if (!(pdpr->rgfSwitchs & (RECURSESWITCH | WIDEFORMATSWITCH | SORTDOWNFORMATSWITCH | SORTSWITCH)))
  265. pfctProcessFilesForGetFS = DisplayFile;
  266. rc = GetFS(pfsFiles,
  267. pdpr->rgfSwitchs,
  268. pdpr->rgfAttribs,
  269. pdpr->rgfAttribsOnOff,
  270. pdpr->dwTimeType,
  271. pscr,
  272. pfctPrintErr,
  273. pfctProcessFilesForGetFS
  274. );
  275. if (pfctProcessFilesForGetFS) {
  276. *pcffTotal += pfsFiles->cffDisplayed;
  277. }
  278. if (rc != SUCCESS) {
  279. if ((rc != ERROR_FILE_NOT_FOUND) && (rc != ERROR_NO_MORE_FILES)) {
  280. // PutStdErr(rc, NOARGS);
  281. // pfctPrintErr(rc, NULL);
  282. return( rc );
  283. }
  284. //
  285. // GetFS returns this only if not files were found
  286. // at all.
  287. //
  288. if (rc == ERROR_FILE_NOT_FOUND) {
  289. //
  290. // If we are not recursing then do not report error and
  291. // continue down tree. If not report error back to caller.
  292. // If are recursing and files must exist at top level then
  293. // removing all printing for cases where we do not
  294. // continue down tree.
  295. //
  296. if ((!fRecurse) || (fMustExist) ) {
  297. return( rc );
  298. }
  299. }
  300. }
  301. //
  302. // Do not bother to sort if no function to process list
  303. //
  304. if (pfctProcessFiles) {
  305. SortFileList(pfsFiles, pdpr->rgsrtdsc, pdpr->dwTimeType);
  306. if ((rc == SUCCESS) || !fRecurse) {
  307. CHECKSTATUS(pfctProcessFiles(pscr,
  308. pcffTotal,
  309. pcbFileTotal,
  310. pdpr->rgfSwitchs,
  311. pdpr->dwTimeType,
  312. pfsFiles));
  313. }
  314. }
  315. //
  316. // Free up buffer holding files since we no longer need these.
  317. // Move on to determine if we needed to go to another directory
  318. //
  319. FreeStr((PTCHAR)(pfsFiles->pff));
  320. pfsFiles->pff = NULL;
  321. if (CtrlCSeen) {
  322. return( FAILURE );
  323. }
  324. if (fRecurse) {
  325. fsDirs.pszDir = (PTCHAR)gmkstr(_tcslen(pfsFiles->pszDir)*sizeof(TCHAR) + sizeof(TCHAR));
  326. mystrcpy(fsDirs.pszDir, pfsFiles->pszDir);
  327. fsDirs.ppatdsc = (PPATDSC)gmkstr( sizeof( PATDSC ) );
  328. fsDirs.cpatdsc = 1;
  329. fsDirs.fIsFat = pfsFiles->fIsFat;
  330. fsDirs.pfsNext = NULL;
  331. if (fFatDrive) {
  332. fsDirs.ppatdsc->pszPattern = TEXT("*.*");
  333. } else {
  334. fsDirs.ppatdsc->pszPattern = TEXT("*");
  335. }
  336. fsDirs.ppatdsc->pszDir = (PTCHAR)gmkstr(_tcslen(fsDirs.pszDir)*sizeof(TCHAR) + sizeof(TCHAR));
  337. mystrcpy(fsDirs.ppatdsc->pszDir, fsDirs.pszDir);
  338. fsDirs.fIsFat = fsDirs.fIsFat;
  339. fsDirs.ppatdsc->ppatdscNext = NULL;
  340. if (GetFS(&fsDirs,
  341. pdpr->rgfSwitchs,
  342. FILE_ATTRIBUTE_DIRECTORY,
  343. FILE_ATTRIBUTE_DIRECTORY,
  344. pdpr->dwTimeType,
  345. pscr,
  346. NULL,
  347. NULL
  348. ) != SUCCESS) {
  349. //
  350. // No directory below
  351. //
  352. fsDirs.cff = 0;
  353. }
  354. //
  355. // Check for CtrlC again after calling GetFS because
  356. // GetFS may have returned failure because CtrlC was hit
  357. // inside the GetFS function call
  358. //
  359. if (CtrlCSeen) {
  360. return( FAILURE );
  361. }
  362. //
  363. // Increment though the list of directories processing each one
  364. //
  365. for (irgpffDirsCur = 0;irgpffDirsCur < fsDirs.cff;irgpffDirsCur++) {
  366. //
  367. // Do not recurse on .. since that will send you up the tree
  368. //
  369. pszDirName = (PTCHAR)((fsDirs.prgpff[irgpffDirsCur])->data.cFileName);
  370. if (_tcscmp(TEXT(".."),pszDirName) && _tcscmp(TEXT("."),pszDirName)) {
  371. //
  372. // If name is too big then blow it all away
  373. //
  374. if ((_tcslen(pfsFiles->pszDir) + _tcslen(pszDirName) + 2) >= MAX_PATH) {
  375. return( ERROR_BUFFER_OVERFLOW );
  376. }
  377. mystrcpy(szDirNew, pfsFiles->pszDir);
  378. //
  379. // check if it needs a trailing path char
  380. //
  381. if (*lastc(szDirNew) != BSLASH) {
  382. DEBUG((ICGRP, DILVL, "\t New Directory `%ws'",szDirNew));
  383. mystrcat(szDirNew, TEXT("\\"));
  384. }
  385. mystrcat(szDirNew,pszDirName);
  386. DEBUG((ICGRP, DILVL, "\t New Directory `%ws'",szDirNew));
  387. fsFilesNext.pszDir = (PTCHAR)gmkstr(_tcslen(szDirNew)*sizeof(TCHAR) + sizeof(TCHAR));
  388. mystrcpy(fsFilesNext.pszDir, szDirNew);
  389. fsFilesNext.ppatdsc = pfsFiles->ppatdsc;
  390. fsFilesNext.cpatdsc = pfsFiles->cpatdsc;
  391. fsFilesNext.fIsFat = pfsFiles->fIsFat;
  392. fsFilesNext.pfsNext = NULL;
  393. rc = DirWalkAndProcess( pfctProcessFiles,
  394. pfctProcessDir,
  395. pscr, pcffTotal, pcbFileTotal,
  396. &fsFilesNext, pdpr, FALSE, pfctPrintErr);
  397. //
  398. // BUGBUG Should this error code be paid attention to
  399. // and what should it be?
  400. //
  401. //
  402. // BUGBUG merge the GetFs with the code above in a seperate
  403. // routine
  404. //
  405. if (pfctProcessDir) {
  406. rc = GetFS(&fsFilesNext,
  407. pdpr->rgfSwitchs,
  408. pdpr->rgfAttribs,
  409. pdpr->rgfAttribsOnOff,
  410. pdpr->dwTimeType,
  411. pscr,
  412. pfctPrintErr,
  413. NULL
  414. );
  415. if (rc != SUCCESS) {
  416. if ((rc != ERROR_FILE_NOT_FOUND) && (rc != ERROR_NO_MORE_FILES)) {
  417. // PutStdErr(rc, NOARGS);
  418. return( rc );
  419. }
  420. }
  421. pfctProcessDir(&fsFilesNext, pcffTotal);
  422. FreeStr((PTCHAR)(fsFilesNext.pff));
  423. FreeStr((PTCHAR)(fsFilesNext.prgpff));
  424. fsFilesNext.pff = NULL;
  425. fsFilesNext.prgpff = NULL;
  426. }
  427. FreeStr(fsFilesNext.pszDir);
  428. }
  429. }
  430. //
  431. // At bottom of directory tree, free buffer holding
  432. // list of directories.
  433. //
  434. FreeStr((PTCHAR)(fsDirs.pszDir));
  435. FreeStr((PTCHAR)(fsDirs.pff));
  436. FreeStr((PTCHAR)(fsDirs.prgpff));
  437. }
  438. return(rc);
  439. }
  440. /*++
  441. Routine Description:
  442. Arguments:
  443. Return Value:
  444. Return:
  445. --*/
  446. STATUS
  447. GetFS(
  448. IN PFS pfsCur,
  449. IN ULONG rgfSwitchs,
  450. IN ULONG rgfAttribs,
  451. IN ULONG rgfAttribsOnOff,
  452. IN ULONG dwTimeType,
  453. IN PSCREEN pscr,
  454. IN BOOLEAN (*pfctPrintPatternErr) (STATUS, PTCHAR),
  455. IN STATUS (* pfctProcessFileEarly) ( PSCREEN, ULONG, ULONG, PLARGE_INTEGER, PFS, PFF )
  456. )
  457. {
  458. HANDLE hndFirst;
  459. PFF pffCur;
  460. ULONG cff = 0;
  461. ULONG cbfsLim;
  462. ULONG cbfsCur = 0;
  463. ULONG irgpffCur;
  464. ULONG cbT;
  465. PPATDSC ppatdscCur;
  466. ULONG i, rc;
  467. USHORT cbFileName, cbAlternateFileName;
  468. BOOLEAN bPrintedErr;
  469. TCHAR szSearchPath[MAX_PATH + 2];
  470. UNREFERENCED_PARAMETER( rgfSwitchs );
  471. DosErr = 0;
  472. pfsCur->pff = pffCur = (PFF)gmkstr( cbfsLim = CBFILEINC);
  473. pfsCur->cff = 0;
  474. pfsCur->cffDisplayed = 0;
  475. pfsCur->cbFileTotal.QuadPart = 0;
  476. bPrintedErr = FALSE;
  477. for(i = 1, ppatdscCur = pfsCur->ppatdsc;
  478. i <= pfsCur->cpatdsc;
  479. i++, ppatdscCur = ppatdscCur->ppatdscNext ) {
  480. //
  481. // Check immediately if a control-c was hit before
  482. // doing file I/O (which may take a long time on a slow link)
  483. //
  484. if (CtrlCSeen) {
  485. return(FAILURE);
  486. }
  487. if (mystrlen(pfsCur->pszDir) > (MAX_PATH + 2) ) {
  488. return( ERROR_BUFFER_OVERFLOW );
  489. }
  490. mystrcpy(szSearchPath, pfsCur->pszDir);
  491. /* don't append '\' if we have a current dir is D:\ */
  492. if (mystrlen(pfsCur->pszDir) != mystrlen(TEXT("D:\\")) ||
  493. szSearchPath[1] != COLON) {
  494. if ( (mystrlen(szSearchPath) + mystrlen(TEXT("\\") ) )
  495. > (MAX_PATH + 2) ) {
  496. return( ERROR_BUFFER_OVERFLOW );
  497. }
  498. mystrcat(szSearchPath, TEXT("\\"));
  499. }
  500. //DbgPrint("GetFS: searching for %s in %s\n",ppatdscCur->pszPattern,szSearchPath);
  501. if ( (mystrlen(szSearchPath) + mystrlen(ppatdscCur->pszPattern) )
  502. > (MAX_PATH + 2) ) {
  503. return( ERROR_BUFFER_OVERFLOW );
  504. }
  505. mystrcat(szSearchPath, ppatdscCur->pszPattern);
  506. if (SetSearchPath(pfsCur, ppatdscCur, szSearchPath, MAX_PATH + 2) != SUCCESS) {
  507. return( ERROR_BUFFER_OVERFLOW );
  508. }
  509. if (pfctProcessFileEarly) {
  510. //
  511. // Setting tabs to 0 forces single line output
  512. //
  513. if (pscr)
  514. SetTab(pscr, 0);
  515. if (!(rgfSwitchs & (BAREFORMATSWITCH|DELPROCESSEARLY))) {
  516. //
  517. // if it is not the bare format or del calling (no header, no tail)
  518. // then display which directory, volume etc.
  519. //
  520. CHECKSTATUS(DisplayFileListHeader(pscr, rgfSwitchs, pfsCur->pszDir ));
  521. }
  522. }
  523. //
  524. // Fetch all files since we may looking for a file with a attribute that
  525. // is not set (a non-directory etc.
  526. //
  527. if (!FindFirstNt(szSearchPath, &(pffCur->data), &hndFirst)) {
  528. if (DosErr) {
  529. if ((DosErr != ERROR_FILE_NOT_FOUND) &&
  530. (DosErr != ERROR_NO_MORE_FILES)) {
  531. return( DosErr );
  532. }
  533. //
  534. if (pfctPrintPatternErr) {
  535. bPrintedErr = TRUE;
  536. pfctPrintPatternErr(DosErr, szSearchPath);
  537. }
  538. // If doing multiple file list then keep loop till out of
  539. // patterns
  540. //
  541. if (pfsCur->cpatdsc > 1) {
  542. // if pfctPrintPatternErr is != NULL, we've been
  543. // called by del, so print an error. otherwise, we've
  544. // been called by dir.
  545. //if (pfctPrintPatternErr) {
  546. // PutStdErr(MSG_NOT_FOUND, ONEARG, szSearchPath);
  547. //}
  548. continue;
  549. } else {
  550. //if (pfctPrintPatternErr) {
  551. // PutStdErr(MSG_NOT_FOUND, ONEARG, szSearchPath);
  552. //}
  553. return( DosErr );
  554. }
  555. }
  556. } else {
  557. do {
  558. //
  559. // Check immediately if a control-c was hit before
  560. // doing file I/O (which may take a long time on a slow link)
  561. //
  562. if (CtrlCSeen) {
  563. findclose( hndFirst );
  564. return(FAILURE);
  565. }
  566. //
  567. // Before allowing this entry to be put in the list check it
  568. // for the proper attribs
  569. //
  570. // rgfAttribs is a bit mask of attribs we care to look at
  571. // rgfAttribsOnOff is the state these selected bits must be in
  572. // for them to be selected.
  573. //
  574. // IMPORTANT: both of these must be in the same bit order
  575. //
  576. //
  577. DEBUG((ICGRP, DILVL, " found %ws", pffCur->data.cFileName)) ;
  578. DEBUG((ICGRP, DILVL, " attribs %x", pffCur->data.dwFileAttributes)) ;
  579. if (!((pffCur->data.dwFileAttributes & rgfAttribs) ==
  580. (rgfAttribs & rgfAttribsOnOff) )) {
  581. continue;
  582. }
  583. //
  584. // Compute the true size of the ff entry and don't forget the zero
  585. // and the DWORD alignment factor.
  586. // Note that pffCur->cb is a USHORT to save space. The
  587. // assumption is that MAX_PATH is quite a bit less then 32k
  588. //
  589. // To compute remove the size of the filename field since it is at MAX_PATH.
  590. // also take out the size of the alternative name field
  591. // then add back in the actual size of the field plus 1 byte termination
  592. //
  593. cbFileName = (USHORT)_tcslen((pffCur->data).cFileName);
  594. cbAlternateFileName = (USHORT)_tcslen((pffCur->data).cAlternateFileName);
  595. pffCur->cb = (USHORT)((sizeof(FF) - (MAX_PATH + 14*sizeof(TCHAR))) + cbFileName + sizeof(TCHAR) );
  596. if (cbAlternateFileName) {
  597. //
  598. // cbAlternateFileName + 1 to account for zero termination
  599. //
  600. pffCur->cb += cbAlternateFileName + sizeof(TCHAR);
  601. pffCur->obAlternate = (USHORT)(cbFileName + sizeof(TCHAR));
  602. memmove(&((pffCur->data).cFileName[cbFileName + sizeof(TCHAR)]),
  603. &((pffCur->data).cAlternateFileName),
  604. (cbAlternateFileName + 1) * sizeof(TCHAR));
  605. } else {
  606. pffCur->obAlternate = 0;
  607. }
  608. //
  609. // Adjust count to align on DWORD boundaries for mips and risc
  610. // machines
  611. //
  612. pffCur->cb = (USHORT)(((pffCur->cb + sizeof(DWORD)) / sizeof(DWORD)) * sizeof(DWORD));
  613. //
  614. // Here we print out the filenames early if a 'dir'
  615. // was executed and we don't need to sort them or print
  616. // them out in any wide format.
  617. //
  618. if (pfctProcessFileEarly) {
  619. rc = (pfctProcessFileEarly)(pscr,
  620. rgfSwitchs,
  621. dwTimeType,
  622. &pfsCur->cbFileTotal,
  623. pfsCur,
  624. pffCur
  625. );
  626. if (rc == (FAILURE+1)) {
  627. findclose( hndFirst );
  628. return FAILURE;
  629. } else
  630. if (rc == FAILURE)
  631. bPrintedErr = TRUE;
  632. }
  633. if (!pfctProcessFileEarly || (pffCur->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  634. cff++;
  635. //
  636. // Update the accounting information for file buffer info.
  637. //
  638. cbfsCur += pffCur->cb;
  639. (char*)(pffCur) += pffCur->cb;
  640. //
  641. // make sure we can handle the next entry.
  642. //
  643. if ((sizeof( FF ) + sizeof(DWORD) + cbfsCur) > cbfsLim) {
  644. // cbT = cbfsCur + CBFILEINC;
  645. //
  646. // BUGBUG change this inline to a #define later.
  647. // I do not want to make a change to the .h file this
  648. // close to beta.
  649. // the 64k value is here to avoid heavy heap
  650. // fragmentation
  651. //
  652. cbT = cbfsCur + (64 * 1024);
  653. DEBUG((ICGRP, DILVL, "\t size of new pff %d", cbT ));
  654. if ((pffCur = pfsCur->pff = (PFF)resize(pfsCur->pff, cbT)) == NULL) {
  655. DEBUG((ICGRP, DILVL, "\t Could not resize pff" ));
  656. return( MSG_NO_MEMORY );
  657. }
  658. DEBUG((ICGRP, DILVL, "\t resized pffCur new value %lx", (ULONG)(pffCur))) ;
  659. //
  660. // recompute the currency of the ff pointer
  661. //
  662. pffCur = (PFF)((char*)(pfsCur->pff) + cbfsCur);
  663. //
  664. // reset the buffer size
  665. //
  666. cbfsLim = cbT;
  667. }
  668. }
  669. } while (FindNextNt(&(pffCur->data), hndFirst));
  670. findclose( hndFirst );
  671. //
  672. // BUGBUG may need to check for error on Find. here
  673. //
  674. }
  675. } // FOR
  676. //
  677. // DosErr is set in the FindNext code.
  678. // Check if we term. loop for something other then end of
  679. // file list.
  680. //
  681. if ((DosErr) && (DosErr != ERROR_NO_MORE_FILES)) {
  682. //
  683. // If not doing multiple file list then error
  684. // If multiple have failed but still have files from previous pattern
  685. //
  686. if (pfsCur->cpatdsc <= 1) {
  687. return( DosErr );
  688. }
  689. }
  690. //
  691. // if no files then do not create pointers
  692. //
  693. if (cff || pfsCur->cffDisplayed) {
  694. if (!pfctProcessFileEarly) {
  695. pfsCur->prgpff = (PPFF)gmkstr( sizeof(PFF) * (cff));
  696. pfsCur->cff = cff;
  697. pffCur = pfsCur->pff;
  698. for (irgpffCur = 0; irgpffCur < cff; irgpffCur++ ) {
  699. pfsCur->prgpff[irgpffCur] = pffCur;
  700. (char*)(pffCur) += pffCur->cb;
  701. }
  702. }
  703. return( SUCCESS);
  704. }
  705. if (!bPrintedErr) {
  706. DosErr = ERROR_FILE_NOT_FOUND;
  707. if (pfctPrintPatternErr) {
  708. pfctPrintPatternErr(DosErr, szSearchPath);
  709. }
  710. }
  711. return( DosErr );
  712. }
  713. STATUS
  714. SetSearchPath (
  715. IN PFS pfsCur,
  716. IN PPATDSC ppatdscCur,
  717. IN PTCHAR pszSearchPath,
  718. IN ULONG cSearchPath
  719. ) {
  720. if ((mystrlen(pfsCur->pszDir) +
  721. mystrlen(TEXT("\\")) +
  722. mystrlen(ppatdscCur->pszPattern) + 1) > cSearchPath) {
  723. return(ERROR_BUFFER_OVERFLOW);
  724. }
  725. mystrcpy(pszSearchPath, pfsCur->pszDir);
  726. /* don't append '\' if we have a current dir is D:\ */
  727. if (mystrlen(pfsCur->pszDir) != mystrlen(TEXT("D:\\")) ||
  728. pszSearchPath[1] != COLON) {
  729. mystrcat(pszSearchPath, TEXT("\\"));
  730. }
  731. mystrcat(pszSearchPath, ppatdscCur->pszPattern);
  732. return( SUCCESS );
  733. }