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.
828 lines
23 KiB
828 lines
23 KiB
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// File : OSACHECK.CPP
|
|
//
|
|
// Synopsis: Tools to check OSATTR(s) of catalog file(s).
|
|
//
|
|
// History: DSIE - January 30, 2001
|
|
//
|
|
// Microsoft Corporation (c) Copy Rights 2001.
|
|
//
|
|
|
|
#include <io.h>
|
|
#include <tchar.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <crtdbg.h>
|
|
#include <direct.h>
|
|
#include <atlbase.h>
|
|
#include <windows.h>
|
|
#include <cryptui.h>
|
|
#include <wintrust.h>
|
|
|
|
|
|
////////////////////
|
|
//
|
|
// macros
|
|
//
|
|
|
|
#define ASSERT(x) _ASSERT(x)
|
|
#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
|
|
|
|
|
|
////////////////////
|
|
//
|
|
// Global variables
|
|
//
|
|
|
|
_TCHAR * g_pszFilePath = _T(""); // Pointer to catalog file path.
|
|
BOOL g_bCatalogOSAttrOnly = FALSE; // OSAttr listing only flag.
|
|
BOOL g_bIncludeSubDir = FALSE; // Inlcude sub-dir flag.
|
|
BOOL g_bIgnoreError = FALSE; // Ignore error flag.
|
|
BOOL g_bVerbose = FALSE; // Verbose flag.
|
|
BOOL g_bViewCatalog = FALSE; // Display catalog dialog flag.
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Function: DebugTrace
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
#ifdef PKIDEBUG
|
|
|
|
BOOL g_bUseOutputDebugString = FALSE; // Use OutputDebugString flag.
|
|
|
|
void DebugTrace (char * pszFormat, ...)
|
|
{
|
|
char szMessage[512] = "";
|
|
|
|
va_list arglist;
|
|
|
|
va_start(arglist, pszFormat);
|
|
|
|
_vsnprintf(szMessage, ARRAYSIZE(szMessage), pszFormat, arglist);
|
|
|
|
if (g_bUseOutputDebugString)
|
|
{
|
|
OutputDebugString(szMessage);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, szMessage);
|
|
}
|
|
|
|
va_end(arglist);
|
|
|
|
return;
|
|
}
|
|
#else
|
|
inline void DebugTrace (char * pszFormat, ...) {}
|
|
#endif
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Function: DisplayHelp
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
void DisplayHelp (_TCHAR * pszFullExePath, BOOL bExtraHelp)
|
|
{
|
|
_TCHAR szDrive[_MAX_DRIVE] = _T("");
|
|
_TCHAR szDir[_MAX_DIR] = _T("");
|
|
_TCHAR szFName[_MAX_FNAME] = _T("");
|
|
_TCHAR szExt[_MAX_EXT] = _T("");
|
|
|
|
_TCHAR * pszExeName = _T("OSACheck");
|
|
|
|
if (pszFullExePath)
|
|
{
|
|
_splitpath(pszFullExePath, szDrive, szDir, szFName, szExt);
|
|
pszExeName = szFName;
|
|
}
|
|
|
|
_ftprintf(stderr, _T("Usage: %s [drive:][path][filename] [options]\n"), pszExeName);
|
|
_ftprintf(stderr, _T("\n"));
|
|
_ftprintf(stderr, _T(" [drive:][path][filename]\n"));
|
|
_ftprintf(stderr, _T(" Specifies drive, directory, and/or catalog files to scan.\n"));
|
|
_ftprintf(stderr, _T("\n"));
|
|
_ftprintf(stderr, _T(" [options]\n"));
|
|
_ftprintf(stderr, _T(" -c List only catalog OSAttrs (no file listing).\n"));
|
|
_ftprintf(stderr, _T(" -s Scan catalog files in specified directory and all subdirectories.\n"));
|
|
_ftprintf(stderr, _T(" -i Ignore error and continue with next catalog file.\n"));
|
|
_ftprintf(stderr, _T(" -v Verbose.\n"));
|
|
if (bExtraHelp)
|
|
{
|
|
#ifdef PKIDEBUG
|
|
_ftprintf(stderr, _T(" ~d Display catalog dialog.\n"));
|
|
_ftprintf(stderr, _T(" ~o Use OutputDebugString() for debug trace.\n"));
|
|
#endif
|
|
_ftprintf(stderr, _T(" ~h This help screen.\n"));
|
|
}
|
|
else
|
|
{
|
|
_ftprintf(stderr, _T(" -h This help screen.\n"));
|
|
}
|
|
_ftprintf(stderr, _T("\n"));
|
|
_ftprintf(stderr, _T("Note: If filename is not provided, *.CAT is assumed.\n"));
|
|
_ftprintf(stderr, _T("\n"));
|
|
return;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Function: ParseCommandLine
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
int ParseCommandLine (int argc, _TCHAR * argv[])
|
|
{
|
|
int nResult = 0;
|
|
BOOL bDisplayHelp = FALSE;
|
|
BOOL bExtraHelp = FALSE;
|
|
|
|
ASSERT(argc);
|
|
|
|
for (int i = 1; i < argc; i++)
|
|
{
|
|
ASSERT(argv[i]);
|
|
|
|
if (_T('-') == argv[i][0] || _T('/') == argv[i][0])
|
|
{
|
|
switch (toupper(argv[i][1]))
|
|
{
|
|
case _T('C'):
|
|
{
|
|
g_bCatalogOSAttrOnly = TRUE;
|
|
break;
|
|
}
|
|
|
|
case _T('I'):
|
|
{
|
|
g_bIgnoreError = TRUE;
|
|
break;
|
|
}
|
|
|
|
case _T('S'):
|
|
{
|
|
g_bIncludeSubDir = TRUE;
|
|
break;
|
|
}
|
|
|
|
case _T('V'):
|
|
{
|
|
g_bVerbose = TRUE;
|
|
break;
|
|
}
|
|
|
|
case _T('?'):
|
|
case _T('H'):
|
|
|
|
default:
|
|
{
|
|
nResult = -1;
|
|
bDisplayHelp = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (_T('~') == argv[i][0])
|
|
{
|
|
switch (toupper(argv[i][1]))
|
|
{
|
|
case _T('D'):
|
|
{
|
|
g_bViewCatalog = TRUE;
|
|
break;
|
|
}
|
|
|
|
#ifdef PKIDEBUG
|
|
case _T('O'):
|
|
{
|
|
g_bUseOutputDebugString = TRUE;
|
|
break;
|
|
}
|
|
#endif
|
|
case _T('?'):
|
|
case _T('H'):
|
|
|
|
default:
|
|
{
|
|
nResult = -1;
|
|
bExtraHelp = TRUE;
|
|
bDisplayHelp = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (0 == _tcslen(g_pszFilePath))
|
|
{
|
|
g_pszFilePath = argv[i];
|
|
|
|
if (NULL == _tcschr(g_pszFilePath, _T('*')) && NULL == strchr(g_pszFilePath, _T('?')))
|
|
{
|
|
long hFile;
|
|
struct _finddata_t fd;
|
|
|
|
if (-1 != (hFile = _tfindfirst(g_pszFilePath, &fd)))
|
|
{
|
|
if (_A_SUBDIR & fd.attrib)
|
|
{
|
|
if (_T('\\') != g_pszFilePath[_tcslen(g_pszFilePath) - 1])
|
|
{
|
|
if (g_pszFilePath = (_TCHAR *) malloc((_tcslen(g_pszFilePath) +
|
|
_tcslen(_T("\\")) + 1) *
|
|
sizeof(_TCHAR)))
|
|
{
|
|
_tcscpy(g_pszFilePath, argv[i]);
|
|
_tcscat(g_pszFilePath, _T("\\"));
|
|
}
|
|
else
|
|
{
|
|
nResult = -2;
|
|
}
|
|
}
|
|
}
|
|
|
|
_findclose(hFile);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nResult = -3;
|
|
bDisplayHelp = TRUE;
|
|
}
|
|
|
|
if (bDisplayHelp)
|
|
{
|
|
DisplayHelp(argv[0], bExtraHelp);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return nResult;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Function: ViewCatalog
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
int ViewCatalog (PCCTL_CONTEXT pCTLContext)
|
|
{
|
|
CRYPTUI_VIEWCTL_STRUCT ViewCTLStruct;
|
|
|
|
ASSERT(pCTLContext);
|
|
|
|
memset(&ViewCTLStruct, 0, sizeof(ViewCTLStruct));
|
|
ViewCTLStruct.dwSize = sizeof(ViewCTLStruct);
|
|
ViewCTLStruct.pCTLContext = pCTLContext;
|
|
|
|
CryptUIDlgViewCTL(&ViewCTLStruct);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Function: DecodeObject
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
int DecodeObject (LPCSTR pszStructType,
|
|
BYTE * pbEncoded,
|
|
DWORD cbEncoded,
|
|
CRYPT_DATA_BLOB * pDecodedBlob)
|
|
{
|
|
int nResult = 0;
|
|
DWORD cbDecoded = 0;
|
|
BYTE * pbDecoded = NULL;
|
|
|
|
ASSERT(pszStructType);
|
|
ASSERT(pbEncoded);
|
|
ASSERT(pDecodedBlob);
|
|
|
|
__try
|
|
{
|
|
pDecodedBlob->cbData = 0;
|
|
pDecodedBlob->pbData = NULL;
|
|
|
|
if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
pszStructType,
|
|
(const BYTE *) pbEncoded,
|
|
cbEncoded,
|
|
0,
|
|
NULL,
|
|
&cbDecoded))
|
|
{
|
|
nResult = GetLastError();
|
|
DebugTrace("\nError [%#x]: CryptDecodeObject() failed.\n", nResult);
|
|
__leave;
|
|
}
|
|
|
|
if (!(pbDecoded = (BYTE *) malloc(cbDecoded)))
|
|
{
|
|
nResult = E_OUTOFMEMORY;
|
|
DebugTrace("\nError: out of memory.\n");
|
|
__leave;
|
|
}
|
|
|
|
if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
pszStructType,
|
|
(const BYTE *) pbEncoded,
|
|
cbEncoded,
|
|
0,
|
|
pbDecoded,
|
|
&cbDecoded))
|
|
{
|
|
nResult = GetLastError();
|
|
DebugTrace("\nError [%#x]: CryptDecodeObject() failed.\n", nResult);
|
|
__leave;
|
|
}
|
|
|
|
pDecodedBlob->cbData = cbDecoded;
|
|
pDecodedBlob->pbData = pbDecoded;
|
|
}
|
|
|
|
__finally
|
|
{
|
|
if (nResult && pbDecoded)
|
|
{
|
|
free(pbDecoded);
|
|
}
|
|
}
|
|
|
|
return nResult;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Function: ProcessFileOSAttr
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
int ProcessFileOSAttr (PCTL_INFO pCTLInfo)
|
|
{
|
|
int nResult = 0;
|
|
|
|
ASSERT(pCTLInfo);
|
|
|
|
for (DWORD i = 0; i < pCTLInfo->cCTLEntry; i++)
|
|
{
|
|
DWORD cOSAttr = 0;
|
|
DWORD cFiles = 0;
|
|
PCTL_ENTRY pCTLEntry = &pCTLInfo->rgCTLEntry[i];
|
|
|
|
if (i)
|
|
{
|
|
if (g_bVerbose)
|
|
{
|
|
_ftprintf(stdout, _T("\n%-10s"), _T(""));
|
|
}
|
|
else
|
|
{
|
|
_ftprintf(stdout, _T("\n%-14s"), _T(""));
|
|
}
|
|
}
|
|
|
|
_ftprintf(stdout, _T("%-40S "), pCTLEntry->SubjectIdentifier.pbData);
|
|
|
|
for (DWORD j = 0; j < pCTLEntry->cAttribute; j++)
|
|
{
|
|
PCRYPT_ATTRIBUTE pAttribute = &pCTLEntry->rgAttribute[j];
|
|
CRYPT_DATA_BLOB DataBlob = {0, NULL};
|
|
PCAT_NAMEVALUE pCATNameValue = NULL;
|
|
|
|
if (0 != strcmp(pAttribute->pszObjId, CAT_NAMEVALUE_OBJID))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (0 != (nResult = DecodeObject(CAT_NAMEVALUE_STRUCT,
|
|
pAttribute->rgValue[0].pbData,
|
|
pAttribute->rgValue[0].cbData,
|
|
&DataBlob)))
|
|
{
|
|
return nResult;
|
|
}
|
|
|
|
pCATNameValue = (PCAT_NAMEVALUE) DataBlob.pbData;
|
|
|
|
if (0 == wcscmp(L"File", pCATNameValue->pwszTag))
|
|
{
|
|
j = pCTLEntry->cAttribute;
|
|
_ftprintf(stdout, _T("%-15S "), pCATNameValue->Value.pbData);
|
|
cFiles++;
|
|
}
|
|
|
|
free(DataBlob.pbData);
|
|
}
|
|
|
|
if (0 == cFiles)
|
|
{
|
|
_ftprintf(stdout, _T("%-15s "), "");
|
|
}
|
|
|
|
for (j = 0; j < pCTLEntry->cAttribute; j++)
|
|
{
|
|
PCRYPT_ATTRIBUTE pAttribute = &pCTLEntry->rgAttribute[j];
|
|
CRYPT_DATA_BLOB DataBlob = {0, NULL};
|
|
PCAT_NAMEVALUE pCATNameValue = NULL;
|
|
|
|
if (0 != strcmp(pAttribute->pszObjId, CAT_NAMEVALUE_OBJID))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (0 != (nResult = DecodeObject(CAT_NAMEVALUE_STRUCT,
|
|
pAttribute->rgValue[0].pbData,
|
|
pAttribute->rgValue[0].cbData,
|
|
&DataBlob)))
|
|
{
|
|
return nResult;
|
|
}
|
|
|
|
pCATNameValue = (PCAT_NAMEVALUE) DataBlob.pbData;
|
|
|
|
if (0 == wcscmp(L"OSAttr", pCATNameValue->pwszTag))
|
|
{
|
|
j = pCTLEntry->cAttribute;
|
|
_ftprintf(stdout, _T("%S "), pCATNameValue->Value.pbData);
|
|
cOSAttr++;
|
|
}
|
|
|
|
free(DataBlob.pbData);
|
|
}
|
|
}
|
|
|
|
return nResult;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Function: ProcessCatalogOSAttr
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
int ProcessCatalogOSAttr (PCTL_INFO pCTLInfo)
|
|
{
|
|
int nResult = 0;
|
|
DWORD cOSAttr = 0;
|
|
|
|
ASSERT(pCTLInfo);
|
|
|
|
for (DWORD i = 0; i < pCTLInfo->cExtension; i++)
|
|
{
|
|
PCERT_EXTENSION pExtension = &pCTLInfo->rgExtension[i];
|
|
|
|
if (0 == strcmp(CAT_NAMEVALUE_OBJID, pExtension->pszObjId))
|
|
{
|
|
BOOL bDuplicate = TRUE;
|
|
CRYPT_DATA_BLOB DataBlob = {0, NULL};
|
|
PCAT_NAMEVALUE pCATNameValue = NULL;
|
|
|
|
if (0 != (nResult = DecodeObject(CAT_NAMEVALUE_STRUCT,
|
|
pExtension->Value.pbData,
|
|
pExtension->Value.cbData,
|
|
&DataBlob)))
|
|
{
|
|
return nResult;
|
|
}
|
|
|
|
pCATNameValue = (PCAT_NAMEVALUE) DataBlob.pbData;
|
|
|
|
if (0 == wcscmp(L"OSAttr", pCATNameValue->pwszTag))
|
|
{
|
|
i = pCTLInfo->cExtension;
|
|
_ftprintf(stdout, _T("%S"), pCATNameValue->Value.pbData);
|
|
cOSAttr++;
|
|
}
|
|
|
|
free(DataBlob.pbData);
|
|
}
|
|
}
|
|
|
|
if (0 == cOSAttr)
|
|
{
|
|
_ftprintf(stdout, _T("None"));
|
|
}
|
|
|
|
return nResult;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Function: ProcessCatalog
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
int ProcessCatalog (_TCHAR * pszFileName)
|
|
{
|
|
int nResult = 0;
|
|
PCCTL_CONTEXT pCTLContext = NULL;
|
|
|
|
ASSERT(pszFileName);
|
|
|
|
__try
|
|
{
|
|
USES_CONVERSION;
|
|
WCHAR * pwszFileName = NULL;
|
|
|
|
if (g_bVerbose)
|
|
{
|
|
_TCHAR szCWD[_MAX_PATH] = _T("");
|
|
|
|
if (_tgetcwd(szCWD, ARRAYSIZE(szCWD)))
|
|
{
|
|
if (szCWD[_tcslen(szCWD) - 1] != _T('\\'))
|
|
{
|
|
szCWD[_tcslen(szCWD) + 1] = _T('\0');
|
|
szCWD[_tcslen(szCWD)] = _T('\\');
|
|
}
|
|
|
|
_ftprintf(stdout, _T("-------------------------------------------------------------------------------\n"));
|
|
_ftprintf(stdout, _T("Catalog = %s%s\n"), szCWD, pszFileName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_ftprintf(stdout, _T("%-14s"), pszFileName);
|
|
}
|
|
|
|
if (NULL == (pwszFileName = T2W(pszFileName)))
|
|
{
|
|
nResult = E_OUTOFMEMORY;
|
|
DebugTrace(_T("Error: out of memory.\n"));
|
|
__leave;
|
|
}
|
|
|
|
if (!CryptQueryObject(CERT_QUERY_OBJECT_FILE,
|
|
pwszFileName,
|
|
CERT_QUERY_CONTENT_FLAG_CTL,
|
|
CERT_QUERY_FORMAT_FLAG_ALL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
(const void **) &pCTLContext))
|
|
{
|
|
nResult = GetLastError();
|
|
DebugTrace(_T("Error [%#x]: CryptQueryObject() failed.\n"), nResult);
|
|
__leave;
|
|
}
|
|
|
|
if (g_bVerbose)
|
|
{
|
|
_ftprintf(stdout, _T("Entries = %d\n"), pCTLContext->pCtlInfo->cCTLEntry);
|
|
if (g_bCatalogOSAttrOnly)
|
|
{
|
|
_ftprintf(stdout, _T("OSAttrs = "));
|
|
}
|
|
else
|
|
{
|
|
_ftprintf(stdout, _T("Details = "));
|
|
}
|
|
}
|
|
|
|
if (g_bCatalogOSAttrOnly)
|
|
{
|
|
nResult = ProcessCatalogOSAttr(pCTLContext->pCtlInfo);
|
|
}
|
|
else
|
|
{
|
|
nResult = ProcessFileOSAttr(pCTLContext->pCtlInfo);
|
|
}
|
|
|
|
_ftprintf(stdout, _T("\n"));
|
|
|
|
if (0 != nResult)
|
|
{
|
|
__leave;
|
|
}
|
|
|
|
if (g_bViewCatalog)
|
|
{
|
|
ViewCatalog(pCTLContext);
|
|
}
|
|
}
|
|
|
|
__finally
|
|
{
|
|
if (pCTLContext)
|
|
{
|
|
CertFreeCTLContext(pCTLContext);
|
|
}
|
|
}
|
|
|
|
return nResult;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Function: ProcessCatalogs
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
int ProcessCatalogs (_TCHAR * pszFilePath, BOOL bIncludeSubDir)
|
|
{
|
|
int nResult = 0;
|
|
long hFile = -1;
|
|
TCHAR szFilePath[_MAX_PATH] = _T("");
|
|
|
|
ASSERT(pszFilePath);
|
|
|
|
__try
|
|
{
|
|
DWORD cDirs = 0;
|
|
struct _finddata_t fd;
|
|
|
|
if (0 == _tcslen(pszFilePath))
|
|
{
|
|
_tcscpy(szFilePath, _T("*.cat"));
|
|
}
|
|
else
|
|
{
|
|
_tcscpy(szFilePath, pszFilePath);
|
|
}
|
|
|
|
if (-1 != (hFile = _tfindfirst(szFilePath, &fd)))
|
|
{
|
|
do
|
|
{
|
|
if (_A_SUBDIR & fd.attrib)
|
|
{
|
|
if (_tcscmp(_T("."), fd.name) && _tcscmp(_T(".."), fd.name))
|
|
{
|
|
cDirs++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (0 != (nResult = ProcessCatalog(fd.name)))
|
|
{
|
|
if (g_bIgnoreError)
|
|
{
|
|
nResult = 0;
|
|
}
|
|
else
|
|
{
|
|
__leave;
|
|
}
|
|
}
|
|
}
|
|
} while (0 == _tfindnext(hFile, &fd));
|
|
|
|
_findclose(hFile);
|
|
hFile = -1;
|
|
}
|
|
|
|
if (bIncludeSubDir)
|
|
{
|
|
if (0 == cDirs)
|
|
{
|
|
_tcscpy(szFilePath, _T("*.*"));
|
|
}
|
|
|
|
if (-1 != (hFile = _tfindfirst(szFilePath, &fd)))
|
|
{
|
|
do
|
|
{
|
|
if ((_A_SUBDIR & fd.attrib) && _tcscmp(_T("."), fd.name) && _tcscmp(_T(".."), fd.name))
|
|
{
|
|
_TCHAR szCWD[_MAX_PATH] = _T("");
|
|
|
|
if (_tgetcwd(szCWD, ARRAYSIZE(szCWD)))
|
|
{
|
|
_tchdir(fd.name);
|
|
|
|
nResult = ProcessCatalogs(pszFilePath, bIncludeSubDir);
|
|
|
|
_tchdir(szCWD);
|
|
}
|
|
else
|
|
{
|
|
nResult = errno;
|
|
DebugTrace(_T("\nError [%#x]: _tgetcwd() failed.\n"), errno);
|
|
}
|
|
|
|
if (0 != nResult)
|
|
{
|
|
if (g_bIgnoreError)
|
|
{
|
|
nResult = 0;
|
|
}
|
|
else
|
|
{
|
|
__leave;
|
|
}
|
|
}
|
|
}
|
|
} while (0 == _tfindnext(hFile, &fd));
|
|
|
|
_findclose(hFile);
|
|
hFile = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
__finally
|
|
{
|
|
if (-1 != hFile)
|
|
{
|
|
_findclose(hFile);
|
|
}
|
|
}
|
|
|
|
return nResult;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Function: main
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
int __cdecl _tmain (int argc, _TCHAR * argv[])
|
|
{
|
|
int nResult = 0;
|
|
int CurrentDrive = _getdrive();
|
|
_TCHAR szCWD[_MAX_PATH] = _T("");
|
|
|
|
_tgetcwd(szCWD, sizeof(szCWD) / sizeof(szCWD[0]));
|
|
|
|
__try
|
|
{
|
|
_TCHAR szDrive[_MAX_DRIVE] = _T("");
|
|
_TCHAR szDir[_MAX_DIR] = _T("");
|
|
_TCHAR szFName[_MAX_FNAME] = _T("");
|
|
_TCHAR szExt[_MAX_EXT] = _T("");
|
|
_TCHAR szFilePath[_MAX_PATH] = _T("");
|
|
|
|
if (0 != (nResult = ParseCommandLine(argc, argv)))
|
|
{
|
|
__leave;
|
|
}
|
|
|
|
if (g_bVerbose)
|
|
{
|
|
_ftprintf(stdout, _T("Current drive = %c:\n"), CurrentDrive - 1 + _T('A'));
|
|
_ftprintf(stdout, _T("Current directory = %s\n"), szCWD);
|
|
_ftprintf(stdout, _T("Command line ="));
|
|
for (int i = 0; i < argc; i++)
|
|
{
|
|
_ftprintf(stdout, _T(" %s"), argv[i]);
|
|
}
|
|
_ftprintf(stdout, _T("\n"));
|
|
}
|
|
|
|
_splitpath(g_pszFilePath, szDrive, szDir, szFName, szExt);
|
|
|
|
if (_tcslen(szDrive))
|
|
{
|
|
if (0 != _chdrive(toupper(szDrive[0]) - _T('A') + 1))
|
|
{
|
|
nResult = ENOENT;
|
|
_ftprintf(stdout, _T("Error: _chdrive() to %s failed.\n"), szDrive);
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
if (_tcslen(szDir))
|
|
{
|
|
if (0 != _tchdir(szDir))
|
|
{
|
|
nResult = ENOENT;
|
|
_ftprintf(stdout, _T("Error: _tchdir() to %s failed.\n"), szDir);
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
_tcscpy(szFilePath, szFName);
|
|
_tcscat(szFilePath, szExt);
|
|
|
|
nResult = ProcessCatalogs(szFilePath, g_bIncludeSubDir);
|
|
}
|
|
|
|
__finally
|
|
{
|
|
_chdrive(CurrentDrive);
|
|
|
|
_tchdir(szCWD);
|
|
}
|
|
|
|
return nResult;
|
|
}
|