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

/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
Where.c
Abstract:
Lists the files that matches
Syntax:
------
WHERE [/R dir] [/Q] [/F] [/T] pattern...
Author:
Revision History:
25-Jan-2000 a-anurag in the 'found' function changed the printf format of the year in the date from
%d to %02d and did ptm->tm_year%100 to display the right year in 2 digits.
06-Aug-1990 davegi Added check for no arguments
03-Mar-1987 danl Update usage
17-Feb-1987 BW Move strExeType to TOOLS.LIB
18-Jul-1986 DL Add /t
18-Jun-1986 DL handle *. properly
Search current directory if no env specified
17-Jun-1986 DL Do look4match on Recurse and wildcards
16-Jun-1986 DL Add wild cards to $FOO:BAR, added /q
1-Jun-1986 DL Add /r, fix Match to handle pat ending with '*'
27-May-1986 MZ Add *NIX searching.
30-Jan-1998 ravisp Add /Q
02-Jul-2001 Wipro Technologies, has modified the tool for localization.
/Q switch is changed to /f
--*/
#include "pch.h"
#include "where.h"
#include <strsafe.h>
DWORD
_cdecl wmain( IN DWORD argc,
IN LPCWSTR argv[] )
/*++
Routine Description : This is the main routine which calls other routines
for processing the options and finding the files.
[ IN ] argc : A DWORD variable having the argument count.
[ IN ] argv : An array of constant strings of command line options.
Return Value : DWORD
Returns successfully if function is success otherwise return failure.
--*/
{
DWORD i = 0;
DWORD dwStatus = 0;
DWORD dwCount = 0;
BOOL bQuiet = FALSE;
BOOL bQuote = FALSE;
BOOL bTime = FALSE;
BOOL bUsage = FALSE;
LPWSTR wszRecursive = NULL;
LPWSTR wszPattern = NULL;
TARRAY szPatternInArr = NULL;
TARRAY szPatternArr = NULL;
DWORD dw = 0;
BOOL bFound = FALSE;
LPWSTR szTemp = NULL;
WCHAR *szTempPattern = NULL;
BOOL *bMatched = NULL;
if( argc<=1 )
{
SetLastError( (DWORD)MK_E_SYNTAX );
SaveLastError();
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
ShowMessage( stderr, GetResString( IDS_HELP_MESSAGE ) );
ReleaseGlobals();
return( EXIT_FAILURE_2 );
}
//this error mode is set for not to display messagebox when device is not ready
SetErrorMode( SEM_FAILCRITICALERRORS);
dwStatus = ProcessOptions( argc, argv,
&wszRecursive,
&bQuiet,
&bQuote,
&bTime,
&szPatternInArr,
&bUsage);
if( EXIT_FAILURE == dwStatus )
{
DestroyDynamicArray(&szPatternInArr );
FreeMemory((LPVOID *) &wszRecursive );
ReleaseGlobals();
return( EXIT_FAILURE_2 );
}
if( TRUE == bUsage )
{
DisplayHelpUsage();
DestroyDynamicArray(&szPatternInArr );
FreeMemory((LPVOID *) &wszRecursive );
ReleaseGlobals();
return(EXIT_SUCCESS);
}
szPatternArr = CreateDynamicArray();
if( NULL == szPatternArr )
{
SetLastError( ERROR_OUTOFMEMORY );
SaveLastError();
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
DestroyDynamicArray(&szPatternInArr);
FreeMemory((LPVOID *) &wszRecursive );
ReleaseGlobals();
return( EXIT_FAILURE_2 );
}
//check for invalid slashes
dwCount = DynArrayGetCount( szPatternInArr );
//fill bMatched array
bMatched = (BOOL *) AllocateMemory( (dwCount+1)*sizeof(BOOL) );
if( NULL == bMatched )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
DestroyDynamicArray(&szPatternInArr);
DestroyDynamicArray(&szPatternArr );
FreeMemory((LPVOID *) &wszRecursive );
ReleaseGlobals();
return( EXIT_FAILURE_2 );
}
for(dw=0;dw<dwCount;dw++)
{
bMatched[dw]=FALSE;
wszPattern =(LPWSTR)DynArrayItemAsString(szPatternInArr,dw);
//check if / is specified in the pattern
if( wszPattern[0] == '/' )
{
ShowMessageEx( stderr, 1, TRUE, GetResString(IDS_INVALID_ARUGUMENTS), wszPattern );
ShowMessage( stderr, GetResString(IDS_HELP_MESSAGE) );
DestroyDynamicArray(&szPatternInArr );
DestroyDynamicArray(&szPatternArr );
FreeMemory((LPVOID *) &wszRecursive );
FreeMemory( (LPVOID *) &bMatched );
ReleaseGlobals();
return( EXIT_FAILURE_2 );
}
//and also check if recursive option is used with $env:path pattern
if( StringLengthW(wszRecursive, 0)!=0 && wszPattern[0]==_T('$') && (szTemp = (LPWSTR)FindString( wszPattern, _T(":"),0)) != NULL )
{
ShowMessage( stderr, GetResString(IDS_RECURSIVE_WITH_DOLLAR) ) ;
DestroyDynamicArray(&szPatternInArr );
DestroyDynamicArray(&szPatternArr );
FreeMemory((LPVOID *) &wszRecursive );
FreeMemory( (LPVOID *) &bMatched );
ReleaseGlobals();
return( EXIT_FAILURE_2 );
}
//check if path:pattern is specified along with recursive option
if( StringLengthW(wszRecursive, 0)!=0 && (szTemp = (LPWSTR)FindString( wszPattern, _T(":"),0)) != NULL )
{
ShowMessage( stderr, GetResString(IDS_RECURSIVE_WITH_COLON) ) ;
DestroyDynamicArray(&szPatternInArr );
DestroyDynamicArray(&szPatternArr );
FreeMemory((LPVOID *) &wszRecursive );
FreeMemory( (LPVOID *) &bMatched );
ReleaseGlobals();
return( EXIT_FAILURE_2 );
}
//check if null patterns specified in $env:pattern
if( (wszPattern[0] == _T('$') && (szTemp = wcsrchr( wszPattern, L':' )) != NULL) )
{
//divide $env:pattern
szTemp = wcsrchr( wszPattern, L':' );
szTemp++;
if (szTemp == NULL || StringLength( szTemp, 0) == 0)
{
ShowMessage(stderr, GetResString(IDS_NO_PATTERN) );
DestroyDynamicArray(&szPatternInArr );
DestroyDynamicArray(&szPatternArr );
FreeMemory((LPVOID *) &wszRecursive );
FreeMemory( (LPVOID *) &bMatched );
ReleaseGlobals();
return( EXIT_FAILURE_2 );
}
//now check whether the pattern consists of / or \s
//this check was done for patterns, but not done for $env:pattern
if( szTemp[0] == L'\\' || szTemp[0] == L'/' )
{
ShowMessage(stderr, GetResString(IDS_INVALID_PATTERN) );
DestroyDynamicArray(&szPatternInArr );
DestroyDynamicArray(&szPatternArr );
FreeMemory((LPVOID *) &wszRecursive );
FreeMemory( (LPVOID *) &bMatched );
ReleaseGlobals();
return EXIT_FAILURE_2;
}
}
//check if null patterns specified in path:pattern
if( (szTemp = wcsrchr( wszPattern, L':' )) != NULL )
{
//divide $env:pattern
szTemp = wcsrchr( wszPattern, L':' );
szTemp++;
if ( NULL == szTemp || StringLength( szTemp, 0) == 0)
{
ShowMessage(stderr, GetResString(IDS_NO_PATTERN_2) );
DestroyDynamicArray(&szPatternInArr );
DestroyDynamicArray(&szPatternArr );
FreeMemory((LPVOID *) &wszRecursive );
FreeMemory( (LPVOID *) &bMatched );
ReleaseGlobals();
return( EXIT_FAILURE_2 );
}
//now check whether the pattern consists of / or \s
//this check was done for patterns, but not done for $env:pattern
if( szTemp[0] == L'\\' || szTemp[0] == L'/' )
{
ShowMessage(stderr, GetResString(IDS_INVALID_PATTERN1) );
DestroyDynamicArray(&szPatternInArr );
DestroyDynamicArray(&szPatternArr );
FreeMemory((LPVOID *) &wszRecursive );
FreeMemory( (LPVOID *) &bMatched );
ReleaseGlobals();
return EXIT_FAILURE_2;
}
}
//remove off the consequtive *s in the pattern, this is because the patten matching logic
//will match for the patten recursivly, so limit the unnecessary no. of recursions
szTempPattern = (LPWSTR) AllocateMemory((StringLengthW(wszPattern,0)+10)*sizeof(WCHAR) );
if( NULL == szTempPattern )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
DestroyDynamicArray(&szPatternInArr );
DestroyDynamicArray(&szPatternArr );
FreeMemory((LPVOID *) &wszRecursive );
FreeMemory( (LPVOID *) &bMatched );
ReleaseGlobals();
return( EXIT_FAILURE_2 );
}
SecureZeroMemory(szTempPattern, SIZE_OF_ARRAY_IN_BYTES(szTempPattern) );
szTemp = wszPattern;
i=0;
while( *szTemp )
{
szTempPattern[i++] = *szTemp;
if( L'*' == *szTemp )
{
while( L'*' == *szTemp )
szTemp++;
}
else
szTemp++;
}
szTempPattern[i]=0;
DynArrayAppendString( szPatternArr, (LPCWSTR) szTempPattern, StringLengthW(szTempPattern, 0) );
FreeMemory((LPVOID *) &szTempPattern);
}
//no need, destroy the dynamic array
DestroyDynamicArray( &szPatternInArr );
if( (NULL != wszRecursive) && StringLengthW(wszRecursive, 0) != 0 )
{
dwStatus = FindforFileRecursive( wszRecursive, szPatternArr, bQuiet, bQuote, bTime );
if( EXIT_FAILURE == dwStatus )
{
//check if it fails due to memory allocation
if( ERROR_NOT_ENOUGH_MEMORY == GetLastError() )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL);
ReleaseGlobals();
DestroyDynamicArray( &szPatternArr );
FreeMemory((LPVOID *) &wszRecursive );
FreeMemory( (LPVOID *) &bMatched );
ReleaseGlobals();
return EXIT_FAILURE_2;
}
bFound = FALSE;
}
else
bFound = TRUE;
}
else
{
//get the patterns one by one and process them
for(dw=0;dw<dwCount;dw++)
{
SetReason(L"");
wszPattern = (LPWSTR)DynArrayItemAsString(szPatternArr,dw);
szTempPattern = (LPWSTR) AllocateMemory((StringLengthW(wszPattern, 0)+10)*sizeof(WCHAR) );
if( NULL == szTempPattern )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
FreeMemory((LPVOID *) &wszRecursive );
DestroyDynamicArray( &szPatternArr );
FreeMemory( (LPVOID *) &bMatched );
ReleaseGlobals();
return( EXIT_FAILURE_2 );
}
StringCopy(szTempPattern, wszPattern, SIZE_OF_ARRAY_IN_CHARS(szTempPattern));
dwStatus = Where( szTempPattern, bQuiet, bQuote, bTime );
if( EXIT_SUCCESS == dwStatus )
{
bFound = TRUE;
bMatched[dw]=TRUE;
}
else
{
//check out if it fails due to outof memory
if( ERROR_NOT_ENOUGH_MEMORY == GetLastError() )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
ReleaseGlobals();
DestroyDynamicArray( &szPatternArr );
FreeMemory((LPVOID *) &wszRecursive );
FreeMemory((LPVOID *) &szTempPattern);
FreeMemory( (LPVOID *) &bMatched );
ReleaseGlobals();
return EXIT_FAILURE_2;
}
else //might be matching not found for this pattern
{
//display it only if it is not displayed earlier
if( StringLengthW(GetReason(), 0) != 0 )
{
bMatched[dw] = TRUE;
// ShowMessageEx( stderr, 2,TRUE, GetResString( IDS_NO_DATA), _X( wszPattern ) );
}
}
}
}
//display non matched patterns
if( bFound )
{
for(dw=0;dw<dwCount;dw++)
{
if( !bMatched[dw] && !bQuiet)
{
wszPattern = (LPWSTR)DynArrayItemAsString(szPatternArr,dw);
ShowMessageEx( stderr, 2,TRUE, GetResString( IDS_NO_DATA), _X( wszPattern ) );
}
}
}
}
if( !bFound )
{
if(!bQuiet)
{
ShowMessage( stderr, GetResString(IDS_NO_DATA1) );
}
DestroyDynamicArray(&szPatternArr );
FreeMemory((LPVOID *) &wszRecursive );
FreeMemory( (LPVOID *) &bMatched );
ReleaseGlobals();
return( EXIT_FAILURE );
}
DestroyDynamicArray(&szPatternArr );
FreeMemory( (LPVOID *) &bMatched );
//again set back to normal mode
SetErrorMode(0);
FreeMemory((LPVOID *) &wszRecursive );
ReleaseGlobals();
return( EXIT_SUCCESS );
}
DWORD
Where( IN LPWSTR lpszPattern,
IN BOOL bQuiet,
IN BOOL bQuote,
IN BOOL bTime)
/*++
Routine Description : This routine is to build the path in which the files that matches
the given pattern are to be found.
[ IN ] lpszPattern : A pattern string for which the matching files are to be found.
[ IN ] lpszrecursive : A string variable having directory path along with the files
mathces the pattern to be found.
[ IN ] bQuiet : A boolean variable which specifies output in quiet mode or not.
[ IN ] bQuote : A boolean variable which specifies to add quotes to the output or not.
[ IN ] bTime : A boolean variable which specifies to display time and sizes of files or not.
Return Value : DWORD
Returns successfully if function is success other wise return failure.
--*/
{
WCHAR *szTemp = NULL;
LPWSTR szEnvPath = NULL;
WCHAR *szTraversedPath = NULL;
WCHAR *szDirectory = NULL;
WCHAR *szTemp1 = NULL;
DWORD dwStatus = EXIT_FAILURE;
WCHAR *szEnvVar = NULL;
BOOL bFound = FALSE;
LPWSTR szFilePart = NULL;
DWORD dwAttr = 0;
DWORD dwSize = 0;
LPWSTR szFullPath = NULL;
LPWSTR szLongPath = NULL;
LPWSTR szTempPath = NULL;
BOOL bDuplicate = FALSE;
BOOL bAllInvalid = TRUE;
DWORD cb = 0;
//return back if reverse slashes are there, because the API will consider them as part of the path
if( lpszPattern[0] == L'\\' )
{
return EXIT_FAILURE;
}
//if environment variable is specified at default argument
//through $ symbol find the files matches the pattern along that path
if( lpszPattern[0] == _T('$') && (szTemp = wcsrchr( lpszPattern, L':' )) != NULL )
{
//divide $env:pattern
szTemp = wcsrchr( lpszPattern, L':' );
szTemp++;
lpszPattern[(szTemp-1)-lpszPattern] = 0;
//swap these, because lpszPattern holds environment varibale and szTemp holds pattern
szTemp1 = lpszPattern;
lpszPattern = szTemp;
szTemp = szTemp1;
StrTrim( lpszPattern, L" " );
//remove off $ from environment variable
szTemp++;
szTemp1 = _wgetenv( szTemp );
if( NULL == szTemp1 )
{
if( !bQuiet )
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_ENV_VRARIABLE), _X(szTemp) );
}
SetReason(GetResString(IDS_ERROR_ENV_VRARIABLE));
return(EXIT_FAILURE );
}
szEnvVar = (LPWSTR) AllocateMemory( StringLengthW(szTemp, 0)+10);
if( NULL == szEnvVar )
{
FreeMemory( (LPVOID *) &szEnvVar );
return( EXIT_FAILURE );
}
StringCopy( szEnvVar, szTemp, SIZE_OF_ARRAY_IN_CHARS(szEnvVar) ); //this is for display purpose
szEnvPath = (WCHAR *) AllocateMemory( (StringLengthW(szTemp1, 0)+10)*sizeof(WCHAR) );
if( NULL == szEnvPath )
{
return( EXIT_FAILURE );
}
StringCopy( szEnvPath, szTemp1, SIZE_OF_ARRAY_IN_CHARS(szEnvPath) );
if( NULL == szEnvPath )
{
SetLastError( ERROR_OUTOFMEMORY );
SaveLastError();
FreeMemory( (LPVOID *) &szEnvVar );
return( EXIT_FAILURE );
}
}
else
{
if( (szTemp = wcsrchr( lpszPattern, L':' )) != NULL )
{
//consider it as a path
//divide path:pattern structure
szTemp++;
lpszPattern[(szTemp-1)-lpszPattern] = 0;
//swap these, because lpszPattern holds environment varibale and szTemp holds pattern
szTemp1 = lpszPattern;
lpszPattern = szTemp;
szTemp = szTemp1;
StrTrim( lpszPattern, L" " );
szEnvPath = (WCHAR *) AllocateMemory( (StringLengthW(szTemp, 0)+10)*sizeof(WCHAR) );
if( NULL == szEnvPath )
{
return( EXIT_FAILURE );
}
szEnvVar = (WCHAR *) AllocateMemory( (StringLengthW(szTemp, 0)+10)*sizeof(WCHAR) );
if( NULL == szEnvVar )
{
return( EXIT_FAILURE );
}
StringCopy( szEnvPath, szTemp, SIZE_OF_ARRAY_IN_CHARS(szEnvPath) );
StringCopy( szEnvVar, szTemp, SIZE_OF_ARRAY_IN_CHARS(szEnvPath) ); //this is for display purpose
}
else
{
//get the PATH value
dwSize = GetEnvironmentVariable( L"PATH", szEnvPath, 0 );
if( 0==dwSize )
{
if( !bQuiet )
{
ShowMessageEx( stderr, 1, TRUE, GetResString(IDS_ERROR_ENV_VRARIABLE), L"PATH" );
}
SetReason( GetResString(IDS_ERROR_ENV_VRARIABLE) );
return(EXIT_FAILURE );
}
//this variable for display purpose
szEnvVar = (WCHAR *) AllocateMemory( (StringLengthW(L"PATH",0)+1)*sizeof(WCHAR) );
if( NULL == szEnvVar )
{
SetLastError( ERROR_OUTOFMEMORY );
SaveLastError();
return( EXIT_FAILURE );
}
StringCopy(szEnvVar, L"PATH", SIZE_OF_ARRAY_IN_CHARS(szEnvVar) );
//now get the "PATH" value from environment
szEnvPath = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
if( NULL == szEnvPath )
{
FreeMemory( (LPVOID *) &szEnvPath );
return( EXIT_FAILURE );
}
//add the current directory to the path
StringCopy( szEnvPath, L".;", SIZE_OF_ARRAY_IN_CHARS(szEnvPath));
if( 0==GetEnvironmentVariable( L"PATH", szEnvPath+(StringLengthW(L".",0)*sizeof(WCHAR)), dwSize ) )
{
if( !bQuiet )
{
ShowMessageEx( stderr, 1, TRUE, GetResString(IDS_ERROR_ENV_VRARIABLE), L"PATH" );
}
SetReason( GetResString(IDS_ERROR_ENV_VRARIABLE) );
FreeMemory((LPVOID *) &szEnvPath);
FreeMemory((LPVOID *) &szEnvVar);
return EXIT_FAILURE;
}
}
}
//take each directory path from the variable
szDirectory = _tcstok(szEnvPath, L";");
while(szDirectory != NULL)
{
//now check the given directory is true directory or not
dwAttr = GetFileAttributes( szDirectory);
if( -1 == dwAttr || !(dwAttr & FILE_ATTRIBUTE_DIRECTORY) )
{
szDirectory = _tcstok(NULL, L";");
continue;
}
else
{
bAllInvalid = FALSE; //this tells all directories in the path are not invalid
}
//ensure there are no duplicate directories, so far, in the path
bDuplicate = FALSE;
dwSize=GetFullPathName(szDirectory,
0,
szFullPath,
&szFilePart );
if( dwSize != 0 )
{
szFullPath = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
if( NULL == szFullPath )
{
FreeMemory((LPVOID *) &szEnvPath);
FreeMemory((LPVOID *) &szEnvVar);
return( EXIT_FAILURE );
}
dwSize=GetFullPathName(szDirectory,
(DWORD) dwSize+5,
szFullPath,
&szFilePart );
//get the long path name
dwSize = GetLongPathName( szFullPath, szLongPath, 0 );
szLongPath = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
if( NULL == szLongPath )
{
FreeMemory((LPVOID *) &szFullPath );
FreeMemory((LPVOID *) &szEnvPath);
FreeMemory((LPVOID *) &szEnvVar);
return( EXIT_FAILURE );
}
dwSize = GetLongPathName( szFullPath, szLongPath, dwSize+5 );
//check if a trailing \ is there, if so suppress it because it no way affect the directory name
//but could obscure another same path not having traling \ which results in duplication of paths
if( (*(szLongPath+StringLengthW(szLongPath,0)-1) == _T('\\')) && (*(szLongPath+StringLengthW(szLongPath,0)-2) != _T(':')) )
*(szLongPath+StringLengthW(szLongPath,0)-1) = 0;
FreeMemory((LPVOID *) &szFullPath );
}
//check for duplicates
if( szTraversedPath != NULL)
{
//copy already traversedpath into temporary variable and
//divide it into tokens, so that by comparing eache token with
//the current path will set eliminates the duplicates
szTempPath = (LPWSTR) AllocateMemory( (StringLengthW(szTraversedPath,0)+10)*sizeof(WCHAR) );
if( NULL == szTempPath )
{
FreeMemory((LPVOID*) &szEnvPath);
FreeMemory((LPVOID*) &szEnvVar);
FreeMemory((LPVOID*) &szTraversedPath);
FreeMemory( (LPVOID*) &szLongPath );
return( EXIT_FAILURE );
}
SecureZeroMemory( szTempPath, SIZE_OF_ARRAY_IN_BYTES(szTempPath));
StringCopy(szTempPath, szTraversedPath, SIZE_OF_ARRAY_IN_CHARS(szTempPath));
szTemp=DivideToken(szTempPath);
while( szTemp!= NULL )
{
if ( StringCompare( szTemp, szLongPath, TRUE, 0 ) == 0 )
{
bDuplicate = TRUE;
break;
}
szTemp=DivideToken(NULL);
}
FreeMemory((LPVOID *) &szTempPath);
}
// find for file only if directory is not in already traversed path
if( !bDuplicate )
{
dwStatus = FindforFile( szLongPath, lpszPattern, bQuiet, bQuote, bTime );
cb += StringLengthW(szLongPath,0)+10;
if( NULL != szTraversedPath )
{
if( FALSE == ReallocateMemory( (LPVOID *)&szTraversedPath, cb*sizeof(WCHAR) ) )
{
FreeMemory((LPVOID*) &szTraversedPath);
szTraversedPath = NULL;
}
}
else
{
szTraversedPath = (LPWSTR) AllocateMemory( cb*sizeof(WCHAR) );
SecureZeroMemory( szTraversedPath, SIZE_OF_ARRAY_IN_BYTES(szTraversedPath) );
}
if( szTraversedPath == NULL )
{
SaveLastError();
FreeMemory((LPVOID*) &szEnvPath);
FreeMemory((LPVOID*) &szEnvVar);
FreeMemory((LPVOID*) &szLongPath );
return( EXIT_FAILURE );
}
if( StringLengthW(szTraversedPath,0) == 0 )
{
StringCopy( szTraversedPath, szLongPath, SIZE_OF_ARRAY_IN_CHARS(szTraversedPath) );
}
else
{
StringConcat( szTraversedPath, szLongPath, SIZE_OF_ARRAY_IN_CHARS(szTraversedPath) );
}
StringConcat( szTraversedPath, L"*", SIZE_OF_ARRAY_IN_CHARS(szTraversedPath));
}
szDirectory = _tcstok(NULL, L";");
if( EXIT_SUCCESS == dwStatus )
{
bFound = TRUE;
}
FreeMemory((LPVOID *) &szLongPath );
}
FreeMemory( (LPVOID *) &szEnvPath );
FreeMemory( (LPVOID *) &szTraversedPath );
FreeMemory( (LPVOID *) &szEnvVar );
if( FALSE == bFound )
return(EXIT_FAILURE);
return( EXIT_SUCCESS );
}
DWORD
FindforFile(IN LPWSTR lpszDirectory,
IN LPWSTR lpszPattern,
IN BOOL bQuiet,
IN BOOL bQuote,
IN BOOL bTime
)
/*++
Routine Description : This routine is to find the files that match for the given pattern.
[ IN ] lpszDirectory : A string variable having directory path along with the files
mathces the pattern to be found.
[ IN ] lpszPattern : A pattern string for which the matching files are to be found.
[ IN ] bQuiet : A boolean variable which specifies the search is recursive or not.
[ IN ] bQuiet : A boolean variable which specifies the output can be in quiet mode or not.
[ IN ] bQuote : A boolean variable which specifies to add quotes to th output or not.
[ IN ] bTime : A boolean variable which specifies to display time and sizes of file or not.
Return Value : DWORD
Returns successfully if function is success other wise return failure.
--*/
{
HANDLE hFData;
WIN32_FIND_DATA fData;
LPWSTR szFilenamePattern = NULL;
LPWSTR szTempPath = NULL;
LPWSTR szBuffer = NULL;
BOOL bFound = FALSE;
LPWSTR szTemp = NULL;
DWORD cb = 0;
DWORD dwSize = 0;
LPWSTR szPathExt = NULL;
LPWSTR szTempPathExt = NULL;
LPWSTR lpszTempPattern = NULL;
LPWSTR szToken = NULL;
//get the file extension path PATHEXT
dwSize = GetEnvironmentVariable( L"PATHEXT", szPathExt, 0 );
if( dwSize!=0 )
{
szPathExt = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
if( NULL == szPathExt )
{
return( EXIT_FAILURE );
}
GetEnvironmentVariable( L"PATHEXT", szPathExt, dwSize );
szTempPathExt = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
if( NULL == szPathExt )
{
FreeMemory((LPVOID *) &szPathExt );
return( EXIT_FAILURE );
}
}
//allocate memory for file name pattern
cb = StringLengthW(lpszDirectory,0)+15;
szFilenamePattern = (LPWSTR)AllocateMemory( cb*sizeof(WCHAR) );
if( NULL == szFilenamePattern )
{
FreeMemory((LPVOID *) &lpszTempPattern );
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
return( EXIT_FAILURE );
}
SecureZeroMemory( szFilenamePattern, SIZE_OF_ARRAY_IN_BYTES(szFilenamePattern) );
//check for trailing slash is there in the path of directory
//if it is there remove it other wise add it along with the *.* pattern
if( *(lpszDirectory+StringLengthW(lpszDirectory,0)-1) != _T('\\'))
{
StringCchPrintf( szFilenamePattern, cb-1, L"%s\\*.*", _X( lpszDirectory ) );
}
else
{
StringCchPrintf( szFilenamePattern, cb-1, L"%s*.*", _X( lpszDirectory ) );
}
//find first file in the directory
hFData = FindFirstFileEx( szFilenamePattern,
FindExInfoStandard,
&fData,
FindExSearchNameMatch,
NULL,
0);
if( INVALID_HANDLE_VALUE != hFData )
{
do
{
//allocate memory for full path of file name
cb = StringLengthW(lpszDirectory,0)+StringLengthW(fData.cFileName,0)+10;
szTempPath = (LPWSTR) AllocateMemory( cb*sizeof(WCHAR) );
if( NULL == szTempPath )
{
FreeMemory((LPVOID *) &szFilenamePattern );
FreeMemory((LPVOID *) &lpszTempPattern );
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
return( EXIT_FAILURE );
}
SecureZeroMemory( szTempPath, cb*sizeof(WCHAR) );
//get full path of file name
if( *(lpszDirectory+StringLengthW(lpszDirectory,0)-1) != _T('\\'))
{
StringCchPrintf( szTempPath, cb, L"%s\\%s", _X( lpszDirectory ), _X2( fData.cFileName ) );
}
else
{
StringCchPrintf( szTempPath, cb, L"%s%s", _X( lpszDirectory ), _X2( fData.cFileName ) );
}
//check for patten matching
//if file name is a directory then dont match for the pattern
if( (FILE_ATTRIBUTE_DIRECTORY & fData.dwFileAttributes))
{
FreeMemory((LPVOID *) &szTempPath );
continue;
}
szBuffer = (LPWSTR) AllocateMemory( (StringLengthW(fData.cFileName,0)+10)*sizeof(WCHAR) );
if( NULL == szBuffer )
{
FreeMemory((LPVOID *) &szFilenamePattern );
FreeMemory((LPVOID *) &lpszTempPattern );
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
return( EXIT_FAILURE );
}
StringCopy( szBuffer, fData.cFileName, SIZE_OF_ARRAY_IN_CHARS(szBuffer) );
//if pattern has dot and file doesn't have dot means search for *. type
//so append . for the file
if( ((szTemp=(LPWSTR)FindString((LPCWSTR)lpszPattern, _T("."),0)) != NULL) &&
((szTemp=(LPWSTR)FindString(szBuffer, _T("."),0)) == NULL) )
{
StringConcat(szBuffer, _T("."), SIZE_OF_ARRAY_IN_CHARS(szBuffer) );
}
if(Match( lpszPattern, szBuffer ))
{
found( szTempPath, bQuiet, bQuote, bTime );
bFound = TRUE ;
}
else
{
//checkout for if extension in the EXTPATH matches
StringCopy(szTempPathExt, szPathExt, SIZE_OF_ARRAY_IN_CHARS(szTempPathExt));
szTemp = szTempPathExt;
szToken=(LPWSTR)FindString(szTemp, L";",0);
if( szToken != NULL )
{
szToken[0]=0;
szToken = szTemp;
szTemp+=StringLengthW(szTemp,0)+1;
}
else
{
szToken = szTempPathExt;
szTemp = NULL;
}
while(szToken!=NULL )
{
//allocate memory for temporary pattern which can be used to check for file extensions
cb = StringLengthW(lpszPattern,0)+StringLengthW(szToken,0)+25;
lpszTempPattern = (LPWSTR)AllocateMemory( cb*sizeof(WCHAR) );
if( NULL == lpszTempPattern )
{
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
FreeMemory((LPVOID *) &szBuffer );
return( EXIT_FAILURE );
}
SecureZeroMemory( lpszTempPattern, SIZE_OF_ARRAY_IN_BYTES(lpszTempPattern) );
if( szToken[0] == L'.' )
{
StringCchPrintf(lpszTempPattern, cb-1, L"%s%s",lpszPattern, szToken);
if(Match( lpszTempPattern, szBuffer ))
{
found( szTempPath, bQuiet, bQuote, bTime );
bFound = TRUE ;
}
}
if( NULL == szTemp )
{
szToken = NULL;
}
else
{
szToken=(LPWSTR)FindString(szTemp, L";",0);
if( szToken != NULL )
{
szToken[0]=0;
szToken = szTemp;
szTemp+=StringLengthW(szTemp,0)+1;
}
else
{
szToken = szTemp;
szTemp=NULL;
}
}
FreeMemory((LPVOID*) &lpszTempPattern );
}
FreeMemory( (LPVOID *) &szBuffer );
}
FreeMemory((LPVOID *) &szTempPath );
FreeMemory( (LPVOID *) &szBuffer );
}while(FindNextFile(hFData, &fData));
FindClose(hFData);
}
FreeMemory((LPVOID *) &szFilenamePattern );
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
if( !bFound )
{
return( EXIT_FAILURE );
}
return( EXIT_SUCCESS );
}
DWORD
FindforFileRecursive(
IN LPWSTR lpszDirectory,
IN PTARRAY PatternArr,
IN BOOL bQuiet,
IN BOOL bQuote,
IN BOOL bTime
)
/*++
Routine Description : This routine is to find the files that match for the given pattern.
[ IN ] lpszDirectory : A string variable having directory path along with the files
mathces the pattern to be found.
[ IN ] lpszPattern : A pattern string for which the matching files are to be found.
[ IN ] bQuiet : A boolean variable which specifies the directory is to recursive or not.
[ IN ] bQuiet : A boolean variable which specifies the output is in quiet mode or not.
[ IN ] bQuote : A boolean variable which specifies to add quotes to the output or not.
[ IN ] bTime : A boolean variable which specifies to display time and size of file or not.
Return Value : DWORD
Returns successfully if function is success other wise return failure.
--*/
{
HANDLE hFData;
WIN32_FIND_DATA fData;
BOOL bStatus = FALSE;
LPWSTR szFilenamePattern = NULL;
LPWSTR szTempPath = NULL;
LPWSTR szDirectoryName = NULL;
LPWSTR lpszPattern = NULL;
WCHAR *szBuffer = NULL;
BOOL bFound = FALSE;
LPWSTR szTemp = NULL;
DIRECTORY dir = NULL;
DIRECTORY dirNextLevel = NULL;
DIRECTORY dirTemp = NULL;
DWORD cb = 0;
DWORD dwCount = 0;
DWORD dw = 0;
DWORD dwSize = 0;
LPWSTR szPathExt = NULL;
LPWSTR szTempPathExt = NULL;
LPWSTR lpszTempPattern = NULL;
LPWSTR szToken = NULL;
BOOL *bMatched = NULL;
//get the file extension path PATHEXT
dwSize = GetEnvironmentVariable( L"PATHEXT", szPathExt, 0 );
if( dwSize!=0 )
{
szPathExt = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
if( NULL == szPathExt )
{
return( EXIT_FAILURE );
}
GetEnvironmentVariable( L"PATHEXT", szPathExt, dwSize );
szTempPathExt = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
if( NULL == szPathExt )
{
FreeMemory((LPVOID *) &szPathExt );
return( EXIT_FAILURE );
}
}
//this array of bools corresponding to each given patterns
//which tells whether any file found corresponding to that pattern
dwCount = DynArrayGetCount( PatternArr );
bMatched = (BOOL *)AllocateMemory((dwCount+1)*sizeof(BOOL) );
if(NULL == bMatched )
{
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
return (EXIT_FAILURE );
}
//allocate memory for directory name
cb = (StringLengthW(lpszDirectory,0)+5)*sizeof(WCHAR);
szDirectoryName = (LPWSTR) AllocateMemory(cb);
if( NULL == szDirectoryName )
{
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
return( EXIT_FAILURE );
}
SecureZeroMemory( szDirectoryName, SIZE_OF_ARRAY_IN_BYTES(szDirectoryName) );
StringCopy( szDirectoryName, lpszDirectory, SIZE_OF_ARRAY_IN_CHARS(szDirectoryName) );
do
{
//allocate memory for file name pattern
cb = StringLengthW(szDirectoryName,0)+15;
szFilenamePattern = AllocateMemory( cb*sizeof(WCHAR) );
if( NULL == szFilenamePattern )
{
FreeMemory((LPVOID *) &szDirectoryName );
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
return( EXIT_FAILURE );
}
ZeroMemory( szFilenamePattern, cb*sizeof(WCHAR) );
//check for trailing slash is there in the path of directory
//if it is there remove it other wise add it along with the *.* pattern
if( *(szDirectoryName+StringLengthW(szDirectoryName,0)-1) != _T('\\'))
{
StringCchPrintf( szFilenamePattern, cb, L"%s\\*.*", _X( szDirectoryName ) );
}
else
{
StringCchPrintf( szFilenamePattern, cb, L"%s*.*", _X( szDirectoryName ) );
}
//find first file in the directory
hFData = FindFirstFileEx( szFilenamePattern,
FindExInfoStandard,
&fData,
FindExSearchNameMatch,
NULL,
0);
if( INVALID_HANDLE_VALUE != hFData )
{
do
{
//allocate memory for full path of file name
cb = StringLengthW(szDirectoryName,0)+StringLengthW(fData.cFileName,0)+10;
szTempPath = (LPWSTR) AllocateMemory( cb*sizeof(WCHAR) );
if( NULL == szTempPath )
{
FreeMemory((LPVOID *) &szDirectoryName );
FreeMemory((LPVOID *) &szFilenamePattern );
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
return( EXIT_FAILURE );
}
SecureZeroMemory( szTempPath, SIZE_OF_ARRAY_IN_CHARS(szTempPath) );
//get full path of file name
if( *(szDirectoryName+StringLengthW(szDirectoryName,0)-1) != _T('\\'))
{
StringCchPrintf( szTempPath, cb, L"%s\\%s", _X( szDirectoryName ), _X2( fData.cFileName ) );
}
else
{
StringCchPrintf( szTempPath, cb, L"%s%s", _X( szDirectoryName ), _X2( fData.cFileName ) );
}
//check if recursive is specified and file name is directory then push that into stack
if( StringCompare(fData.cFileName, L".", TRUE, 0)!=0 && StringCompare(fData.cFileName, L"..", TRUE, 0)!=0 &&
(FILE_ATTRIBUTE_DIRECTORY & fData.dwFileAttributes) )
{
//place the directory in the list which is to be recursed later
if( EXIT_FAILURE == Push(&dirNextLevel, szTempPath ) )
{
FreeMemory((LPVOID *) &szDirectoryName );
FreeMemory((LPVOID *) &szFilenamePattern );
FreeMemory((LPVOID *) &szTempPath );
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
FreeList( dir );
return(EXIT_FAILURE );
}
//the file name is a directory so continue
FreeMemory((LPVOID *) &szTempPath );
continue;
}
else //check for patten matching
{
//check for patten matching
//if file name is a directory then dont match for the pattern
if( (FILE_ATTRIBUTE_DIRECTORY & fData.dwFileAttributes))
{
FreeMemory((LPVOID*) &szTempPath );
continue;
}
//check if this file is mathched with any of the patterns given
dwCount = DynArrayGetCount( PatternArr );
for(dw=0;dw<dwCount;dw++)
{
szBuffer = (LPWSTR) AllocateMemory( (StringLengthW(fData.cFileName,0)+10)*sizeof(WCHAR) );
if( NULL == szBuffer )
{
FreeMemory((LPVOID *) &szDirectoryName );
FreeMemory((LPVOID *) &szFilenamePattern );
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
FreeList(dir);
return( EXIT_FAILURE );
}
lpszPattern = (LPWSTR)DynArrayItemAsString( PatternArr, dw );
StringCopy( szBuffer, fData.cFileName, SIZE_OF_ARRAY_IN_CHARS(szBuffer) );
//if pattern has dot and file doesn't have dot means search for *. type
//so append . for the file
if( ((szTemp=(LPWSTR)FindString((LPCWSTR)lpszPattern, _T("."),0)) != NULL) &&
((szTemp=(LPWSTR)FindString(szBuffer, _T("."),0)) == NULL) )
{
StringConcat(szBuffer, _T("."), SIZE_OF_ARRAY_IN_CHARS(szBuffer) );
}
if(Match( lpszPattern, szBuffer ))
{
found( szTempPath, bQuiet, bQuote, bTime );
bFound = TRUE ;
bMatched[dw]=TRUE;
}
else
{
//checkout for if extension in the EXTPATH matches
StringCopy(szTempPathExt, szPathExt, SIZE_OF_ARRAY_IN_CHARS(szTempPathExt));
szTemp = szTempPathExt;
szToken=(LPWSTR)FindString(szTemp, L";",0);
if( szToken != NULL )
{
szToken[0]=0;
szToken = szTemp;
szTemp+=StringLengthW(szTemp,0)+1;
}
else
{
szToken = szTempPathExt;
szTemp = NULL;
}
while(szToken!=NULL )
{
//allocate memory for temporary pattern which can be used to check for file extensions
cb = StringLengthW(lpszPattern,0)+StringLengthW(szToken,0)+25;
lpszTempPattern = AllocateMemory( cb*sizeof(WCHAR) );
if( NULL == lpszTempPattern )
{
FreeMemory((LPVOID *) &szDirectoryName );
FreeMemory((LPVOID *) &szFilenamePattern );
FreeMemory((LPVOID *) &bMatched);
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
FreeMemory((LPVOID *) &szBuffer );
FreeList(dir);
return( EXIT_FAILURE );
}
SecureZeroMemory( lpszTempPattern, SIZE_OF_ARRAY_IN_BYTES(lpszTempPattern) );
if( szToken[0] == L'.' ) //if the extension in PATHEXT doesn't have dot
{
StringCchPrintf(lpszTempPattern, cb, L"%s%s",lpszPattern, szToken);
if(Match( lpszTempPattern, szBuffer ))
{
found( szTempPath, bQuiet, bQuote, bTime );
bFound = TRUE ;
bMatched[dw]=TRUE;
}
}
if( NULL == szTemp )
{
szToken = NULL;
}
else
{
szToken=(LPWSTR)FindString(szTemp, L";",0);
if( szToken != NULL )
{
szToken[0]=0;
szToken = szTemp;
szTemp+=StringLengthW(szTemp,0)+1;
}
else
{
szToken = szTemp;
szTemp=NULL;
}
}
FreeMemory((LPVOID *) &lpszTempPattern );
}
}
FreeMemory((LPVOID *) &szBuffer );
}
}
FreeMemory((LPVOID *) &szTempPath );
}while(FindNextFile(hFData, &fData));
FindClose(hFData);
}
FreeMemory((LPVOID *) &szDirectoryName );
FreeMemory((LPVOID *) &szFilenamePattern );
//pop directory and do the search in that directory
//now insert Nextlevel directories in the begining of the list,
//because it is to be processed first
if( NULL == dir && dirNextLevel )
{
dir = dirNextLevel;
dirNextLevel = NULL;
}
else if( dirNextLevel )
{
dirTemp = dirNextLevel;
while( dirTemp->next && dirTemp)
dirTemp = dirTemp->next;
dirTemp->next = dir;
dir = dirNextLevel;
dirNextLevel = NULL;
dirTemp=NULL;
}
bStatus = Pop( &dir, &szDirectoryName );
}while( bStatus );
FreeMemory((LPVOID *) &lpszTempPattern );
FreeMemory((LPVOID *) &szTempPathExt );
FreeMemory((LPVOID *) &szPathExt );
FreeList(dir);
if( !bFound )
{
FreeMemory((LPVOID *) &bMatched );
return( EXIT_FAILURE );
}
//display error messages for all patterns which dont have any matched files
dwCount = DynArrayGetCount( PatternArr );
for( dw=0;dw<dwCount;dw++ )
{
if( FALSE == bMatched[dw] )
{
lpszPattern = (LPWSTR) DynArrayItemAsString( PatternArr, dw );
if( !bQuiet )
{
ShowMessageEx(stderr, 1, TRUE, GetResString( IDS_NO_DATA), _X( lpszPattern ) );
}
}
}
FreeMemory((LPVOID *) &bMatched );
return( EXIT_SUCCESS );
}
BOOL
Match(
IN LPWSTR szPat,
IN LPWSTR szFile
)
/*++
Routine Description : This routine is used to check whether file is mathced against
pattern or not.
[ IN ] szPat : A string variable pattern against which the file name to be matched.
[ IN ] szFile : A pattern string which specifies the file name to be matched.
Return Value : BOOL
Returns successfully if function is success other wise return failure.
--*/
{
switch (*szPat) {
case '\0':
return *szFile == L'\0';
case '?':
return *szFile != L'\0' && Match (szPat + 1, szFile + 1);
case '*':
do {
if (Match (szPat + 1, szFile))
return TRUE;
} while (*szFile++);
return FALSE;
default:
return towupper (*szFile) == towupper (*szPat) && Match (szPat + 1, szFile + 1);
}
}
DWORD
found(
IN LPWSTR p,
IN BOOL bQuiet,
IN BOOL bQuote,
IN BOOL bTimes
)
/*++
Routine Description : This routine is to display the file name as per the attributes specified.
[ IN ] p : A string variable having full path of file that is to be displayed.
[ IN ] bQuiet : A boolean variable which specifies the directory is to recursive or not.
[ IN ] bQuiet : A boolean variable which specifies quiet or not.
[ IN ] bQuote : A boolean variable which specifies to add quotes or not.
[ IN ] bTime : A boolean variable which specifies to times and sizes or not.
Return Value : DWORD
Returns successfully if function is success otherwise return failure.
--*/
{
WCHAR szDateBuffer[MAX_RES_STRING] = NULL_U_STRING;
WCHAR szTimeBuffer[MAX_RES_STRING] = NULL_U_STRING;
DWORD dwSize = 0;
if (!bQuiet)
{
if (bTimes)
{
if( EXIT_SUCCESS == GetFileDateTimeandSize( p, &dwSize, szDateBuffer, szTimeBuffer ) )
{
ShowMessageEx( stdout, 3, TRUE, L"% 10ld %9s %12s ", dwSize, szDateBuffer, szTimeBuffer );
}
else
{
ShowMessage( stdout, _T(" ? ? ? ") );
}
}
if (bQuote)
{
ShowMessageEx( stdout, 1, TRUE, _T("\"%s\"\n"), _X( p ) );
}
else
{
ShowMessage( stdout, _X(p) );
ShowMessage( stdout, NEW_LINE );
}
}
return( 0 );
}
DWORD
Push( OUT DIRECTORY *dir,
IN LPWSTR szPath
)
/*
Routine Description : will place the directory name in the list
[ IN ] dir : Pointer to a list of files
[ IN ] szPath : A string variable having the path to be inserted into list
Return Value : DWORD
Returns successfully if function is success otherwise return failure.
*/
{
DIRECTORY tmp = NULL;
DIRECTORY tempnode = NULL;
tmp = NULL;
//create a node
tmp = (DIRECTORY) AllocateMemory( sizeof(struct dirtag) );
if( NULL == tmp )
{
return( EXIT_FAILURE );
}
tmp->szDirectoryName = (LPWSTR) AllocateMemory( (StringLengthW(szPath, 0)+10)*sizeof(WCHAR) );
if( NULL == tmp->szDirectoryName )
{
return( EXIT_FAILURE );
}
StringCopy(tmp->szDirectoryName, szPath, SIZE_OF_ARRAY_IN_CHARS(tmp->szDirectoryName) );
tmp->next = NULL;
if( NULL == *dir ) //if stack is empty
{
*dir = tmp;
return EXIT_SUCCESS;
}
for( tempnode=*dir;tempnode->next!=NULL;tempnode=tempnode->next);
tempnode->next = tmp;
return EXIT_SUCCESS;
}
BOOL Pop( IN DIRECTORY *dir,
OUT LPWSTR *lpszDirectory)
/*
Routine Description : It will pop the directory name from the stack
[ IN ] dir : Pointer to a list of files
[ IN ] lpszDirectory : A pointer to a string will have the next directory in the list
Return Value : DWORD
Returns TRUE if list is not NULL, returns FALSE otherwise
*/
{
DIRECTORY tmp = *dir;
if( NULL == tmp ) //if there are no elements in stack
return FALSE;
*lpszDirectory = (LPWSTR )AllocateMemory( (StringLengthW( tmp->szDirectoryName, 0 )+10)*sizeof(WCHAR) );
if( NULL == *lpszDirectory )
{
return( EXIT_FAILURE );
}
StringCopy( *lpszDirectory, tmp->szDirectoryName, SIZE_OF_ARRAY_IN_CHARS(*lpszDirectory) );
*dir = tmp->next; //move to the next element
FreeMemory((LPVOID *) &tmp->szDirectoryName);
FreeMemory((LPVOID *) &tmp);
return( TRUE );
}
DWORD
GetFileDateTimeandSize( LPWSTR wszFileName, DWORD *dwSize, LPWSTR wszDate, LPWSTR wszTime )
/*++
Routine Description : This function gets the date and time according to system locale.
--*/
{
HANDLE hFile;
FILETIME fileLocalTime= {0,0};
SYSTEMTIME sysTime = {0,0,0,0,0,0,0,0};
LCID lcid;
BOOL bLocaleChanged = FALSE;
DWORD wBuffSize = 0;
BY_HANDLE_FILE_INFORMATION FileInfo;
struct _stat sbuf;
struct tm *ptm;
hFile = CreateFile( wszFileName, 0 ,FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS , NULL );
if ( INVALID_HANDLE_VALUE == hFile )
{
if ( _wstat(wszFileName, &sbuf) != 0 )
return EXIT_FAILURE;
ptm = localtime (&sbuf.st_mtime);
if( NULL == ptm )
return EXIT_FAILURE;
*dwSize = sbuf.st_size;
sysTime.wYear = (WORD) ptm->tm_year+1900;
sysTime.wMonth = (WORD)ptm->tm_mon+1;
sysTime.wDayOfWeek = (WORD)ptm->tm_wday;
sysTime.wDay = (WORD)ptm->tm_mday;
sysTime.wHour = (WORD)ptm->tm_hour;
sysTime.wMinute = (WORD)ptm->tm_min;
sysTime.wSecond = (WORD)ptm->tm_sec;
sysTime.wMilliseconds = (WORD)0;
}
else
{
*dwSize = GetFileSize( hFile, NULL );
if (FALSE == GetFileInformationByHandle( hFile, &FileInfo ) )
{
CloseHandle (hFile);
return EXIT_FAILURE;
}
if (FALSE == CloseHandle (hFile))
return EXIT_FAILURE;
// get the creation time
if ( FALSE == FileTimeToLocalFileTime ( &FileInfo.ftLastWriteTime, &fileLocalTime ) )
return EXIT_FAILURE;
// get the creation time
if ( FALSE == FileTimeToSystemTime ( &fileLocalTime, &sysTime ) )
return EXIT_FAILURE;
}
// verify whether console supports the current locale fully or not
lcid = GetSupportedUserLocale( &bLocaleChanged );
//Retrieve the Date
wBuffSize = GetDateFormat( lcid, 0, &sysTime,
(( bLocaleChanged == TRUE ) ? L"MM/dd/yyyy" : NULL), wszDate, MAX_RES_STRING );
if( 0 == wBuffSize )
{
SaveLastError();
return EXIT_FAILURE;
}
wBuffSize = GetTimeFormat( lcid, 0, &sysTime,
(( bLocaleChanged == TRUE ) ? L"HH:mm:ss" : NULL), wszTime, MAX_RES_STRING );
if( 0 == wBuffSize )
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
DWORD DisplayHelpUsage()
/*++
Routine Description : This routine is to display the help usage.
Return Value : DWORD
Returns success.
--*/
{
DWORD dw = 0;
for(dw=IDS_MAIN_HELP_BEGIN;dw<=IDS_MAIN_HELP_END;dw++)
ShowMessage(stdout, GetResString(dw) );
return( EXIT_SUCCESS);
}
DWORD ProcessOptions( IN DWORD argc,
IN LPCWSTR argv[],
OUT LPWSTR *lpszRecursive,
OUT PBOOL pbQuiet,
OUT PBOOL pbQuote,
OUT PBOOL pbTime,
OUT PTARRAY pArrVal,
OUT PBOOL pbUsage
)
/*++
Routine Description : Function used to process the main options
Arguments:
[ in ] argc : Number of command line arguments
[ in ] argv : Array containing command line arguments
[ out ] lpszRecursive : A string varibles returns recursive directory if specified.
[ out ] pbQuiet : A pointer to boolean variable returns TRUE if Quiet option is specified.
[ out ] pbQuote : A pointer to boolean variable returns TRUE if Quote option is specified.
[ out ] pbTime : A pointer to boolean variable returns TRUE if Times option is specified.
[ out ] pArrVal : A pointer to dynamic array returns patterns specified as default options.
[ out ] pbUsage : A pointer to boolean variable returns TRUE if Usage option is specified.
Return Type : DWORD
A Integer value indicating EXIT_SUCCESS on successful parsing of
command line else EXIT_FAILURE
--*/
{
DWORD dwAttr = 0;
LPWSTR szFilePart = NULL;
WCHAR szBuffer[MAX_MAX_PATH] = NULL_STRING;
WCHAR *szBuffer1 = NULL;
LPWSTR szLongPath = NULL;
LPWSTR szFullPath = NULL;
DWORD dwSize = 0;
TCMDPARSER2 cmdOptions[6];
//Fill the structure for recursive option
StringCopyA(cmdOptions[OI_RECURSIVE].szSignature, "PARSER2", 8 );
cmdOptions[OI_RECURSIVE].dwType = CP_TYPE_TEXT;
cmdOptions[OI_RECURSIVE].dwFlags = CP2_ALLOCMEMORY | CP_VALUE_MANDATORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL; // | CP_VALUE_MANDATORY;
cmdOptions[OI_RECURSIVE].dwCount = 1;
cmdOptions[OI_RECURSIVE].dwActuals = 0;
cmdOptions[OI_RECURSIVE].pwszOptions = CMDOPTION_RECURSIVE;
cmdOptions[OI_RECURSIVE].pwszFriendlyName = NULL;
cmdOptions[OI_RECURSIVE].pwszValues = NULL;
cmdOptions[OI_RECURSIVE].pValue = NULL;
cmdOptions[OI_RECURSIVE].dwLength = 0;
cmdOptions[OI_RECURSIVE].pFunction = NULL;
cmdOptions[OI_RECURSIVE].pFunctionData = NULL;
cmdOptions[OI_RECURSIVE].dwReserved = 0;
cmdOptions[OI_RECURSIVE].pReserved1 = NULL;
cmdOptions[OI_RECURSIVE].pReserved2 = NULL;
cmdOptions[OI_RECURSIVE].pReserved3 = NULL;
//Fill the structure for Quite option
StringCopyA(cmdOptions[OI_QUITE].szSignature, "PARSER2", 8 );
cmdOptions[OI_QUITE].dwType = CP_TYPE_BOOLEAN;
cmdOptions[OI_QUITE].dwFlags = 0;
cmdOptions[OI_QUITE].dwCount = 1;
cmdOptions[OI_QUITE].dwActuals = 0;
cmdOptions[OI_QUITE].pwszOptions = CMDOPTION_QUITE;
cmdOptions[OI_QUITE].pwszFriendlyName = NULL;
cmdOptions[OI_QUITE].pwszValues = NULL;
cmdOptions[OI_QUITE].pValue = pbQuiet;
cmdOptions[OI_QUITE].dwLength = 0;
cmdOptions[OI_QUITE].pFunction = NULL;
cmdOptions[OI_QUITE].pFunctionData = NULL;
cmdOptions[OI_QUITE].dwReserved = 0;
cmdOptions[OI_QUITE].pReserved1 = NULL;
cmdOptions[OI_QUITE].pReserved2 = NULL;
cmdOptions[OI_QUITE].pReserved3 = NULL;
//Fill the structure for Quote option
StringCopyA(cmdOptions[OI_QUOTE].szSignature, "PARSER2", 8 );
cmdOptions[OI_QUOTE].dwType = CP_TYPE_BOOLEAN;
cmdOptions[OI_QUOTE].dwFlags = 0;
cmdOptions[OI_QUOTE].dwCount = 1;
cmdOptions[OI_QUOTE].dwActuals = 0;
cmdOptions[OI_QUOTE].pwszOptions = CMDOPTION_QUOTE;
cmdOptions[OI_QUOTE].pwszFriendlyName = NULL;
cmdOptions[OI_QUOTE].pwszValues = NULL;
cmdOptions[OI_QUOTE].pValue = pbQuote;
cmdOptions[OI_QUOTE].dwLength = 0;
cmdOptions[OI_QUOTE].pFunction = NULL;
cmdOptions[OI_QUOTE].pFunctionData = NULL;
cmdOptions[OI_QUOTE].dwReserved = 0;
cmdOptions[OI_QUOTE].pReserved1 = NULL;
cmdOptions[OI_QUOTE].pReserved2 = NULL;
cmdOptions[OI_QUOTE].pReserved3 = NULL;
//Fill the structure for Quite option
StringCopyA(cmdOptions[OI_TIME].szSignature, "PARSER2", 8 );
cmdOptions[OI_TIME].dwType = CP_TYPE_BOOLEAN;
cmdOptions[OI_TIME].dwFlags = 0;
cmdOptions[OI_TIME].dwCount = 1;
cmdOptions[OI_TIME].dwActuals = 0;
cmdOptions[OI_TIME].pwszOptions = CMDOPTION_TIME;
cmdOptions[OI_TIME].pwszFriendlyName = NULL;
cmdOptions[OI_TIME].pwszValues = NULL;
cmdOptions[OI_TIME].pValue = pbTime;
cmdOptions[OI_TIME].dwLength = 0;
cmdOptions[OI_TIME].pFunction = NULL;
cmdOptions[OI_TIME].pFunctionData = NULL;
cmdOptions[OI_TIME].dwReserved = 0;
cmdOptions[OI_TIME].pReserved1 = NULL;
cmdOptions[OI_TIME].pReserved2 = NULL;
cmdOptions[OI_TIME].pReserved3 = NULL;
//Fill the structure for Quite option
StringCopyA(cmdOptions[OI_USAGE].szSignature, "PARSER2", 8 );
cmdOptions[OI_USAGE].dwType = CP_TYPE_BOOLEAN;
cmdOptions[OI_USAGE].dwFlags = CP2_USAGE;
cmdOptions[OI_USAGE].dwCount = 1;
cmdOptions[OI_USAGE].dwActuals = 0;
cmdOptions[OI_USAGE].pwszOptions = CMDOPTION_USAGE;
cmdOptions[OI_USAGE].pwszFriendlyName = NULL;
cmdOptions[OI_USAGE].pwszValues = NULL;
cmdOptions[OI_USAGE].pValue = pbUsage;
cmdOptions[OI_USAGE].dwLength = 0;
cmdOptions[OI_USAGE].pFunction = NULL;
cmdOptions[OI_USAGE].pFunctionData = NULL;
cmdOptions[OI_USAGE].dwReserved = 0;
cmdOptions[OI_USAGE].pReserved1 = NULL;
cmdOptions[OI_USAGE].pReserved2 = NULL;
cmdOptions[OI_USAGE].pReserved3 = NULL;
StringCopyA(cmdOptions[OI_DEFAULT].szSignature, "PARSER2", 8 );
cmdOptions[OI_DEFAULT].dwType = CP_TYPE_TEXT;
cmdOptions[OI_DEFAULT].dwFlags =CP2_DEFAULT | CP2_MANDATORY | CP2_VALUE_MASK | CP2_MODE_ARRAY;
cmdOptions[OI_DEFAULT].dwCount = 0;
cmdOptions[OI_DEFAULT].dwActuals = 0;
cmdOptions[OI_DEFAULT].pwszOptions = CMDOPTION_DEFAULT;
cmdOptions[OI_DEFAULT].pwszFriendlyName = NULL;
cmdOptions[OI_DEFAULT].pwszValues = NULL;
cmdOptions[OI_DEFAULT].pValue = pArrVal;
cmdOptions[OI_DEFAULT].dwLength = 0;
cmdOptions[OI_DEFAULT].pFunction = NULL;
cmdOptions[OI_DEFAULT].pFunctionData = NULL;
cmdOptions[OI_DEFAULT].dwReserved = 0;
cmdOptions[OI_DEFAULT].pReserved1 = NULL;
cmdOptions[OI_DEFAULT].pReserved2 = NULL;
cmdOptions[OI_DEFAULT].pReserved3 = NULL;
*pArrVal=CreateDynamicArray();
if( NULL == *pArrVal )
{
SetLastError( ERROR_OUTOFMEMORY );
SaveLastError();
ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
return( EXIT_FAILURE );
}
//process the command line options and display error if it fails
cmdOptions[OI_DEFAULT].pValue = pArrVal;
if( DoParseParam2( argc, argv, -1, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) == FALSE )
{
ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
return( EXIT_FAILURE );
}
*lpszRecursive = cmdOptions[OI_RECURSIVE].pValue;
//if usage specified with any other value display error and return with failure
if( ( TRUE == *pbUsage ) && ( argc > 2 ) )
{
SetLastError( (DWORD)MK_E_SYNTAX );
SaveLastError();
ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
ShowMessage( stderr, GetResString( IDS_HELP_MESSAGE ) );
return( EXIT_FAILURE );
}
if( TRUE == *pbUsage )
return( EXIT_SUCCESS);
StrTrim( *lpszRecursive, L" " );
if( 0 == StringLengthW(*lpszRecursive, 0) && cmdOptions[OI_RECURSIVE].dwActuals !=0 )
{
ShowMessage( stderr, GetResString(IDS_NO_RECURSIVE) );
return( EXIT_FAILURE );
}
//check for invalid characters in the directory name
if ( (*lpszRecursive != NULL) && (szFilePart = wcspbrk(*lpszRecursive, INVALID_DIRECTORY_CHARACTERS ))!=NULL )
{
ShowMessage( stderr, GetResString(IDS_INVALID_DIRECTORY_SPECIFIED) );
return( EXIT_FAILURE );
}
//if recursive is specified check whether the given path is
//a true directory or not.
if( StringLengthW(*lpszRecursive, 0) != 0)
{
szBuffer1 = (LPWSTR) AllocateMemory( (StringLengthW(*lpszRecursive, 0)+10)*sizeof(WCHAR) );
if( NULL == szBuffer1 )
{
ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
return EXIT_FAILURE;
}
//place a copy of recursive directory name into a temporary variable to check later for consequtive dots
StringCopy( szBuffer1, *lpszRecursive, SIZE_OF_ARRAY_IN_CHARS(szBuffer1) );
//get the full path name of directory
dwSize=GetFullPathName(*lpszRecursive,
0,
szFullPath,
&szFilePart );
if( dwSize != 0 )
{
szFullPath = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
if( NULL == szFullPath )
{
ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
FreeMemory((LPVOID *) &szBuffer1);
return( EXIT_FAILURE );
}
if( FALSE == GetFullPathName(*lpszRecursive,
dwSize,
szFullPath,
&szFilePart ) )
{
SaveLastError();
ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
FreeMemory((LPVOID *) &szBuffer1);
return EXIT_FAILURE;
}
}
else
{
SaveLastError();
ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
return EXIT_FAILURE;
}
//get the long path name
dwSize = GetLongPathName( szFullPath, szLongPath, 0 );
if( dwSize == 0 )
{
SaveLastError();
ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
FreeMemory((LPVOID *) &szBuffer1 );
FreeMemory((LPVOID *) &szFullPath);
return( EXIT_FAILURE );
}
szLongPath = (WCHAR *) AllocateMemory( (dwSize+10)*sizeof(WCHAR) );
if( NULL == szLongPath )
{
ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
FreeMemory((LPVOID *) &szBuffer1 );
FreeMemory((LPVOID *) &szFullPath);
return( EXIT_FAILURE );
}
if( FALSE == GetLongPathName( szFullPath, szLongPath, dwSize+5 ) )
{
ShowMessage(stderr,GetResString(IDS_INVALID_DIRECTORY_SPECIFIED));
FreeMemory((LPVOID *) &szBuffer1 );
FreeMemory((LPVOID *) &szFullPath);
FreeMemory((LPVOID *) &szLongPath);
return EXIT_FAILURE;
}
else
{
FreeMemory((LPVOID *) &(*lpszRecursive) );
*lpszRecursive = (LPWSTR ) AllocateMemory( (StringLengthW(szLongPath, 0)+10)*sizeof(WCHAR) );
if( NULL == *lpszRecursive )
{
ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
FreeMemory((LPVOID *) &szBuffer1 );
FreeMemory((LPVOID *) &szFullPath);
FreeMemory((LPVOID *) &szLongPath);
return( EXIT_FAILURE );
}
StringCopy( *lpszRecursive, szLongPath, SIZE_OF_ARRAY_IN_CHARS(*lpszRecursive) );
}
dwAttr = GetFileAttributes( *lpszRecursive);
if( -1 == dwAttr )
{
SaveLastError();
ShowMessageEx( stderr, 2, TRUE, L"%s %s", GetResString(IDS_TAG_ERROR), GetReason() );
FreeMemory((LPVOID *) &szBuffer1 );
FreeMemory((LPVOID *) &szFullPath);
FreeMemory((LPVOID *) &szLongPath);
return EXIT_FAILURE;
}
if( !(dwAttr & FILE_ATTRIBUTE_DIRECTORY) )
{
ShowMessage(stderr,GetResString(IDS_INVALID_DIRECTORY_SPECIFIED));
FreeMemory((LPVOID *) &szBuffer1 );
FreeMemory((LPVOID *) &szFullPath);
FreeMemory((LPVOID *) &szLongPath);
return EXIT_FAILURE;
}
//check if current directory is specified by more than two dots
GetCurrentDirectory(MAX_MAX_PATH, szBuffer );
StringConcat( szBuffer, L"\\", MAX_MAX_PATH );
if( StringCompare(szBuffer, *lpszRecursive, TRUE, 0) == 0 && (szFilePart=(LPWSTR)FindString( szBuffer1, L"...", 0) )!= NULL )
{
ShowMessage(stderr,GetResString(IDS_INVALID_DIRECTORY_SPECIFIED));
FreeMemory((LPVOID *) &szBuffer1 );
FreeMemory((LPVOID *) &szFullPath);
FreeMemory((LPVOID *) &szLongPath);
return EXIT_FAILURE;
}
}
return( EXIT_SUCCESS );
}
LPWSTR DivideToken( LPTSTR szString )
/*++
Routine Description : Function used to divide the string into tokens delimited by quotes or space
Arguments:
[ in ] szString : An LPTSTR string which is to parsed for quotes and spaces.
Return Type : LPWSTR
Returns the token upon successful, NULL otherwise
--*/
{
static WCHAR* str=NULL;
WCHAR* szTemp=NULL;
if( szString )
str = szString;
szTemp = str;
while( *str!=_T('*') && *str )
str++;
if( *str )
{
*str=_T('\0');
str++;
}
while( *str==_T('*') && *str )
str++;
if( szTemp[0] )
return (szTemp );
else return( NULL );
}
DWORD FreeList( DIRECTORY dir )
/*++
Routine Description : Function is used to free the linked list
Arguments:
[ in ] *dir : pointer to DIRECTORY list
Return Type : LPWSTR
Returns the EXIT_SUCCESS successful, EXIT_FAILURE otherwise
--*/
{
DIRECTORY temp;
for( temp=dir; dir; temp=dir->next )
{
FreeMemory( (LPVOID *)&temp->szDirectoryName );
FreeMemory((LPVOID*) &temp );
}
return EXIT_SUCCESS;
}