Leaked source code of windows server 2003
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.

2037 lines
74 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. Where.c
  5. Abstract:
  6. Lists the files that matches
  7. Syntax:
  8. ------
  9. WHERE [/R dir] [/Q] [/F] [/T] pattern...
  10. Author:
  11. Revision History:
  12. 25-Jan-2000 a-anurag in the 'found' function changed the printf format of the year in the date from
  13. %d to %02d and did ptm->tm_year%100 to display the right year in 2 digits.
  14. 06-Aug-1990 davegi Added check for no arguments
  15. 03-Mar-1987 danl Update usage
  16. 17-Feb-1987 BW Move strExeType to TOOLS.LIB
  17. 18-Jul-1986 DL Add /t
  18. 18-Jun-1986 DL handle *. properly
  19. Search current directory if no env specified
  20. 17-Jun-1986 DL Do look4match on Recurse and wildcards
  21. 16-Jun-1986 DL Add wild cards to $FOO:BAR, added /q
  22. 1-Jun-1986 DL Add /r, fix Match to handle pat ending with '*'
  23. 27-May-1986 MZ Add *NIX searching.
  24. 30-Jan-1998 ravisp Add /Q
  25. 02-Jul-2001 Wipro Technologies, has modified the tool for localization.
  26. /Q switch is changed to /f
  27. --*/
  28. #include "pch.h"
  29. #include "where.h"
  30. #include <strsafe.h>
  31. DWORD
  32. _cdecl wmain( IN DWORD argc,
  33. IN LPCWSTR argv[] )
  34. /*++
  35. Routine Description : This is the main routine which calls other routines
  36. for processing the options and finding the files.
  37. [ IN ] argc : A DWORD variable having the argument count.
  38. [ IN ] argv : An array of constant strings of command line options.
  39. Return Value : DWORD
  40. Returns successfully if function is success otherwise return failure.
  41. --*/
  42. {
  43. DWORD i = 0;
  44. DWORD dwStatus = 0;
  45. DWORD dwCount = 0;
  46. BOOL bQuiet = FALSE;
  47. BOOL bQuote = FALSE;
  48. BOOL bTime = FALSE;
  49. BOOL bUsage = FALSE;
  50. LPWSTR wszRecursive = NULL;
  51. LPWSTR wszPattern = NULL;
  52. TARRAY szPatternInArr = NULL;
  53. TARRAY szPatternArr = NULL;
  54. DWORD dw = 0;
  55. BOOL bFound = FALSE;
  56. LPWSTR szTemp = NULL;
  57. WCHAR *szTempPattern = NULL;
  58. BOOL *bMatched = NULL;
  59. if( argc<=1 )
  60. {
  61. SetLastError( (DWORD)MK_E_SYNTAX );
  62. SaveLastError();
  63. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  64. ShowMessage( stderr, GetResString( IDS_HELP_MESSAGE ) );
  65. ReleaseGlobals();
  66. return( EXIT_FAILURE_2 );
  67. }
  68. //this error mode is set for not to display messagebox when device is not ready
  69. SetErrorMode( SEM_FAILCRITICALERRORS);
  70. dwStatus = ProcessOptions( argc, argv,
  71. &wszRecursive,
  72. &bQuiet,
  73. &bQuote,
  74. &bTime,
  75. &szPatternInArr,
  76. &bUsage);
  77. if( EXIT_FAILURE == dwStatus )
  78. {
  79. DestroyDynamicArray(&szPatternInArr );
  80. FreeMemory((LPVOID *) &wszRecursive );
  81. ReleaseGlobals();
  82. return( EXIT_FAILURE_2 );
  83. }
  84. if( TRUE == bUsage )
  85. {
  86. DisplayHelpUsage();
  87. DestroyDynamicArray(&szPatternInArr );
  88. FreeMemory((LPVOID *) &wszRecursive );
  89. ReleaseGlobals();
  90. return(EXIT_SUCCESS);
  91. }
  92. szPatternArr = CreateDynamicArray();
  93. if( NULL == szPatternArr )
  94. {
  95. SetLastError( ERROR_OUTOFMEMORY );
  96. SaveLastError();
  97. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  98. DestroyDynamicArray(&szPatternInArr);
  99. FreeMemory((LPVOID *) &wszRecursive );
  100. ReleaseGlobals();
  101. return( EXIT_FAILURE_2 );
  102. }
  103. //check for invalid slashes
  104. dwCount = DynArrayGetCount( szPatternInArr );
  105. //fill bMatched array
  106. bMatched = (BOOL *) AllocateMemory( (dwCount+1)*sizeof(BOOL) );
  107. if( NULL == bMatched )
  108. {
  109. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  110. DestroyDynamicArray(&szPatternInArr);
  111. DestroyDynamicArray(&szPatternArr );
  112. FreeMemory((LPVOID *) &wszRecursive );
  113. ReleaseGlobals();
  114. return( EXIT_FAILURE_2 );
  115. }
  116. for(dw=0;dw<dwCount;dw++)
  117. {
  118. bMatched[dw]=FALSE;
  119. wszPattern =(LPWSTR)DynArrayItemAsString(szPatternInArr,dw);
  120. //check if / is specified in the pattern
  121. if( wszPattern[0] == '/' )
  122. {
  123. ShowMessageEx( stderr, 1, TRUE, GetResString(IDS_INVALID_ARUGUMENTS), wszPattern );
  124. ShowMessage( stderr, GetResString(IDS_HELP_MESSAGE) );
  125. DestroyDynamicArray(&szPatternInArr );
  126. DestroyDynamicArray(&szPatternArr );
  127. FreeMemory((LPVOID *) &wszRecursive );
  128. FreeMemory( (LPVOID *) &bMatched );
  129. ReleaseGlobals();
  130. return( EXIT_FAILURE_2 );
  131. }
  132. //and also check if recursive option is used with $env:path pattern
  133. if( StringLengthW(wszRecursive, 0)!=0 && wszPattern[0]==_T('$') && (szTemp = (LPWSTR)FindString( wszPattern, _T(":"),0)) != NULL )
  134. {
  135. ShowMessage( stderr, GetResString(IDS_RECURSIVE_WITH_DOLLAR) ) ;
  136. DestroyDynamicArray(&szPatternInArr );
  137. DestroyDynamicArray(&szPatternArr );
  138. FreeMemory((LPVOID *) &wszRecursive );
  139. FreeMemory( (LPVOID *) &bMatched );
  140. ReleaseGlobals();
  141. return( EXIT_FAILURE_2 );
  142. }
  143. //check if path:pattern is specified along with recursive option
  144. if( StringLengthW(wszRecursive, 0)!=0 && (szTemp = (LPWSTR)FindString( wszPattern, _T(":"),0)) != NULL )
  145. {
  146. ShowMessage( stderr, GetResString(IDS_RECURSIVE_WITH_COLON) ) ;
  147. DestroyDynamicArray(&szPatternInArr );
  148. DestroyDynamicArray(&szPatternArr );
  149. FreeMemory((LPVOID *) &wszRecursive );
  150. FreeMemory( (LPVOID *) &bMatched );
  151. ReleaseGlobals();
  152. return( EXIT_FAILURE_2 );
  153. }
  154. //check if null patterns specified in $env:pattern
  155. if( (wszPattern[0] == _T('$') && (szTemp = wcsrchr( wszPattern, L':' )) != NULL) )
  156. {
  157. //divide $env:pattern
  158. szTemp = wcsrchr( wszPattern, L':' );
  159. szTemp++;
  160. if (szTemp == NULL || StringLength( szTemp, 0) == 0)
  161. {
  162. ShowMessage(stderr, GetResString(IDS_NO_PATTERN) );
  163. DestroyDynamicArray(&szPatternInArr );
  164. DestroyDynamicArray(&szPatternArr );
  165. FreeMemory((LPVOID *) &wszRecursive );
  166. FreeMemory( (LPVOID *) &bMatched );
  167. ReleaseGlobals();
  168. return( EXIT_FAILURE_2 );
  169. }
  170. //now check whether the pattern consists of / or \s
  171. //this check was done for patterns, but not done for $env:pattern
  172. if( szTemp[0] == L'\\' || szTemp[0] == L'/' )
  173. {
  174. ShowMessage(stderr, GetResString(IDS_INVALID_PATTERN) );
  175. DestroyDynamicArray(&szPatternInArr );
  176. DestroyDynamicArray(&szPatternArr );
  177. FreeMemory((LPVOID *) &wszRecursive );
  178. FreeMemory( (LPVOID *) &bMatched );
  179. ReleaseGlobals();
  180. return EXIT_FAILURE_2;
  181. }
  182. }
  183. //check if null patterns specified in path:pattern
  184. if( (szTemp = wcsrchr( wszPattern, L':' )) != NULL )
  185. {
  186. //divide $env:pattern
  187. szTemp = wcsrchr( wszPattern, L':' );
  188. szTemp++;
  189. if ( NULL == szTemp || StringLength( szTemp, 0) == 0)
  190. {
  191. ShowMessage(stderr, GetResString(IDS_NO_PATTERN_2) );
  192. DestroyDynamicArray(&szPatternInArr );
  193. DestroyDynamicArray(&szPatternArr );
  194. FreeMemory((LPVOID *) &wszRecursive );
  195. FreeMemory( (LPVOID *) &bMatched );
  196. ReleaseGlobals();
  197. return( EXIT_FAILURE_2 );
  198. }
  199. //now check whether the pattern consists of / or \s
  200. //this check was done for patterns, but not done for $env:pattern
  201. if( szTemp[0] == L'\\' || szTemp[0] == L'/' )
  202. {
  203. ShowMessage(stderr, GetResString(IDS_INVALID_PATTERN1) );
  204. DestroyDynamicArray(&szPatternInArr );
  205. DestroyDynamicArray(&szPatternArr );
  206. FreeMemory((LPVOID *) &wszRecursive );
  207. FreeMemory( (LPVOID *) &bMatched );
  208. ReleaseGlobals();
  209. return EXIT_FAILURE_2;
  210. }
  211. }
  212. //remove off the consequtive *s in the pattern, this is because the patten matching logic
  213. //will match for the patten recursivly, so limit the unnecessary no. of recursions
  214. szTempPattern = (LPWSTR) AllocateMemory((StringLengthW(wszPattern,0)+10)*sizeof(WCHAR) );
  215. if( NULL == szTempPattern )
  216. {
  217. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  218. DestroyDynamicArray(&szPatternInArr );
  219. DestroyDynamicArray(&szPatternArr );
  220. FreeMemory((LPVOID *) &wszRecursive );
  221. FreeMemory( (LPVOID *) &bMatched );
  222. ReleaseGlobals();
  223. return( EXIT_FAILURE_2 );
  224. }
  225. SecureZeroMemory(szTempPattern, SIZE_OF_ARRAY_IN_BYTES(szTempPattern) );
  226. szTemp = wszPattern;
  227. i=0;
  228. while( *szTemp )
  229. {
  230. szTempPattern[i++] = *szTemp;
  231. if( L'*' == *szTemp )
  232. {
  233. while( L'*' == *szTemp )
  234. szTemp++;
  235. }
  236. else
  237. szTemp++;
  238. }
  239. szTempPattern[i]=0;
  240. DynArrayAppendString( szPatternArr, (LPCWSTR) szTempPattern, StringLengthW(szTempPattern, 0) );
  241. FreeMemory((LPVOID *) &szTempPattern);
  242. }
  243. //no need, destroy the dynamic array
  244. DestroyDynamicArray( &szPatternInArr );
  245. if( (NULL != wszRecursive) && StringLengthW(wszRecursive, 0) != 0 )
  246. {
  247. dwStatus = FindforFileRecursive( wszRecursive, szPatternArr, bQuiet, bQuote, bTime );
  248. if( EXIT_FAILURE == dwStatus )
  249. {
  250. //check if it fails due to memory allocation
  251. if( ERROR_NOT_ENOUGH_MEMORY == GetLastError() )
  252. {
  253. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL);
  254. ReleaseGlobals();
  255. DestroyDynamicArray( &szPatternArr );
  256. FreeMemory((LPVOID *) &wszRecursive );
  257. FreeMemory( (LPVOID *) &bMatched );
  258. ReleaseGlobals();
  259. return EXIT_FAILURE_2;
  260. }
  261. bFound = FALSE;
  262. }
  263. else
  264. bFound = TRUE;
  265. }
  266. else
  267. {
  268. //get the patterns one by one and process them
  269. for(dw=0;dw<dwCount;dw++)
  270. {
  271. SetReason(L"");
  272. wszPattern = (LPWSTR)DynArrayItemAsString(szPatternArr,dw);
  273. szTempPattern = (LPWSTR) AllocateMemory((StringLengthW(wszPattern, 0)+10)*sizeof(WCHAR) );
  274. if( NULL == szTempPattern )
  275. {
  276. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  277. FreeMemory((LPVOID *) &wszRecursive );
  278. DestroyDynamicArray( &szPatternArr );
  279. FreeMemory( (LPVOID *) &bMatched );
  280. ReleaseGlobals();
  281. return( EXIT_FAILURE_2 );
  282. }
  283. StringCopy(szTempPattern, wszPattern, SIZE_OF_ARRAY_IN_CHARS(szTempPattern));
  284. dwStatus = Where( szTempPattern, bQuiet, bQuote, bTime );
  285. if( EXIT_SUCCESS == dwStatus )
  286. {
  287. bFound = TRUE;
  288. bMatched[dw]=TRUE;
  289. }
  290. else
  291. {
  292. //check out if it fails due to outof memory
  293. if( ERROR_NOT_ENOUGH_MEMORY == GetLastError() )
  294. {
  295. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  296. ReleaseGlobals();
  297. DestroyDynamicArray( &szPatternArr );
  298. FreeMemory((LPVOID *) &wszRecursive );
  299. FreeMemory((LPVOID *) &szTempPattern);
  300. FreeMemory( (LPVOID *) &bMatched );
  301. ReleaseGlobals();
  302. return EXIT_FAILURE_2;
  303. }
  304. else //might be matching not found for this pattern
  305. {
  306. //display it only if it is not displayed earlier
  307. if( StringLengthW(GetReason(), 0) != 0 )
  308. {
  309. bMatched[dw] = TRUE;
  310. // ShowMessageEx( stderr, 2,TRUE, GetResString( IDS_NO_DATA), _X( wszPattern ) );
  311. }
  312. }
  313. }
  314. }
  315. //display non matched patterns
  316. if( bFound )
  317. {
  318. for(dw=0;dw<dwCount;dw++)
  319. {
  320. if( !bMatched[dw] && !bQuiet)
  321. {
  322. wszPattern = (LPWSTR)DynArrayItemAsString(szPatternArr,dw);
  323. ShowMessageEx( stderr, 2,TRUE, GetResString( IDS_NO_DATA), _X( wszPattern ) );
  324. }
  325. }
  326. }
  327. }
  328. if( !bFound )
  329. {
  330. if(!bQuiet)
  331. {
  332. ShowMessage( stderr, GetResString(IDS_NO_DATA1) );
  333. }
  334. DestroyDynamicArray(&szPatternArr );
  335. FreeMemory((LPVOID *) &wszRecursive );
  336. FreeMemory( (LPVOID *) &bMatched );
  337. ReleaseGlobals();
  338. return( EXIT_FAILURE );
  339. }
  340. DestroyDynamicArray(&szPatternArr );
  341. FreeMemory( (LPVOID *) &bMatched );
  342. //again set back to normal mode
  343. SetErrorMode(0);
  344. FreeMemory((LPVOID *) &wszRecursive );
  345. ReleaseGlobals();
  346. return( EXIT_SUCCESS );
  347. }
  348. DWORD
  349. Where( IN LPWSTR lpszPattern,
  350. IN BOOL bQuiet,
  351. IN BOOL bQuote,
  352. IN BOOL bTime)
  353. /*++
  354. Routine Description : This routine is to build the path in which the files that matches
  355. the given pattern are to be found.
  356. [ IN ] lpszPattern : A pattern string for which the matching files are to be found.
  357. [ IN ] lpszrecursive : A string variable having directory path along with the files
  358. mathces the pattern to be found.
  359. [ IN ] bQuiet : A boolean variable which specifies output in quiet mode or not.
  360. [ IN ] bQuote : A boolean variable which specifies to add quotes to the output or not.
  361. [ IN ] bTime : A boolean variable which specifies to display time and sizes of files or not.
  362. Return Value : DWORD
  363. Returns successfully if function is success other wise return failure.
  364. --*/
  365. {
  366. WCHAR *szTemp = NULL;
  367. LPWSTR szEnvPath = NULL;
  368. WCHAR *szTraversedPath = NULL;
  369. WCHAR *szDirectory = NULL;
  370. WCHAR *szTemp1 = NULL;
  371. DWORD dwStatus = EXIT_FAILURE;
  372. WCHAR *szEnvVar = NULL;
  373. BOOL bFound = FALSE;
  374. LPWSTR szFilePart = NULL;
  375. DWORD dwAttr = 0;
  376. DWORD dwSize = 0;
  377. LPWSTR szFullPath = NULL;
  378. LPWSTR szLongPath = NULL;
  379. LPWSTR szTempPath = NULL;
  380. BOOL bDuplicate = FALSE;
  381. BOOL bAllInvalid = TRUE;
  382. DWORD cb = 0;
  383. //return back if reverse slashes are there, because the API will consider them as part of the path
  384. if( lpszPattern[0] == L'\\' )
  385. {
  386. return EXIT_FAILURE;
  387. }
  388. //if environment variable is specified at default argument
  389. //through $ symbol find the files matches the pattern along that path
  390. if( lpszPattern[0] == _T('$') && (szTemp = wcsrchr( lpszPattern, L':' )) != NULL )
  391. {
  392. //divide $env:pattern
  393. szTemp = wcsrchr( lpszPattern, L':' );
  394. szTemp++;
  395. lpszPattern[(szTemp-1)-lpszPattern] = 0;
  396. //swap these, because lpszPattern holds environment varibale and szTemp holds pattern
  397. szTemp1 = lpszPattern;
  398. lpszPattern = szTemp;
  399. szTemp = szTemp1;
  400. StrTrim( lpszPattern, L" " );
  401. //remove off $ from environment variable
  402. szTemp++;
  403. szTemp1 = _wgetenv( szTemp );
  404. if( NULL == szTemp1 )
  405. {
  406. if( !bQuiet )
  407. {
  408. ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_ENV_VRARIABLE), _X(szTemp) );
  409. }
  410. SetReason(GetResString(IDS_ERROR_ENV_VRARIABLE));
  411. return(EXIT_FAILURE );
  412. }
  413. szEnvVar = (LPWSTR) AllocateMemory( StringLengthW(szTemp, 0)+10);
  414. if( NULL == szEnvVar )
  415. {
  416. FreeMemory( (LPVOID *) &szEnvVar );
  417. return( EXIT_FAILURE );
  418. }
  419. StringCopy( szEnvVar, szTemp, SIZE_OF_ARRAY_IN_CHARS(szEnvVar) ); //this is for display purpose
  420. szEnvPath = (WCHAR *) AllocateMemory( (StringLengthW(szTemp1, 0)+10)*sizeof(WCHAR) );
  421. if( NULL == szEnvPath )
  422. {
  423. return( EXIT_FAILURE );
  424. }
  425. StringCopy( szEnvPath, szTemp1, SIZE_OF_ARRAY_IN_CHARS(szEnvPath) );
  426. if( NULL == szEnvPath )
  427. {
  428. SetLastError( ERROR_OUTOFMEMORY );
  429. SaveLastError();
  430. FreeMemory( (LPVOID *) &szEnvVar );
  431. return( EXIT_FAILURE );
  432. }
  433. }
  434. else
  435. {
  436. if( (szTemp = wcsrchr( lpszPattern, L':' )) != NULL )
  437. {
  438. //consider it as a path
  439. //divide path:pattern structure
  440. szTemp++;
  441. lpszPattern[(szTemp-1)-lpszPattern] = 0;
  442. //swap these, because lpszPattern holds environment varibale and szTemp holds pattern
  443. szTemp1 = lpszPattern;
  444. lpszPattern = szTemp;
  445. szTemp = szTemp1;
  446. StrTrim( lpszPattern, L" " );
  447. szEnvPath = (WCHAR *) AllocateMemory( (StringLengthW(szTemp, 0)+10)*sizeof(WCHAR) );
  448. if( NULL == szEnvPath )
  449. {
  450. return( EXIT_FAILURE );
  451. }
  452. szEnvVar = (WCHAR *) AllocateMemory( (StringLengthW(szTemp, 0)+10)*sizeof(WCHAR) );
  453. if( NULL == szEnvVar )
  454. {
  455. return( EXIT_FAILURE );
  456. }
  457. StringCopy( szEnvPath, szTemp, SIZE_OF_ARRAY_IN_CHARS(szEnvPath) );
  458. StringCopy( szEnvVar, szTemp, SIZE_OF_ARRAY_IN_CHARS(szEnvPath) ); //this is for display purpose
  459. }
  460. else
  461. {
  462. //get the PATH value
  463. dwSize = GetEnvironmentVariable( L"PATH", szEnvPath, 0 );
  464. if( 0==dwSize )
  465. {
  466. if( !bQuiet )
  467. {
  468. ShowMessageEx( stderr, 1, TRUE, GetResString(IDS_ERROR_ENV_VRARIABLE), L"PATH" );
  469. }
  470. SetReason( GetResString(IDS_ERROR_ENV_VRARIABLE) );
  471. return(EXIT_FAILURE );
  472. }
  473. //this variable for display purpose
  474. szEnvVar = (WCHAR *) AllocateMemory( (StringLengthW(L"PATH",0)+1)*sizeof(WCHAR) );
  475. if( NULL == szEnvVar )
  476. {
  477. SetLastError( ERROR_OUTOFMEMORY );
  478. SaveLastError();
  479. return( EXIT_FAILURE );
  480. }
  481. StringCopy(szEnvVar, L"PATH", SIZE_OF_ARRAY_IN_CHARS(szEnvVar) );
  482. //now get the "PATH" value from environment
  483. szEnvPath = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
  484. if( NULL == szEnvPath )
  485. {
  486. FreeMemory( (LPVOID *) &szEnvPath );
  487. return( EXIT_FAILURE );
  488. }
  489. //add the current directory to the path
  490. StringCopy( szEnvPath, L".;", SIZE_OF_ARRAY_IN_CHARS(szEnvPath));
  491. if( 0==GetEnvironmentVariable( L"PATH", szEnvPath+(StringLengthW(L".",0)*sizeof(WCHAR)), dwSize ) )
  492. {
  493. if( !bQuiet )
  494. {
  495. ShowMessageEx( stderr, 1, TRUE, GetResString(IDS_ERROR_ENV_VRARIABLE), L"PATH" );
  496. }
  497. SetReason( GetResString(IDS_ERROR_ENV_VRARIABLE) );
  498. FreeMemory((LPVOID *) &szEnvPath);
  499. FreeMemory((LPVOID *) &szEnvVar);
  500. return EXIT_FAILURE;
  501. }
  502. }
  503. }
  504. //take each directory path from the variable
  505. szDirectory = _tcstok(szEnvPath, L";");
  506. while(szDirectory != NULL)
  507. {
  508. //now check the given directory is true directory or not
  509. dwAttr = GetFileAttributes( szDirectory);
  510. if( -1 == dwAttr || !(dwAttr & FILE_ATTRIBUTE_DIRECTORY) )
  511. {
  512. szDirectory = _tcstok(NULL, L";");
  513. continue;
  514. }
  515. else
  516. {
  517. bAllInvalid = FALSE; //this tells all directories in the path are not invalid
  518. }
  519. //ensure there are no duplicate directories, so far, in the path
  520. bDuplicate = FALSE;
  521. dwSize=GetFullPathName(szDirectory,
  522. 0,
  523. szFullPath,
  524. &szFilePart );
  525. if( dwSize != 0 )
  526. {
  527. szFullPath = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
  528. if( NULL == szFullPath )
  529. {
  530. FreeMemory((LPVOID *) &szEnvPath);
  531. FreeMemory((LPVOID *) &szEnvVar);
  532. return( EXIT_FAILURE );
  533. }
  534. dwSize=GetFullPathName(szDirectory,
  535. (DWORD) dwSize+5,
  536. szFullPath,
  537. &szFilePart );
  538. //get the long path name
  539. dwSize = GetLongPathName( szFullPath, szLongPath, 0 );
  540. szLongPath = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
  541. if( NULL == szLongPath )
  542. {
  543. FreeMemory((LPVOID *) &szFullPath );
  544. FreeMemory((LPVOID *) &szEnvPath);
  545. FreeMemory((LPVOID *) &szEnvVar);
  546. return( EXIT_FAILURE );
  547. }
  548. dwSize = GetLongPathName( szFullPath, szLongPath, dwSize+5 );
  549. //check if a trailing \ is there, if so suppress it because it no way affect the directory name
  550. //but could obscure another same path not having traling \ which results in duplication of paths
  551. if( (*(szLongPath+StringLengthW(szLongPath,0)-1) == _T('\\')) && (*(szLongPath+StringLengthW(szLongPath,0)-2) != _T(':')) )
  552. *(szLongPath+StringLengthW(szLongPath,0)-1) = 0;
  553. FreeMemory((LPVOID *) &szFullPath );
  554. }
  555. //check for duplicates
  556. if( szTraversedPath != NULL)
  557. {
  558. //copy already traversedpath into temporary variable and
  559. //divide it into tokens, so that by comparing eache token with
  560. //the current path will set eliminates the duplicates
  561. szTempPath = (LPWSTR) AllocateMemory( (StringLengthW(szTraversedPath,0)+10)*sizeof(WCHAR) );
  562. if( NULL == szTempPath )
  563. {
  564. FreeMemory((LPVOID*) &szEnvPath);
  565. FreeMemory((LPVOID*) &szEnvVar);
  566. FreeMemory((LPVOID*) &szTraversedPath);
  567. FreeMemory( (LPVOID*) &szLongPath );
  568. return( EXIT_FAILURE );
  569. }
  570. SecureZeroMemory( szTempPath, SIZE_OF_ARRAY_IN_BYTES(szTempPath));
  571. StringCopy(szTempPath, szTraversedPath, SIZE_OF_ARRAY_IN_CHARS(szTempPath));
  572. szTemp=DivideToken(szTempPath);
  573. while( szTemp!= NULL )
  574. {
  575. if ( StringCompare( szTemp, szLongPath, TRUE, 0 ) == 0 )
  576. {
  577. bDuplicate = TRUE;
  578. break;
  579. }
  580. szTemp=DivideToken(NULL);
  581. }
  582. FreeMemory((LPVOID *) &szTempPath);
  583. }
  584. // find for file only if directory is not in already traversed path
  585. if( !bDuplicate )
  586. {
  587. dwStatus = FindforFile( szLongPath, lpszPattern, bQuiet, bQuote, bTime );
  588. cb += StringLengthW(szLongPath,0)+10;
  589. if( NULL != szTraversedPath )
  590. {
  591. if( FALSE == ReallocateMemory( (LPVOID *)&szTraversedPath, cb*sizeof(WCHAR) ) )
  592. {
  593. FreeMemory((LPVOID*) &szTraversedPath);
  594. szTraversedPath = NULL;
  595. }
  596. }
  597. else
  598. {
  599. szTraversedPath = (LPWSTR) AllocateMemory( cb*sizeof(WCHAR) );
  600. SecureZeroMemory( szTraversedPath, SIZE_OF_ARRAY_IN_BYTES(szTraversedPath) );
  601. }
  602. if( szTraversedPath == NULL )
  603. {
  604. SaveLastError();
  605. FreeMemory((LPVOID*) &szEnvPath);
  606. FreeMemory((LPVOID*) &szEnvVar);
  607. FreeMemory((LPVOID*) &szLongPath );
  608. return( EXIT_FAILURE );
  609. }
  610. if( StringLengthW(szTraversedPath,0) == 0 )
  611. {
  612. StringCopy( szTraversedPath, szLongPath, SIZE_OF_ARRAY_IN_CHARS(szTraversedPath) );
  613. }
  614. else
  615. {
  616. StringConcat( szTraversedPath, szLongPath, SIZE_OF_ARRAY_IN_CHARS(szTraversedPath) );
  617. }
  618. StringConcat( szTraversedPath, L"*", SIZE_OF_ARRAY_IN_CHARS(szTraversedPath));
  619. }
  620. szDirectory = _tcstok(NULL, L";");
  621. if( EXIT_SUCCESS == dwStatus )
  622. {
  623. bFound = TRUE;
  624. }
  625. FreeMemory((LPVOID *) &szLongPath );
  626. }
  627. FreeMemory( (LPVOID *) &szEnvPath );
  628. FreeMemory( (LPVOID *) &szTraversedPath );
  629. FreeMemory( (LPVOID *) &szEnvVar );
  630. if( FALSE == bFound )
  631. return(EXIT_FAILURE);
  632. return( EXIT_SUCCESS );
  633. }
  634. DWORD
  635. FindforFile(IN LPWSTR lpszDirectory,
  636. IN LPWSTR lpszPattern,
  637. IN BOOL bQuiet,
  638. IN BOOL bQuote,
  639. IN BOOL bTime
  640. )
  641. /*++
  642. Routine Description : This routine is to find the files that match for the given pattern.
  643. [ IN ] lpszDirectory : A string variable having directory path along with the files
  644. mathces the pattern to be found.
  645. [ IN ] lpszPattern : A pattern string for which the matching files are to be found.
  646. [ IN ] bQuiet : A boolean variable which specifies the search is recursive or not.
  647. [ IN ] bQuiet : A boolean variable which specifies the output can be in quiet mode or not.
  648. [ IN ] bQuote : A boolean variable which specifies to add quotes to th output or not.
  649. [ IN ] bTime : A boolean variable which specifies to display time and sizes of file or not.
  650. Return Value : DWORD
  651. Returns successfully if function is success other wise return failure.
  652. --*/
  653. {
  654. HANDLE hFData;
  655. WIN32_FIND_DATA fData;
  656. LPWSTR szFilenamePattern = NULL;
  657. LPWSTR szTempPath = NULL;
  658. LPWSTR szBuffer = NULL;
  659. BOOL bFound = FALSE;
  660. LPWSTR szTemp = NULL;
  661. DWORD cb = 0;
  662. DWORD dwSize = 0;
  663. LPWSTR szPathExt = NULL;
  664. LPWSTR szTempPathExt = NULL;
  665. LPWSTR lpszTempPattern = NULL;
  666. LPWSTR szToken = NULL;
  667. //get the file extension path PATHEXT
  668. dwSize = GetEnvironmentVariable( L"PATHEXT", szPathExt, 0 );
  669. if( dwSize!=0 )
  670. {
  671. szPathExt = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
  672. if( NULL == szPathExt )
  673. {
  674. return( EXIT_FAILURE );
  675. }
  676. GetEnvironmentVariable( L"PATHEXT", szPathExt, dwSize );
  677. szTempPathExt = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
  678. if( NULL == szPathExt )
  679. {
  680. FreeMemory((LPVOID *) &szPathExt );
  681. return( EXIT_FAILURE );
  682. }
  683. }
  684. //allocate memory for file name pattern
  685. cb = StringLengthW(lpszDirectory,0)+15;
  686. szFilenamePattern = (LPWSTR)AllocateMemory( cb*sizeof(WCHAR) );
  687. if( NULL == szFilenamePattern )
  688. {
  689. FreeMemory((LPVOID *) &lpszTempPattern );
  690. FreeMemory((LPVOID *) &szTempPathExt );
  691. FreeMemory((LPVOID *) &szPathExt );
  692. return( EXIT_FAILURE );
  693. }
  694. SecureZeroMemory( szFilenamePattern, SIZE_OF_ARRAY_IN_BYTES(szFilenamePattern) );
  695. //check for trailing slash is there in the path of directory
  696. //if it is there remove it other wise add it along with the *.* pattern
  697. if( *(lpszDirectory+StringLengthW(lpszDirectory,0)-1) != _T('\\'))
  698. {
  699. StringCchPrintf( szFilenamePattern, cb-1, L"%s\\*.*", _X( lpszDirectory ) );
  700. }
  701. else
  702. {
  703. StringCchPrintf( szFilenamePattern, cb-1, L"%s*.*", _X( lpszDirectory ) );
  704. }
  705. //find first file in the directory
  706. hFData = FindFirstFileEx( szFilenamePattern,
  707. FindExInfoStandard,
  708. &fData,
  709. FindExSearchNameMatch,
  710. NULL,
  711. 0);
  712. if( INVALID_HANDLE_VALUE != hFData )
  713. {
  714. do
  715. {
  716. //allocate memory for full path of file name
  717. cb = StringLengthW(lpszDirectory,0)+StringLengthW(fData.cFileName,0)+10;
  718. szTempPath = (LPWSTR) AllocateMemory( cb*sizeof(WCHAR) );
  719. if( NULL == szTempPath )
  720. {
  721. FreeMemory((LPVOID *) &szFilenamePattern );
  722. FreeMemory((LPVOID *) &lpszTempPattern );
  723. FreeMemory((LPVOID *) &szTempPathExt );
  724. FreeMemory((LPVOID *) &szPathExt );
  725. return( EXIT_FAILURE );
  726. }
  727. SecureZeroMemory( szTempPath, cb*sizeof(WCHAR) );
  728. //get full path of file name
  729. if( *(lpszDirectory+StringLengthW(lpszDirectory,0)-1) != _T('\\'))
  730. {
  731. StringCchPrintf( szTempPath, cb, L"%s\\%s", _X( lpszDirectory ), _X2( fData.cFileName ) );
  732. }
  733. else
  734. {
  735. StringCchPrintf( szTempPath, cb, L"%s%s", _X( lpszDirectory ), _X2( fData.cFileName ) );
  736. }
  737. //check for patten matching
  738. //if file name is a directory then dont match for the pattern
  739. if( (FILE_ATTRIBUTE_DIRECTORY & fData.dwFileAttributes))
  740. {
  741. FreeMemory((LPVOID *) &szTempPath );
  742. continue;
  743. }
  744. szBuffer = (LPWSTR) AllocateMemory( (StringLengthW(fData.cFileName,0)+10)*sizeof(WCHAR) );
  745. if( NULL == szBuffer )
  746. {
  747. FreeMemory((LPVOID *) &szFilenamePattern );
  748. FreeMemory((LPVOID *) &lpszTempPattern );
  749. FreeMemory((LPVOID *) &szTempPathExt );
  750. FreeMemory((LPVOID *) &szPathExt );
  751. return( EXIT_FAILURE );
  752. }
  753. StringCopy( szBuffer, fData.cFileName, SIZE_OF_ARRAY_IN_CHARS(szBuffer) );
  754. //if pattern has dot and file doesn't have dot means search for *. type
  755. //so append . for the file
  756. if( ((szTemp=(LPWSTR)FindString((LPCWSTR)lpszPattern, _T("."),0)) != NULL) &&
  757. ((szTemp=(LPWSTR)FindString(szBuffer, _T("."),0)) == NULL) )
  758. {
  759. StringConcat(szBuffer, _T("."), SIZE_OF_ARRAY_IN_CHARS(szBuffer) );
  760. }
  761. if(Match( lpszPattern, szBuffer ))
  762. {
  763. found( szTempPath, bQuiet, bQuote, bTime );
  764. bFound = TRUE ;
  765. }
  766. else
  767. {
  768. //checkout for if extension in the EXTPATH matches
  769. StringCopy(szTempPathExt, szPathExt, SIZE_OF_ARRAY_IN_CHARS(szTempPathExt));
  770. szTemp = szTempPathExt;
  771. szToken=(LPWSTR)FindString(szTemp, L";",0);
  772. if( szToken != NULL )
  773. {
  774. szToken[0]=0;
  775. szToken = szTemp;
  776. szTemp+=StringLengthW(szTemp,0)+1;
  777. }
  778. else
  779. {
  780. szToken = szTempPathExt;
  781. szTemp = NULL;
  782. }
  783. while(szToken!=NULL )
  784. {
  785. //allocate memory for temporary pattern which can be used to check for file extensions
  786. cb = StringLengthW(lpszPattern,0)+StringLengthW(szToken,0)+25;
  787. lpszTempPattern = (LPWSTR)AllocateMemory( cb*sizeof(WCHAR) );
  788. if( NULL == lpszTempPattern )
  789. {
  790. FreeMemory((LPVOID *) &szTempPathExt );
  791. FreeMemory((LPVOID *) &szPathExt );
  792. FreeMemory((LPVOID *) &szBuffer );
  793. return( EXIT_FAILURE );
  794. }
  795. SecureZeroMemory( lpszTempPattern, SIZE_OF_ARRAY_IN_BYTES(lpszTempPattern) );
  796. if( szToken[0] == L'.' )
  797. {
  798. StringCchPrintf(lpszTempPattern, cb-1, L"%s%s",lpszPattern, szToken);
  799. if(Match( lpszTempPattern, szBuffer ))
  800. {
  801. found( szTempPath, bQuiet, bQuote, bTime );
  802. bFound = TRUE ;
  803. }
  804. }
  805. if( NULL == szTemp )
  806. {
  807. szToken = NULL;
  808. }
  809. else
  810. {
  811. szToken=(LPWSTR)FindString(szTemp, L";",0);
  812. if( szToken != NULL )
  813. {
  814. szToken[0]=0;
  815. szToken = szTemp;
  816. szTemp+=StringLengthW(szTemp,0)+1;
  817. }
  818. else
  819. {
  820. szToken = szTemp;
  821. szTemp=NULL;
  822. }
  823. }
  824. FreeMemory((LPVOID*) &lpszTempPattern );
  825. }
  826. FreeMemory( (LPVOID *) &szBuffer );
  827. }
  828. FreeMemory((LPVOID *) &szTempPath );
  829. FreeMemory( (LPVOID *) &szBuffer );
  830. }while(FindNextFile(hFData, &fData));
  831. FindClose(hFData);
  832. }
  833. FreeMemory((LPVOID *) &szFilenamePattern );
  834. FreeMemory((LPVOID *) &szTempPathExt );
  835. FreeMemory((LPVOID *) &szPathExt );
  836. if( !bFound )
  837. {
  838. return( EXIT_FAILURE );
  839. }
  840. return( EXIT_SUCCESS );
  841. }
  842. DWORD
  843. FindforFileRecursive(
  844. IN LPWSTR lpszDirectory,
  845. IN PTARRAY PatternArr,
  846. IN BOOL bQuiet,
  847. IN BOOL bQuote,
  848. IN BOOL bTime
  849. )
  850. /*++
  851. Routine Description : This routine is to find the files that match for the given pattern.
  852. [ IN ] lpszDirectory : A string variable having directory path along with the files
  853. mathces the pattern to be found.
  854. [ IN ] lpszPattern : A pattern string for which the matching files are to be found.
  855. [ IN ] bQuiet : A boolean variable which specifies the directory is to recursive or not.
  856. [ IN ] bQuiet : A boolean variable which specifies the output is in quiet mode or not.
  857. [ IN ] bQuote : A boolean variable which specifies to add quotes to the output or not.
  858. [ IN ] bTime : A boolean variable which specifies to display time and size of file or not.
  859. Return Value : DWORD
  860. Returns successfully if function is success other wise return failure.
  861. --*/
  862. {
  863. HANDLE hFData;
  864. WIN32_FIND_DATA fData;
  865. BOOL bStatus = FALSE;
  866. LPWSTR szFilenamePattern = NULL;
  867. LPWSTR szTempPath = NULL;
  868. LPWSTR szDirectoryName = NULL;
  869. LPWSTR lpszPattern = NULL;
  870. WCHAR *szBuffer = NULL;
  871. BOOL bFound = FALSE;
  872. LPWSTR szTemp = NULL;
  873. DIRECTORY dir = NULL;
  874. DIRECTORY dirNextLevel = NULL;
  875. DIRECTORY dirTemp = NULL;
  876. DWORD cb = 0;
  877. DWORD dwCount = 0;
  878. DWORD dw = 0;
  879. DWORD dwSize = 0;
  880. LPWSTR szPathExt = NULL;
  881. LPWSTR szTempPathExt = NULL;
  882. LPWSTR lpszTempPattern = NULL;
  883. LPWSTR szToken = NULL;
  884. BOOL *bMatched = NULL;
  885. //get the file extension path PATHEXT
  886. dwSize = GetEnvironmentVariable( L"PATHEXT", szPathExt, 0 );
  887. if( dwSize!=0 )
  888. {
  889. szPathExt = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
  890. if( NULL == szPathExt )
  891. {
  892. return( EXIT_FAILURE );
  893. }
  894. GetEnvironmentVariable( L"PATHEXT", szPathExt, dwSize );
  895. szTempPathExt = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
  896. if( NULL == szPathExt )
  897. {
  898. FreeMemory((LPVOID *) &szPathExt );
  899. return( EXIT_FAILURE );
  900. }
  901. }
  902. //this array of bools corresponding to each given patterns
  903. //which tells whether any file found corresponding to that pattern
  904. dwCount = DynArrayGetCount( PatternArr );
  905. bMatched = (BOOL *)AllocateMemory((dwCount+1)*sizeof(BOOL) );
  906. if(NULL == bMatched )
  907. {
  908. FreeMemory((LPVOID *) &szTempPathExt );
  909. FreeMemory((LPVOID *) &szPathExt );
  910. return (EXIT_FAILURE );
  911. }
  912. //allocate memory for directory name
  913. cb = (StringLengthW(lpszDirectory,0)+5)*sizeof(WCHAR);
  914. szDirectoryName = (LPWSTR) AllocateMemory(cb);
  915. if( NULL == szDirectoryName )
  916. {
  917. FreeMemory((LPVOID *) &szTempPathExt );
  918. FreeMemory((LPVOID *) &szPathExt );
  919. return( EXIT_FAILURE );
  920. }
  921. SecureZeroMemory( szDirectoryName, SIZE_OF_ARRAY_IN_BYTES(szDirectoryName) );
  922. StringCopy( szDirectoryName, lpszDirectory, SIZE_OF_ARRAY_IN_CHARS(szDirectoryName) );
  923. do
  924. {
  925. //allocate memory for file name pattern
  926. cb = StringLengthW(szDirectoryName,0)+15;
  927. szFilenamePattern = AllocateMemory( cb*sizeof(WCHAR) );
  928. if( NULL == szFilenamePattern )
  929. {
  930. FreeMemory((LPVOID *) &szDirectoryName );
  931. FreeMemory((LPVOID *) &szTempPathExt );
  932. FreeMemory((LPVOID *) &szPathExt );
  933. return( EXIT_FAILURE );
  934. }
  935. ZeroMemory( szFilenamePattern, cb*sizeof(WCHAR) );
  936. //check for trailing slash is there in the path of directory
  937. //if it is there remove it other wise add it along with the *.* pattern
  938. if( *(szDirectoryName+StringLengthW(szDirectoryName,0)-1) != _T('\\'))
  939. {
  940. StringCchPrintf( szFilenamePattern, cb, L"%s\\*.*", _X( szDirectoryName ) );
  941. }
  942. else
  943. {
  944. StringCchPrintf( szFilenamePattern, cb, L"%s*.*", _X( szDirectoryName ) );
  945. }
  946. //find first file in the directory
  947. hFData = FindFirstFileEx( szFilenamePattern,
  948. FindExInfoStandard,
  949. &fData,
  950. FindExSearchNameMatch,
  951. NULL,
  952. 0);
  953. if( INVALID_HANDLE_VALUE != hFData )
  954. {
  955. do
  956. {
  957. //allocate memory for full path of file name
  958. cb = StringLengthW(szDirectoryName,0)+StringLengthW(fData.cFileName,0)+10;
  959. szTempPath = (LPWSTR) AllocateMemory( cb*sizeof(WCHAR) );
  960. if( NULL == szTempPath )
  961. {
  962. FreeMemory((LPVOID *) &szDirectoryName );
  963. FreeMemory((LPVOID *) &szFilenamePattern );
  964. FreeMemory((LPVOID *) &szTempPathExt );
  965. FreeMemory((LPVOID *) &szPathExt );
  966. return( EXIT_FAILURE );
  967. }
  968. SecureZeroMemory( szTempPath, SIZE_OF_ARRAY_IN_CHARS(szTempPath) );
  969. //get full path of file name
  970. if( *(szDirectoryName+StringLengthW(szDirectoryName,0)-1) != _T('\\'))
  971. {
  972. StringCchPrintf( szTempPath, cb, L"%s\\%s", _X( szDirectoryName ), _X2( fData.cFileName ) );
  973. }
  974. else
  975. {
  976. StringCchPrintf( szTempPath, cb, L"%s%s", _X( szDirectoryName ), _X2( fData.cFileName ) );
  977. }
  978. //check if recursive is specified and file name is directory then push that into stack
  979. if( StringCompare(fData.cFileName, L".", TRUE, 0)!=0 && StringCompare(fData.cFileName, L"..", TRUE, 0)!=0 &&
  980. (FILE_ATTRIBUTE_DIRECTORY & fData.dwFileAttributes) )
  981. {
  982. //place the directory in the list which is to be recursed later
  983. if( EXIT_FAILURE == Push(&dirNextLevel, szTempPath ) )
  984. {
  985. FreeMemory((LPVOID *) &szDirectoryName );
  986. FreeMemory((LPVOID *) &szFilenamePattern );
  987. FreeMemory((LPVOID *) &szTempPath );
  988. FreeMemory((LPVOID *) &szTempPathExt );
  989. FreeMemory((LPVOID *) &szPathExt );
  990. FreeList( dir );
  991. return(EXIT_FAILURE );
  992. }
  993. //the file name is a directory so continue
  994. FreeMemory((LPVOID *) &szTempPath );
  995. continue;
  996. }
  997. else //check for patten matching
  998. {
  999. //check for patten matching
  1000. //if file name is a directory then dont match for the pattern
  1001. if( (FILE_ATTRIBUTE_DIRECTORY & fData.dwFileAttributes))
  1002. {
  1003. FreeMemory((LPVOID*) &szTempPath );
  1004. continue;
  1005. }
  1006. //check if this file is mathched with any of the patterns given
  1007. dwCount = DynArrayGetCount( PatternArr );
  1008. for(dw=0;dw<dwCount;dw++)
  1009. {
  1010. szBuffer = (LPWSTR) AllocateMemory( (StringLengthW(fData.cFileName,0)+10)*sizeof(WCHAR) );
  1011. if( NULL == szBuffer )
  1012. {
  1013. FreeMemory((LPVOID *) &szDirectoryName );
  1014. FreeMemory((LPVOID *) &szFilenamePattern );
  1015. FreeMemory((LPVOID *) &szTempPathExt );
  1016. FreeMemory((LPVOID *) &szPathExt );
  1017. FreeList(dir);
  1018. return( EXIT_FAILURE );
  1019. }
  1020. lpszPattern = (LPWSTR)DynArrayItemAsString( PatternArr, dw );
  1021. StringCopy( szBuffer, fData.cFileName, SIZE_OF_ARRAY_IN_CHARS(szBuffer) );
  1022. //if pattern has dot and file doesn't have dot means search for *. type
  1023. //so append . for the file
  1024. if( ((szTemp=(LPWSTR)FindString((LPCWSTR)lpszPattern, _T("."),0)) != NULL) &&
  1025. ((szTemp=(LPWSTR)FindString(szBuffer, _T("."),0)) == NULL) )
  1026. {
  1027. StringConcat(szBuffer, _T("."), SIZE_OF_ARRAY_IN_CHARS(szBuffer) );
  1028. }
  1029. if(Match( lpszPattern, szBuffer ))
  1030. {
  1031. found( szTempPath, bQuiet, bQuote, bTime );
  1032. bFound = TRUE ;
  1033. bMatched[dw]=TRUE;
  1034. }
  1035. else
  1036. {
  1037. //checkout for if extension in the EXTPATH matches
  1038. StringCopy(szTempPathExt, szPathExt, SIZE_OF_ARRAY_IN_CHARS(szTempPathExt));
  1039. szTemp = szTempPathExt;
  1040. szToken=(LPWSTR)FindString(szTemp, L";",0);
  1041. if( szToken != NULL )
  1042. {
  1043. szToken[0]=0;
  1044. szToken = szTemp;
  1045. szTemp+=StringLengthW(szTemp,0)+1;
  1046. }
  1047. else
  1048. {
  1049. szToken = szTempPathExt;
  1050. szTemp = NULL;
  1051. }
  1052. while(szToken!=NULL )
  1053. {
  1054. //allocate memory for temporary pattern which can be used to check for file extensions
  1055. cb = StringLengthW(lpszPattern,0)+StringLengthW(szToken,0)+25;
  1056. lpszTempPattern = AllocateMemory( cb*sizeof(WCHAR) );
  1057. if( NULL == lpszTempPattern )
  1058. {
  1059. FreeMemory((LPVOID *) &szDirectoryName );
  1060. FreeMemory((LPVOID *) &szFilenamePattern );
  1061. FreeMemory((LPVOID *) &bMatched);
  1062. FreeMemory((LPVOID *) &szTempPathExt );
  1063. FreeMemory((LPVOID *) &szPathExt );
  1064. FreeMemory((LPVOID *) &szTempPathExt );
  1065. FreeMemory((LPVOID *) &szPathExt );
  1066. FreeMemory((LPVOID *) &szBuffer );
  1067. FreeList(dir);
  1068. return( EXIT_FAILURE );
  1069. }
  1070. SecureZeroMemory( lpszTempPattern, SIZE_OF_ARRAY_IN_BYTES(lpszTempPattern) );
  1071. if( szToken[0] == L'.' ) //if the extension in PATHEXT doesn't have dot
  1072. {
  1073. StringCchPrintf(lpszTempPattern, cb, L"%s%s",lpszPattern, szToken);
  1074. if(Match( lpszTempPattern, szBuffer ))
  1075. {
  1076. found( szTempPath, bQuiet, bQuote, bTime );
  1077. bFound = TRUE ;
  1078. bMatched[dw]=TRUE;
  1079. }
  1080. }
  1081. if( NULL == szTemp )
  1082. {
  1083. szToken = NULL;
  1084. }
  1085. else
  1086. {
  1087. szToken=(LPWSTR)FindString(szTemp, L";",0);
  1088. if( szToken != NULL )
  1089. {
  1090. szToken[0]=0;
  1091. szToken = szTemp;
  1092. szTemp+=StringLengthW(szTemp,0)+1;
  1093. }
  1094. else
  1095. {
  1096. szToken = szTemp;
  1097. szTemp=NULL;
  1098. }
  1099. }
  1100. FreeMemory((LPVOID *) &lpszTempPattern );
  1101. }
  1102. }
  1103. FreeMemory((LPVOID *) &szBuffer );
  1104. }
  1105. }
  1106. FreeMemory((LPVOID *) &szTempPath );
  1107. }while(FindNextFile(hFData, &fData));
  1108. FindClose(hFData);
  1109. }
  1110. FreeMemory((LPVOID *) &szDirectoryName );
  1111. FreeMemory((LPVOID *) &szFilenamePattern );
  1112. //pop directory and do the search in that directory
  1113. //now insert Nextlevel directories in the begining of the list,
  1114. //because it is to be processed first
  1115. if( NULL == dir && dirNextLevel )
  1116. {
  1117. dir = dirNextLevel;
  1118. dirNextLevel = NULL;
  1119. }
  1120. else if( dirNextLevel )
  1121. {
  1122. dirTemp = dirNextLevel;
  1123. while( dirTemp->next && dirTemp)
  1124. dirTemp = dirTemp->next;
  1125. dirTemp->next = dir;
  1126. dir = dirNextLevel;
  1127. dirNextLevel = NULL;
  1128. dirTemp=NULL;
  1129. }
  1130. bStatus = Pop( &dir, &szDirectoryName );
  1131. }while( bStatus );
  1132. FreeMemory((LPVOID *) &lpszTempPattern );
  1133. FreeMemory((LPVOID *) &szTempPathExt );
  1134. FreeMemory((LPVOID *) &szPathExt );
  1135. FreeList(dir);
  1136. if( !bFound )
  1137. {
  1138. FreeMemory((LPVOID *) &bMatched );
  1139. return( EXIT_FAILURE );
  1140. }
  1141. //display error messages for all patterns which dont have any matched files
  1142. dwCount = DynArrayGetCount( PatternArr );
  1143. for( dw=0;dw<dwCount;dw++ )
  1144. {
  1145. if( FALSE == bMatched[dw] )
  1146. {
  1147. lpszPattern = (LPWSTR) DynArrayItemAsString( PatternArr, dw );
  1148. if( !bQuiet )
  1149. {
  1150. ShowMessageEx(stderr, 1, TRUE, GetResString( IDS_NO_DATA), _X( lpszPattern ) );
  1151. }
  1152. }
  1153. }
  1154. FreeMemory((LPVOID *) &bMatched );
  1155. return( EXIT_SUCCESS );
  1156. }
  1157. BOOL
  1158. Match(
  1159. IN LPWSTR szPat,
  1160. IN LPWSTR szFile
  1161. )
  1162. /*++
  1163. Routine Description : This routine is used to check whether file is mathced against
  1164. pattern or not.
  1165. [ IN ] szPat : A string variable pattern against which the file name to be matched.
  1166. [ IN ] szFile : A pattern string which specifies the file name to be matched.
  1167. Return Value : BOOL
  1168. Returns successfully if function is success other wise return failure.
  1169. --*/
  1170. {
  1171. switch (*szPat) {
  1172. case '\0':
  1173. return *szFile == L'\0';
  1174. case '?':
  1175. return *szFile != L'\0' && Match (szPat + 1, szFile + 1);
  1176. case '*':
  1177. do {
  1178. if (Match (szPat + 1, szFile))
  1179. return TRUE;
  1180. } while (*szFile++);
  1181. return FALSE;
  1182. default:
  1183. return towupper (*szFile) == towupper (*szPat) && Match (szPat + 1, szFile + 1);
  1184. }
  1185. }
  1186. DWORD
  1187. found(
  1188. IN LPWSTR p,
  1189. IN BOOL bQuiet,
  1190. IN BOOL bQuote,
  1191. IN BOOL bTimes
  1192. )
  1193. /*++
  1194. Routine Description : This routine is to display the file name as per the attributes specified.
  1195. [ IN ] p : A string variable having full path of file that is to be displayed.
  1196. [ IN ] bQuiet : A boolean variable which specifies the directory is to recursive or not.
  1197. [ IN ] bQuiet : A boolean variable which specifies quiet or not.
  1198. [ IN ] bQuote : A boolean variable which specifies to add quotes or not.
  1199. [ IN ] bTime : A boolean variable which specifies to times and sizes or not.
  1200. Return Value : DWORD
  1201. Returns successfully if function is success otherwise return failure.
  1202. --*/
  1203. {
  1204. WCHAR szDateBuffer[MAX_RES_STRING] = NULL_U_STRING;
  1205. WCHAR szTimeBuffer[MAX_RES_STRING] = NULL_U_STRING;
  1206. DWORD dwSize = 0;
  1207. if (!bQuiet)
  1208. {
  1209. if (bTimes)
  1210. {
  1211. if( EXIT_SUCCESS == GetFileDateTimeandSize( p, &dwSize, szDateBuffer, szTimeBuffer ) )
  1212. {
  1213. ShowMessageEx( stdout, 3, TRUE, L"% 10ld %9s %12s ", dwSize, szDateBuffer, szTimeBuffer );
  1214. }
  1215. else
  1216. {
  1217. ShowMessage( stdout, _T(" ? ? ? ") );
  1218. }
  1219. }
  1220. if (bQuote)
  1221. {
  1222. ShowMessageEx( stdout, 1, TRUE, _T("\"%s\"\n"), _X( p ) );
  1223. }
  1224. else
  1225. {
  1226. ShowMessage( stdout, _X(p) );
  1227. ShowMessage( stdout, NEW_LINE );
  1228. }
  1229. }
  1230. return( 0 );
  1231. }
  1232. DWORD
  1233. Push( OUT DIRECTORY *dir,
  1234. IN LPWSTR szPath
  1235. )
  1236. /*
  1237. Routine Description : will place the directory name in the list
  1238. [ IN ] dir : Pointer to a list of files
  1239. [ IN ] szPath : A string variable having the path to be inserted into list
  1240. Return Value : DWORD
  1241. Returns successfully if function is success otherwise return failure.
  1242. */
  1243. {
  1244. DIRECTORY tmp = NULL;
  1245. DIRECTORY tempnode = NULL;
  1246. tmp = NULL;
  1247. //create a node
  1248. tmp = (DIRECTORY) AllocateMemory( sizeof(struct dirtag) );
  1249. if( NULL == tmp )
  1250. {
  1251. return( EXIT_FAILURE );
  1252. }
  1253. tmp->szDirectoryName = (LPWSTR) AllocateMemory( (StringLengthW(szPath, 0)+10)*sizeof(WCHAR) );
  1254. if( NULL == tmp->szDirectoryName )
  1255. {
  1256. return( EXIT_FAILURE );
  1257. }
  1258. StringCopy(tmp->szDirectoryName, szPath, SIZE_OF_ARRAY_IN_CHARS(tmp->szDirectoryName) );
  1259. tmp->next = NULL;
  1260. if( NULL == *dir ) //if stack is empty
  1261. {
  1262. *dir = tmp;
  1263. return EXIT_SUCCESS;
  1264. }
  1265. for( tempnode=*dir;tempnode->next!=NULL;tempnode=tempnode->next);
  1266. tempnode->next = tmp;
  1267. return EXIT_SUCCESS;
  1268. }
  1269. BOOL Pop( IN DIRECTORY *dir,
  1270. OUT LPWSTR *lpszDirectory)
  1271. /*
  1272. Routine Description : It will pop the directory name from the stack
  1273. [ IN ] dir : Pointer to a list of files
  1274. [ IN ] lpszDirectory : A pointer to a string will have the next directory in the list
  1275. Return Value : DWORD
  1276. Returns TRUE if list is not NULL, returns FALSE otherwise
  1277. */
  1278. {
  1279. DIRECTORY tmp = *dir;
  1280. if( NULL == tmp ) //if there are no elements in stack
  1281. return FALSE;
  1282. *lpszDirectory = (LPWSTR )AllocateMemory( (StringLengthW( tmp->szDirectoryName, 0 )+10)*sizeof(WCHAR) );
  1283. if( NULL == *lpszDirectory )
  1284. {
  1285. return( EXIT_FAILURE );
  1286. }
  1287. StringCopy( *lpszDirectory, tmp->szDirectoryName, SIZE_OF_ARRAY_IN_CHARS(*lpszDirectory) );
  1288. *dir = tmp->next; //move to the next element
  1289. FreeMemory((LPVOID *) &tmp->szDirectoryName);
  1290. FreeMemory((LPVOID *) &tmp);
  1291. return( TRUE );
  1292. }
  1293. DWORD
  1294. GetFileDateTimeandSize( LPWSTR wszFileName, DWORD *dwSize, LPWSTR wszDate, LPWSTR wszTime )
  1295. /*++
  1296. Routine Description : This function gets the date and time according to system locale.
  1297. --*/
  1298. {
  1299. HANDLE hFile;
  1300. FILETIME fileLocalTime= {0,0};
  1301. SYSTEMTIME sysTime = {0,0,0,0,0,0,0,0};
  1302. LCID lcid;
  1303. BOOL bLocaleChanged = FALSE;
  1304. DWORD wBuffSize = 0;
  1305. BY_HANDLE_FILE_INFORMATION FileInfo;
  1306. struct _stat sbuf;
  1307. struct tm *ptm;
  1308. hFile = CreateFile( wszFileName, 0 ,FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS , NULL );
  1309. if ( INVALID_HANDLE_VALUE == hFile )
  1310. {
  1311. if ( _wstat(wszFileName, &sbuf) != 0 )
  1312. return EXIT_FAILURE;
  1313. ptm = localtime (&sbuf.st_mtime);
  1314. if( NULL == ptm )
  1315. return EXIT_FAILURE;
  1316. *dwSize = sbuf.st_size;
  1317. sysTime.wYear = (WORD) ptm->tm_year+1900;
  1318. sysTime.wMonth = (WORD)ptm->tm_mon+1;
  1319. sysTime.wDayOfWeek = (WORD)ptm->tm_wday;
  1320. sysTime.wDay = (WORD)ptm->tm_mday;
  1321. sysTime.wHour = (WORD)ptm->tm_hour;
  1322. sysTime.wMinute = (WORD)ptm->tm_min;
  1323. sysTime.wSecond = (WORD)ptm->tm_sec;
  1324. sysTime.wMilliseconds = (WORD)0;
  1325. }
  1326. else
  1327. {
  1328. *dwSize = GetFileSize( hFile, NULL );
  1329. if (FALSE == GetFileInformationByHandle( hFile, &FileInfo ) )
  1330. {
  1331. CloseHandle (hFile);
  1332. return EXIT_FAILURE;
  1333. }
  1334. if (FALSE == CloseHandle (hFile))
  1335. return EXIT_FAILURE;
  1336. // get the creation time
  1337. if ( FALSE == FileTimeToLocalFileTime ( &FileInfo.ftLastWriteTime, &fileLocalTime ) )
  1338. return EXIT_FAILURE;
  1339. // get the creation time
  1340. if ( FALSE == FileTimeToSystemTime ( &fileLocalTime, &sysTime ) )
  1341. return EXIT_FAILURE;
  1342. }
  1343. // verify whether console supports the current locale fully or not
  1344. lcid = GetSupportedUserLocale( &bLocaleChanged );
  1345. //Retrieve the Date
  1346. wBuffSize = GetDateFormat( lcid, 0, &sysTime,
  1347. (( bLocaleChanged == TRUE ) ? L"MM/dd/yyyy" : NULL), wszDate, MAX_RES_STRING );
  1348. if( 0 == wBuffSize )
  1349. {
  1350. SaveLastError();
  1351. return EXIT_FAILURE;
  1352. }
  1353. wBuffSize = GetTimeFormat( lcid, 0, &sysTime,
  1354. (( bLocaleChanged == TRUE ) ? L"HH:mm:ss" : NULL), wszTime, MAX_RES_STRING );
  1355. if( 0 == wBuffSize )
  1356. return EXIT_FAILURE;
  1357. return EXIT_SUCCESS;
  1358. }
  1359. DWORD DisplayHelpUsage()
  1360. /*++
  1361. Routine Description : This routine is to display the help usage.
  1362. Return Value : DWORD
  1363. Returns success.
  1364. --*/
  1365. {
  1366. DWORD dw = 0;
  1367. for(dw=IDS_MAIN_HELP_BEGIN;dw<=IDS_MAIN_HELP_END;dw++)
  1368. ShowMessage(stdout, GetResString(dw) );
  1369. return( EXIT_SUCCESS);
  1370. }
  1371. DWORD ProcessOptions( IN DWORD argc,
  1372. IN LPCWSTR argv[],
  1373. OUT LPWSTR *lpszRecursive,
  1374. OUT PBOOL pbQuiet,
  1375. OUT PBOOL pbQuote,
  1376. OUT PBOOL pbTime,
  1377. OUT PTARRAY pArrVal,
  1378. OUT PBOOL pbUsage
  1379. )
  1380. /*++
  1381. Routine Description : Function used to process the main options
  1382. Arguments:
  1383. [ in ] argc : Number of command line arguments
  1384. [ in ] argv : Array containing command line arguments
  1385. [ out ] lpszRecursive : A string varibles returns recursive directory if specified.
  1386. [ out ] pbQuiet : A pointer to boolean variable returns TRUE if Quiet option is specified.
  1387. [ out ] pbQuote : A pointer to boolean variable returns TRUE if Quote option is specified.
  1388. [ out ] pbTime : A pointer to boolean variable returns TRUE if Times option is specified.
  1389. [ out ] pArrVal : A pointer to dynamic array returns patterns specified as default options.
  1390. [ out ] pbUsage : A pointer to boolean variable returns TRUE if Usage option is specified.
  1391. Return Type : DWORD
  1392. A Integer value indicating EXIT_SUCCESS on successful parsing of
  1393. command line else EXIT_FAILURE
  1394. --*/
  1395. {
  1396. DWORD dwAttr = 0;
  1397. LPWSTR szFilePart = NULL;
  1398. WCHAR szBuffer[MAX_MAX_PATH] = NULL_STRING;
  1399. WCHAR *szBuffer1 = NULL;
  1400. LPWSTR szLongPath = NULL;
  1401. LPWSTR szFullPath = NULL;
  1402. DWORD dwSize = 0;
  1403. TCMDPARSER2 cmdOptions[6];
  1404. //Fill the structure for recursive option
  1405. StringCopyA(cmdOptions[OI_RECURSIVE].szSignature, "PARSER2", 8 );
  1406. cmdOptions[OI_RECURSIVE].dwType = CP_TYPE_TEXT;
  1407. cmdOptions[OI_RECURSIVE].dwFlags = CP2_ALLOCMEMORY | CP_VALUE_MANDATORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL; // | CP_VALUE_MANDATORY;
  1408. cmdOptions[OI_RECURSIVE].dwCount = 1;
  1409. cmdOptions[OI_RECURSIVE].dwActuals = 0;
  1410. cmdOptions[OI_RECURSIVE].pwszOptions = CMDOPTION_RECURSIVE;
  1411. cmdOptions[OI_RECURSIVE].pwszFriendlyName = NULL;
  1412. cmdOptions[OI_RECURSIVE].pwszValues = NULL;
  1413. cmdOptions[OI_RECURSIVE].pValue = NULL;
  1414. cmdOptions[OI_RECURSIVE].dwLength = 0;
  1415. cmdOptions[OI_RECURSIVE].pFunction = NULL;
  1416. cmdOptions[OI_RECURSIVE].pFunctionData = NULL;
  1417. cmdOptions[OI_RECURSIVE].dwReserved = 0;
  1418. cmdOptions[OI_RECURSIVE].pReserved1 = NULL;
  1419. cmdOptions[OI_RECURSIVE].pReserved2 = NULL;
  1420. cmdOptions[OI_RECURSIVE].pReserved3 = NULL;
  1421. //Fill the structure for Quite option
  1422. StringCopyA(cmdOptions[OI_QUITE].szSignature, "PARSER2", 8 );
  1423. cmdOptions[OI_QUITE].dwType = CP_TYPE_BOOLEAN;
  1424. cmdOptions[OI_QUITE].dwFlags = 0;
  1425. cmdOptions[OI_QUITE].dwCount = 1;
  1426. cmdOptions[OI_QUITE].dwActuals = 0;
  1427. cmdOptions[OI_QUITE].pwszOptions = CMDOPTION_QUITE;
  1428. cmdOptions[OI_QUITE].pwszFriendlyName = NULL;
  1429. cmdOptions[OI_QUITE].pwszValues = NULL;
  1430. cmdOptions[OI_QUITE].pValue = pbQuiet;
  1431. cmdOptions[OI_QUITE].dwLength = 0;
  1432. cmdOptions[OI_QUITE].pFunction = NULL;
  1433. cmdOptions[OI_QUITE].pFunctionData = NULL;
  1434. cmdOptions[OI_QUITE].dwReserved = 0;
  1435. cmdOptions[OI_QUITE].pReserved1 = NULL;
  1436. cmdOptions[OI_QUITE].pReserved2 = NULL;
  1437. cmdOptions[OI_QUITE].pReserved3 = NULL;
  1438. //Fill the structure for Quote option
  1439. StringCopyA(cmdOptions[OI_QUOTE].szSignature, "PARSER2", 8 );
  1440. cmdOptions[OI_QUOTE].dwType = CP_TYPE_BOOLEAN;
  1441. cmdOptions[OI_QUOTE].dwFlags = 0;
  1442. cmdOptions[OI_QUOTE].dwCount = 1;
  1443. cmdOptions[OI_QUOTE].dwActuals = 0;
  1444. cmdOptions[OI_QUOTE].pwszOptions = CMDOPTION_QUOTE;
  1445. cmdOptions[OI_QUOTE].pwszFriendlyName = NULL;
  1446. cmdOptions[OI_QUOTE].pwszValues = NULL;
  1447. cmdOptions[OI_QUOTE].pValue = pbQuote;
  1448. cmdOptions[OI_QUOTE].dwLength = 0;
  1449. cmdOptions[OI_QUOTE].pFunction = NULL;
  1450. cmdOptions[OI_QUOTE].pFunctionData = NULL;
  1451. cmdOptions[OI_QUOTE].dwReserved = 0;
  1452. cmdOptions[OI_QUOTE].pReserved1 = NULL;
  1453. cmdOptions[OI_QUOTE].pReserved2 = NULL;
  1454. cmdOptions[OI_QUOTE].pReserved3 = NULL;
  1455. //Fill the structure for Quite option
  1456. StringCopyA(cmdOptions[OI_TIME].szSignature, "PARSER2", 8 );
  1457. cmdOptions[OI_TIME].dwType = CP_TYPE_BOOLEAN;
  1458. cmdOptions[OI_TIME].dwFlags = 0;
  1459. cmdOptions[OI_TIME].dwCount = 1;
  1460. cmdOptions[OI_TIME].dwActuals = 0;
  1461. cmdOptions[OI_TIME].pwszOptions = CMDOPTION_TIME;
  1462. cmdOptions[OI_TIME].pwszFriendlyName = NULL;
  1463. cmdOptions[OI_TIME].pwszValues = NULL;
  1464. cmdOptions[OI_TIME].pValue = pbTime;
  1465. cmdOptions[OI_TIME].dwLength = 0;
  1466. cmdOptions[OI_TIME].pFunction = NULL;
  1467. cmdOptions[OI_TIME].pFunctionData = NULL;
  1468. cmdOptions[OI_TIME].dwReserved = 0;
  1469. cmdOptions[OI_TIME].pReserved1 = NULL;
  1470. cmdOptions[OI_TIME].pReserved2 = NULL;
  1471. cmdOptions[OI_TIME].pReserved3 = NULL;
  1472. //Fill the structure for Quite option
  1473. StringCopyA(cmdOptions[OI_USAGE].szSignature, "PARSER2", 8 );
  1474. cmdOptions[OI_USAGE].dwType = CP_TYPE_BOOLEAN;
  1475. cmdOptions[OI_USAGE].dwFlags = CP2_USAGE;
  1476. cmdOptions[OI_USAGE].dwCount = 1;
  1477. cmdOptions[OI_USAGE].dwActuals = 0;
  1478. cmdOptions[OI_USAGE].pwszOptions = CMDOPTION_USAGE;
  1479. cmdOptions[OI_USAGE].pwszFriendlyName = NULL;
  1480. cmdOptions[OI_USAGE].pwszValues = NULL;
  1481. cmdOptions[OI_USAGE].pValue = pbUsage;
  1482. cmdOptions[OI_USAGE].dwLength = 0;
  1483. cmdOptions[OI_USAGE].pFunction = NULL;
  1484. cmdOptions[OI_USAGE].pFunctionData = NULL;
  1485. cmdOptions[OI_USAGE].dwReserved = 0;
  1486. cmdOptions[OI_USAGE].pReserved1 = NULL;
  1487. cmdOptions[OI_USAGE].pReserved2 = NULL;
  1488. cmdOptions[OI_USAGE].pReserved3 = NULL;
  1489. StringCopyA(cmdOptions[OI_DEFAULT].szSignature, "PARSER2", 8 );
  1490. cmdOptions[OI_DEFAULT].dwType = CP_TYPE_TEXT;
  1491. cmdOptions[OI_DEFAULT].dwFlags =CP2_DEFAULT | CP2_MANDATORY | CP2_VALUE_MASK | CP2_MODE_ARRAY;
  1492. cmdOptions[OI_DEFAULT].dwCount = 0;
  1493. cmdOptions[OI_DEFAULT].dwActuals = 0;
  1494. cmdOptions[OI_DEFAULT].pwszOptions = CMDOPTION_DEFAULT;
  1495. cmdOptions[OI_DEFAULT].pwszFriendlyName = NULL;
  1496. cmdOptions[OI_DEFAULT].pwszValues = NULL;
  1497. cmdOptions[OI_DEFAULT].pValue = pArrVal;
  1498. cmdOptions[OI_DEFAULT].dwLength = 0;
  1499. cmdOptions[OI_DEFAULT].pFunction = NULL;
  1500. cmdOptions[OI_DEFAULT].pFunctionData = NULL;
  1501. cmdOptions[OI_DEFAULT].dwReserved = 0;
  1502. cmdOptions[OI_DEFAULT].pReserved1 = NULL;
  1503. cmdOptions[OI_DEFAULT].pReserved2 = NULL;
  1504. cmdOptions[OI_DEFAULT].pReserved3 = NULL;
  1505. *pArrVal=CreateDynamicArray();
  1506. if( NULL == *pArrVal )
  1507. {
  1508. SetLastError( ERROR_OUTOFMEMORY );
  1509. SaveLastError();
  1510. ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
  1511. return( EXIT_FAILURE );
  1512. }
  1513. //process the command line options and display error if it fails
  1514. cmdOptions[OI_DEFAULT].pValue = pArrVal;
  1515. if( DoParseParam2( argc, argv, -1, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) == FALSE )
  1516. {
  1517. ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
  1518. return( EXIT_FAILURE );
  1519. }
  1520. *lpszRecursive = cmdOptions[OI_RECURSIVE].pValue;
  1521. //if usage specified with any other value display error and return with failure
  1522. if( ( TRUE == *pbUsage ) && ( argc > 2 ) )
  1523. {
  1524. SetLastError( (DWORD)MK_E_SYNTAX );
  1525. SaveLastError();
  1526. ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
  1527. ShowMessage( stderr, GetResString( IDS_HELP_MESSAGE ) );
  1528. return( EXIT_FAILURE );
  1529. }
  1530. if( TRUE == *pbUsage )
  1531. return( EXIT_SUCCESS);
  1532. StrTrim( *lpszRecursive, L" " );
  1533. if( 0 == StringLengthW(*lpszRecursive, 0) && cmdOptions[OI_RECURSIVE].dwActuals !=0 )
  1534. {
  1535. ShowMessage( stderr, GetResString(IDS_NO_RECURSIVE) );
  1536. return( EXIT_FAILURE );
  1537. }
  1538. //check for invalid characters in the directory name
  1539. if ( (*lpszRecursive != NULL) && (szFilePart = wcspbrk(*lpszRecursive, INVALID_DIRECTORY_CHARACTERS ))!=NULL )
  1540. {
  1541. ShowMessage( stderr, GetResString(IDS_INVALID_DIRECTORY_SPECIFIED) );
  1542. return( EXIT_FAILURE );
  1543. }
  1544. //if recursive is specified check whether the given path is
  1545. //a true directory or not.
  1546. if( StringLengthW(*lpszRecursive, 0) != 0)
  1547. {
  1548. szBuffer1 = (LPWSTR) AllocateMemory( (StringLengthW(*lpszRecursive, 0)+10)*sizeof(WCHAR) );
  1549. if( NULL == szBuffer1 )
  1550. {
  1551. ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
  1552. return EXIT_FAILURE;
  1553. }
  1554. //place a copy of recursive directory name into a temporary variable to check later for consequtive dots
  1555. StringCopy( szBuffer1, *lpszRecursive, SIZE_OF_ARRAY_IN_CHARS(szBuffer1) );
  1556. //get the full path name of directory
  1557. dwSize=GetFullPathName(*lpszRecursive,
  1558. 0,
  1559. szFullPath,
  1560. &szFilePart );
  1561. if( dwSize != 0 )
  1562. {
  1563. szFullPath = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
  1564. if( NULL == szFullPath )
  1565. {
  1566. ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
  1567. FreeMemory((LPVOID *) &szBuffer1);
  1568. return( EXIT_FAILURE );
  1569. }
  1570. if( FALSE == GetFullPathName(*lpszRecursive,
  1571. dwSize,
  1572. szFullPath,
  1573. &szFilePart ) )
  1574. {
  1575. SaveLastError();
  1576. ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
  1577. FreeMemory((LPVOID *) &szBuffer1);
  1578. return EXIT_FAILURE;
  1579. }
  1580. }
  1581. else
  1582. {
  1583. SaveLastError();
  1584. ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
  1585. return EXIT_FAILURE;
  1586. }
  1587. //get the long path name
  1588. dwSize = GetLongPathName( szFullPath, szLongPath, 0 );
  1589. if( dwSize == 0 )
  1590. {
  1591. SaveLastError();
  1592. ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
  1593. FreeMemory((LPVOID *) &szBuffer1 );
  1594. FreeMemory((LPVOID *) &szFullPath);
  1595. return( EXIT_FAILURE );
  1596. }
  1597. szLongPath = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
  1598. if( NULL == szLongPath )
  1599. {
  1600. ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
  1601. FreeMemory((LPVOID *) &szBuffer1 );
  1602. FreeMemory((LPVOID *) &szFullPath);
  1603. return( EXIT_FAILURE );
  1604. }
  1605. if( FALSE == GetLongPathName( szFullPath, szLongPath, dwSize+5 ) )
  1606. {
  1607. ShowMessage(stderr,GetResString(IDS_INVALID_DIRECTORY_SPECIFIED));
  1608. FreeMemory((LPVOID *) &szBuffer1 );
  1609. FreeMemory((LPVOID *) &szFullPath);
  1610. FreeMemory((LPVOID *) &szLongPath);
  1611. return EXIT_FAILURE;
  1612. }
  1613. else
  1614. {
  1615. FreeMemory((LPVOID *) &(*lpszRecursive) );
  1616. *lpszRecursive = (LPWSTR ) AllocateMemory( (StringLengthW(szLongPath, 0)+10)*sizeof(WCHAR) );
  1617. if( NULL == *lpszRecursive )
  1618. {
  1619. ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
  1620. FreeMemory((LPVOID *) &szBuffer1 );
  1621. FreeMemory((LPVOID *) &szFullPath);
  1622. FreeMemory((LPVOID *) &szLongPath);
  1623. return( EXIT_FAILURE );
  1624. }
  1625. StringCopy( *lpszRecursive, szLongPath, SIZE_OF_ARRAY_IN_CHARS(*lpszRecursive) );
  1626. }
  1627. dwAttr = GetFileAttributes( *lpszRecursive);
  1628. if( -1 == dwAttr )
  1629. {
  1630. SaveLastError();
  1631. ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
  1632. FreeMemory((LPVOID *) &szBuffer1 );
  1633. FreeMemory((LPVOID *) &szFullPath);
  1634. FreeMemory((LPVOID *) &szLongPath);
  1635. return EXIT_FAILURE;
  1636. }
  1637. if( !(dwAttr & FILE_ATTRIBUTE_DIRECTORY) )
  1638. {
  1639. ShowMessage(stderr,GetResString(IDS_INVALID_DIRECTORY_SPECIFIED));
  1640. FreeMemory((LPVOID *) &szBuffer1 );
  1641. FreeMemory((LPVOID *) &szFullPath);
  1642. FreeMemory((LPVOID *) &szLongPath);
  1643. return EXIT_FAILURE;
  1644. }
  1645. //check if current directory is specified by more than two dots
  1646. GetCurrentDirectory(MAX_MAX_PATH, szBuffer );
  1647. StringConcat( szBuffer, L"\\", MAX_MAX_PATH );
  1648. if( StringCompare(szBuffer, *lpszRecursive, TRUE, 0) == 0 && (szFilePart=(LPWSTR)FindString( szBuffer1, L"...", 0) )!= NULL )
  1649. {
  1650. ShowMessage(stderr,GetResString(IDS_INVALID_DIRECTORY_SPECIFIED));
  1651. FreeMemory((LPVOID *) &szBuffer1 );
  1652. FreeMemory((LPVOID *) &szFullPath);
  1653. FreeMemory((LPVOID *) &szLongPath);
  1654. return EXIT_FAILURE;
  1655. }
  1656. }
  1657. return( EXIT_SUCCESS );
  1658. }
  1659. LPWSTR DivideToken( LPTSTR szString )
  1660. /*++
  1661. Routine Description : Function used to divide the string into tokens delimited by quotes or space
  1662. Arguments:
  1663. [ in ] szString : An LPTSTR string which is to parsed for quotes and spaces.
  1664. Return Type : LPWSTR
  1665. Returns the token upon successful, NULL otherwise
  1666. --*/
  1667. {
  1668. static WCHAR* str=NULL;
  1669. WCHAR* szTemp=NULL;
  1670. if( szString )
  1671. str = szString;
  1672. szTemp = str;
  1673. while( *str!=_T('*') && *str )
  1674. str++;
  1675. if( *str )
  1676. {
  1677. *str=_T('\0');
  1678. str++;
  1679. }
  1680. while( *str==_T('*') && *str )
  1681. str++;
  1682. if( szTemp[0] )
  1683. return (szTemp );
  1684. else return( NULL );
  1685. }
  1686. DWORD FreeList( DIRECTORY dir )
  1687. /*++
  1688. Routine Description : Function is used to free the linked list
  1689. Arguments:
  1690. [ in ] *dir : pointer to DIRECTORY list
  1691. Return Type : LPWSTR
  1692. Returns the EXIT_SUCCESS successful, EXIT_FAILURE otherwise
  1693. --*/
  1694. {
  1695. DIRECTORY temp;
  1696. for( temp=dir; dir; temp=dir->next )
  1697. {
  1698. FreeMemory( (LPVOID *)&temp->szDirectoryName );
  1699. FreeMemory((LPVOID*) &temp );
  1700. }
  1701. return EXIT_SUCCESS;
  1702. }