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.
 
 
 
 
 
 

2010 lines
64 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2001
//
// File: signtool.cpp
//
// Contents: The SignTool console tool
//
// History: 4/30/2001 SCoyne Created
//
//----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <unicode.h>
#include <locale.h>
#include "resource.h"
#include "signtool.h"
#ifdef SIGNTOOL_DEBUG
#include "signtooldebug.h"
BOOL gDebug; // Global
#endif
typedef WINBASEAPI BOOL (*FUNC_ISWOW64) (HANDLE, PBOOL);
// Global Variables:
HINSTANCE hModule;
// wmain returns 0 on success, 1 on error, and 2 on warning
extern "C" int __cdecl wmain(int argc, WCHAR **wargv)
{
INPUTINFO InputInfo;
WCHAR wszResource[MAX_RES_LEN];
WCHAR *wszLocale = NULL;
HMODULE hModTemp;
FUNC_ISWOW64 fnIsWow64;
BOOL fTemp;
int iReturn;
// Initialize InputInfo
memset(&InputInfo, 0, sizeof(INPUTINFO));
// Initialize Module Handle
if ((hModule=GetModuleHandleA(NULL)) == NULL)
{
// In this case resources cannot be loaded, so English will have to do:
wprintf(L"SignTool Error: GetModuleHandle returned: 0x%08X\n",
GetLastError());
iReturn = 1; // Initialization Error
goto Cleanup;
}
// Set Locale
if (LoadStringU(hModule, IDS_LOCALE, wszResource, MAX_RES_LEN))
{
wszLocale = _wsetlocale(LC_ALL, wszResource);
}
#ifdef SIGNTOOL_DEBUG
if (!wszLocale)
{
wprintf(L"Failed to set locale to: %s\n", wszResource);
}
#endif
// Parse Arguments into InputInfo structure
if (!ParseInputs(argc, wargv, &InputInfo))
{
if (InputInfo.HelpRequest)
{
return 0; // Successfully completed user request for help
}
else
{
iReturn = 1; // Any other Parameter-Parsing Error
goto Cleanup;
}
}
// Determine if we are under WOW64
hModTemp = GetModuleHandleA("kernel32.dll");
if (hModTemp)
{
fnIsWow64 = (FUNC_ISWOW64) GetProcAddress(hModTemp, "IsWow64Process");
if (fnIsWow64 &&
fnIsWow64(GetCurrentProcess(), &fTemp))
{
InputInfo.fIsWow64Process = fTemp;
}
}
#ifdef SIGNTOOL_DEBUG
// Print debug info if debug support is compiled in, and the debug
// switch was specified:
if (gDebug)
PrintInputInfo(&InputInfo);
#endif
// Perform the requested action:
switch (InputInfo.Command)
{
case CatDb:
iReturn = SignTool_CatDb(&InputInfo);
break;
case Sign:
iReturn = SignTool_Sign(&InputInfo);
break;
case SignWizard:
iReturn = SignTool_SignWizard(&InputInfo);
break;
case Timestamp:
iReturn = SignTool_Timestamp(&InputInfo);
break;
case Verify:
iReturn = SignTool_Verify(&InputInfo);
break;
default:
ResErr(IDS_ERR_UNEXPECTED); // This should never happen
iReturn = 1; // Error
}
Cleanup:
#ifdef SIGNTOOL_LIST
if (InputInfo.wszListFileContents)
free(InputInfo.wszListFileContents);
#endif
return iReturn;
}
// PrintUsage automatically prints the relevant Usage based on InputInfo.
void PrintUsage(INPUTINFO *InputInfo)
{
switch (InputInfo->Command)
{
default:
case CommandNone: // Then print top-level Usage
ResErr(IDS_SIGNTOOL_USAGE);
break;
case CatDb:
ResErr(IDS_CATDB_USAGE);
ResErr(IDS_CATDB_DB_SELECT_OPTIONS);
ResErr(IDS_CATDB_D);
ResErr(IDS_CATDB_G);
ResErr(IDS_CATDB_OTHER_OPTIONS);
ResErr(IDS_CATDB_Q);
ResErr(IDS_CATDB_R);
ResErr(IDS_CATDB_U);
ResErr(IDS_CATDB_V);
break;
case Sign:
ResErr(IDS_SIGN_USAGE);
ResErr(IDS_SIGN_CERT_OPTIONS);
ResErr(IDS_SIGN_A);
ResErr(IDS_SIGN_C);
ResErr(IDS_SIGN_F);
ResErr(IDS_SIGN_I);
ResErr(IDS_SIGN_N);
ResErr(IDS_SIGN_P);
ResErr(IDS_SIGN_R);
ResErr(IDS_SIGN_S);
ResErr(IDS_SIGN_SM);
ResErr(IDS_SIGN_SHA1);
ResErr(IDS_SIGN_U);
ResErr(IDS_SIGN_UW);
ResErr(IDS_SIGN_PRIV_KEY_OPTIONS);
ResErr(IDS_SIGN_CSP);
ResErr(IDS_SIGN_K);
ResErr(IDS_SIGN_SIGNING_OPTIONS);
ResErr(IDS_SIGN_D);
ResErr(IDS_SIGN_DU);
ResErr(IDS_SIGN_T);
ResErr(IDS_SIGN_OTHER_OPTIONS);
ResErr(IDS_SIGN_Q);
ResErr(IDS_SIGN_V);
break;
case SignWizard:
ResErr(IDS_SIGNWIZARD_USAGE);
ResErr(IDS_SIGNWIZARD_OPTIONS);
ResErr(IDS_SIGNWIZARD_Q);
ResErr(IDS_SIGNWIZARD_V);
break;
case Timestamp:
ResErr(IDS_TIMESTAMP_USAGE);
ResErr(IDS_TIMESTAMP_Q);
ResErr(IDS_TIMESTAMP_T);
ResErr(IDS_TIMESTAMP_V);
break;
case Verify:
ResErr(IDS_VERIFY_USAGE);
ResErr(IDS_VERIFY_CATALOG_OPTIONS);
ResErr(IDS_VERIFY_A);
ResErr(IDS_VERIFY_AD);
ResErr(IDS_VERIFY_AS);
ResErr(IDS_VERIFY_AG);
ResErr(IDS_VERIFY_C);
ResErr(IDS_VERIFY_O);
ResErr(IDS_VERIFY_POLICY_OPTIONS);
ResErr(IDS_VERIFY_PD);
ResErr(IDS_VERIFY_PG);
ResErr(IDS_VERIFY_SIG_OPTIONS);
ResErr(IDS_VERIFY_R);
ResErr(IDS_VERIFY_TW);
ResErr(IDS_VERIFY_OTHER_OPTIONS);
ResErr(IDS_VERIFY_Q);
ResErr(IDS_VERIFY_V);
break;
}
}
// Error Functions:
void Res_Err(DWORD dwRes)
{
static WCHAR wszResource[MAX_RES_LEN];
if (LoadStringU(hModule, dwRes, wszResource, MAX_RES_LEN))
{
fwprintf(stderr, L"%s", wszResource);
}
else
{
fwprintf(stderr, L"********** %u **********\n", dwRes);
}
}
void ResOut(DWORD dwRes)
{
static WCHAR wszResource[MAX_RES_LEN];
if (LoadStringU(hModule, dwRes, wszResource, MAX_RES_LEN))
{
wprintf(L"%s", wszResource);
}
else
{
wprintf(L"********** %u **********\n", dwRes);
}
}
void ResFormat_Err(DWORD dwRes, ...)
{
static WCHAR wszResource[MAX_RES_LEN];
static WCHAR *lpMsgBuf = NULL;
static va_list vaList;
va_start(vaList, dwRes);
if (LoadStringU(hModule, dwRes, wszResource, MAX_RES_LEN) &&
FormatMessageU(FORMAT_MESSAGE_FROM_STRING |
FORMAT_MESSAGE_ALLOCATE_BUFFER,
wszResource,
0,
0,
(LPWSTR) &lpMsgBuf,
MAX_RES_LEN,
&vaList))
{
fwprintf(stderr, L"%s", lpMsgBuf);
LocalFree(lpMsgBuf);
}
else
{
fwprintf(stderr, L"********** %u **********\n", dwRes);
}
va_end(vaList);
}
void ResFormatOut(DWORD dwRes, ...)
{
static WCHAR wszResource[MAX_RES_LEN];
static WCHAR *lpMsgBuf = NULL;
static va_list vaList;
va_start(vaList, dwRes);
if (LoadStringU(hModule, dwRes, wszResource, MAX_RES_LEN) &&
FormatMessageU(FORMAT_MESSAGE_FROM_STRING |
FORMAT_MESSAGE_ALLOCATE_BUFFER,
wszResource,
0,
0,
(LPWSTR) &lpMsgBuf,
MAX_RES_LEN,
&vaList))
{
wprintf(L"%s", lpMsgBuf);
LocalFree(lpMsgBuf);
}
else
{
wprintf(L"********** %u **********\n", dwRes);
}
va_end(vaList);
}
void Format_ErrRet(WCHAR *wszFunc, DWORD dwErr)
{
WCHAR *lpMsgBuf = NULL;
if (FormatMessageU(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR) &lpMsgBuf,
0,
NULL))
{
ResFormat_Err(IDS_ERR_FUNCTION, wszFunc, dwErr, lpMsgBuf);
LocalFree(lpMsgBuf);
}
else
{
ResFormat_Err(IDS_ERR_FUNCTION, wszFunc, dwErr, L"");
}
}
BOOL GUIDFromWStr(GUID *guid, LPWSTR str)
{
DWORD i;
DWORD temp[8];
if ((wcslen(str) == 38) &&
(wcsncmp(str, L"{", 1) == 0) &&
(wcsncmp(&(str[37]), L"}", 1) == 0) &&
(swscanf(str,
L"{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
&guid->Data1, &guid->Data2, &guid->Data3, &temp[0],
&temp[1], &temp[2], &temp[3], &temp[4],
&temp[5], &temp[6], &temp[7]) == 11))
{
for (i=0; i<8; i++)
guid->Data4[i] = (BYTE) temp[i];
return TRUE;
}
else
memset(guid, 0, sizeof(GUID));
return FALSE;
}
/*********************************************************************
* *
* Command Parsing section: *
* *
*********************************************************************/
// ParseInputs returns TRUE if parameters were parsed successfully,
// FALSE otherwise.
BOOL ParseInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo)
{
FILE *hFileList;
LPWSTR wszTemp;
WCHAR wc;
DWORD dwSize;
DWORD dwRead;
DWORD dwCount;
// Private Function Declarations:
BOOL _ParseCatDbInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo);
BOOL _ParseSignInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo);
BOOL _ParseSignWizardInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo);
BOOL _ParseTimestampInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo);
BOOL _ParseVerifyInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo);
// (These should never be called from any other functions)
if (argc <= 1) // If no parameters were specified
{
ResErr(IDS_ERR_NO_PARAMS);
PrintUsage(InputInfo);
return FALSE; // Print Usage
}
// Check the first parameter to see which command we are performing:
// Is it "CATDB" ?
if (_wcsicmp(wargv[1], L"CATDB") == 0)
{
InputInfo->Command = CatDb;
if (!_ParseCatDbInputs(argc, wargv, InputInfo))
return FALSE;
}
// Is it "SIGN" ?
else if (_wcsicmp(wargv[1], L"SIGN") == 0)
{
InputInfo->Command = Sign;
if (!_ParseSignInputs(argc, wargv, InputInfo))
return FALSE;
}
// Is it "SIGNWIZARD" ?
else if (_wcsicmp(wargv[1], L"SIGNWIZARD") == 0)
{
InputInfo->Command = SignWizard;
if (!_ParseSignWizardInputs(argc, wargv, InputInfo))
return FALSE;
}
// Is it "TIMESTAMP" ?
else if (_wcsicmp(wargv[1], L"TIMESTAMP") == 0)
{
InputInfo->Command = Timestamp;
if (!_ParseTimestampInputs(argc, wargv, InputInfo))
return FALSE;
}
// Is it "VERIFY" ?
else if (_wcsicmp(wargv[1], L"VERIFY") == 0)
{
InputInfo->Command = Verify;
if (!_ParseVerifyInputs(argc, wargv, InputInfo))
return FALSE;
}
// Is it a request for help?
else if ((_wcsicmp(wargv[1], L"/?") == 0) ||
(_wcsicmp(wargv[1], L"-?") == 0) ||
(_wcsicmp(wargv[1], L"/h") == 0) ||
(_wcsicmp(wargv[1], L"-h") == 0))
{
PrintUsage(InputInfo);
InputInfo->HelpRequest = TRUE;
return FALSE;
}
// Or is it unrecognized?
else
{
ResFormatErr(IDS_ERR_INVALID_COMMAND, wargv[1]);
PrintUsage(InputInfo);
return FALSE;
}
// To reach here, one of the _Parse_X_Inputs must have succeeded
#ifdef SIGNTOOL_LIST
// Expand the File List if necessary
if (InputInfo->wszListFileName)
{
// Open the file
hFileList = _wfopen(InputInfo->wszListFileName, L"rt");
if (hFileList == NULL)
{
ResFormatErr(IDS_ERR_OPENING_FILE_LIST, InputInfo->wszListFileName);
PrintUsage(InputInfo);
return FALSE;
}
// Go to the beginning
if (fseek(hFileList, SEEK_SET, 0) != 0)
{
ResErr(IDS_ERR_UNEXPECTED);
fclose(hFileList);
return FALSE;
}
// Get the full file size
// Do it this way to actually count the number of characters in the file
dwSize = 0;
while (fgetwc(hFileList) != WEOF)
{
dwSize++;
}
// Go back to the beginning
if (fseek(hFileList, SEEK_SET, 0) != 0)
{
ResErr(IDS_ERR_UNEXPECTED);
fclose(hFileList);
return FALSE;
}
// Allocate a buffer big enough for all of it
InputInfo->wszListFileContents = (WCHAR*) malloc((dwSize + 1) * sizeof(WCHAR));
if (InputInfo->wszListFileContents == NULL)
{
FormatErrRet(L"malloc", ERROR_OUTOFMEMORY);
fclose(hFileList);
return FALSE;
}
// Read the file into the buffer
dwRead = 0;
while ((dwRead < dwSize) && ((wc = getwc(hFileList)) != WEOF))
{
InputInfo->wszListFileContents[dwRead] = wc;
dwRead++;
}
// Sanity Check
if (dwRead != dwSize)
{
ResErr(IDS_ERR_UNEXPECTED);
fclose(hFileList);
return FALSE;
}
// Adjust for Unicode header if necessary
// if ((lSize > 1) && (InputInfo->wszListFileContents[0] == 0xFEFF))
// {
// InputInfo->wszListFileContents++;
// lSize--;
// }
// NULL terminate the final string (to be safe)
InputInfo->wszListFileContents[dwSize] = L'\0';
// Count the number of lines
wszTemp = InputInfo->wszListFileContents;
dwCount = 1;
while ((wszTemp = wcschr(wszTemp, L'\n')) != NULL)
{
wszTemp++;
dwCount++;
}
// Allocate the buffer for the pointers
InputInfo->rgwszFileNames = (LPWSTR*) malloc(dwCount * sizeof(LPWSTR));
if (InputInfo->rgwszFileNames == NULL)
{
FormatErrRet(L"malloc", ERROR_OUTOFMEMORY);
fclose(hFileList);
return FALSE;
}
// Assign the lines to the FileNames array
wszTemp = InputInfo->wszListFileContents;
InputInfo->NumFiles = 0;
while (wszTemp)
{
InputInfo->rgwszFileNames[InputInfo->NumFiles] = wszTemp;
wszTemp = wcschr(wszTemp, L'\n');
if (wszTemp)
{
*wszTemp = L'\0';
wszTemp++;
}
if (wcslen(InputInfo->rgwszFileNames[InputInfo->NumFiles]) > 0)
InputInfo->NumFiles++;
}
fclose(hFileList);
}
#endif // SIGNTOOL_LIST
return TRUE;
}
// Helper function specifically for the parameters of the CatDb command
BOOL _ParseCatDbInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo)
{
if (argc < 3) // If there's nothing after the "CatDb"
{
ResErr(IDS_ERR_NO_PARAMS);
PrintUsage(InputInfo);
return FALSE;
}
for (int i=2; i<argc; i++)
{
if ((wcsncmp(wargv[i], L"/", 1) == 0) ||
(wcsncmp(wargv[i], L"-", 1) == 0))
{
// Then it's a switch.
// Begin switch processing
// Switch to mark end of switches --
if (_wcsicmp(wargv[i]+1, L"-") == 0)
{
// Then we should treat all further parameters as filenames
if ((i+1) < argc)
{
InputInfo->rgwszFileNames = &wargv[i+1];
InputInfo->NumFiles = argc - (i+1);
goto CheckParams; // Done parsing.
}
else
{
ResErr(IDS_ERR_MISSING_FILENAME);
return FALSE; // No filename found after end of switches.
}
}
// Help: /? /h
else if ((_wcsicmp(wargv[i]+1, L"?") == 0) ||
(_wcsicmp(wargv[i]+1, L"h") == 0))
{
PrintUsage(InputInfo);
InputInfo->HelpRequest = TRUE;
return FALSE;
}
#ifdef SIGNTOOL_DEBUG
// Debug (secret switch) /#
else if (_wcsicmp(wargv[i]+1, L"#") == 0)
{
gDebug = TRUE;
InputInfo->Verbose = TRUE;
}
#endif
// Use Default CatDb /d
else if (_wcsicmp(wargv[i]+1, L"d") == 0)
{
switch (InputInfo->CatDbSelect)
{
case GuidCatDb:
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/d", L"/g");
return FALSE; // You cannot use the same type of switch twice.
case DefaultCatDb:
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
case NoCatDb:
InputInfo->CatDbSelect = DefaultCatDb;
break;
default:
ResErr(IDS_ERR_UNEXPECTED); // This should never happen
return FALSE; // Error
}
}
// CatDb Guid /g
else if (_wcsicmp(wargv[i]+1, L"g") == 0)
{
switch (InputInfo->CatDbSelect)
{
case GuidCatDb:
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
case DefaultCatDb:
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/g", L"/d");
return FALSE; // You cannot use the same type of switch twice.
case NoCatDb:
if ((i+1) < argc)
{
if (GUIDFromWStr(&InputInfo->CatDbGuid, wargv[i+1]))
{
InputInfo->CatDbSelect = GuidCatDb;
i++;
}
else
{
ResFormatErr(IDS_ERR_INVALID_GUID, wargv[i+1]);
return FALSE; // Invalid GUID format
}
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No GUID found after /g
}
break;
default:
ResErr(IDS_ERR_UNEXPECTED); // This should never happen
return FALSE; // Error
}
}
#ifdef SIGNTOOL_LIST
// File List /l
else if (_wcsicmp(wargv[i]+1, L"l") == 0)
{
if (InputInfo->wszListFileName)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszListFileName = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
#endif
// Quiet /q
else if (_wcsicmp(wargv[i]+1, L"q") == 0)
{
InputInfo->Quiet = TRUE;
}
// Remove Catalogs /r
else if (_wcsicmp(wargv[i]+1, L"r") == 0)
{
switch (InputInfo->CatDbCommand)
{
case UpdateCat:
InputInfo->CatDbCommand = RemoveCat;
break;
case AddUniqueCat:
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/u", L"/r");
return FALSE; // You cannot use the same type of switch twice.
case RemoveCat:
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
default:
ResErr(IDS_ERR_UNEXPECTED); // This should never happen
return FALSE; // Error
}
}
// Add Catalog with Unique Names /u
else if (_wcsicmp(wargv[i]+1, L"u") == 0)
{
switch (InputInfo->CatDbCommand)
{
case UpdateCat:
InputInfo->CatDbCommand = AddUniqueCat;
break;
case AddUniqueCat:
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
case RemoveCat:
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/r", L"/u");
return FALSE; // You cannot use the same type of switch twice.
default:
ResErr(IDS_ERR_UNEXPECTED); // This should never happen
return FALSE; // Error
}
}
// Verbose /v
else if (_wcsicmp(wargv[i]+1, L"v") == 0)
{
InputInfo->Verbose = TRUE;
}
else
{
ResFormatErr(IDS_ERR_INVALID_SWITCH, wargv[i]);
return FALSE; // Invalid switch
}
} // End of switch processing
else
{
// It's not a switch
// So it must be the filename(s) at the end.
InputInfo->rgwszFileNames = &wargv[i];
InputInfo->NumFiles = argc - i;
goto CheckParams; // Done parsing.
}
} // End FOR loop
#ifdef SIGNTOOL_LIST
// Handle the case where no files were passed on the command line
if (InputInfo->wszListFileName)
goto CheckParams; // Done Parsing
#endif
// No filename found after end of switches.
ResErr(IDS_ERR_MISSING_FILENAME);
return FALSE;
CheckParams:
if (InputInfo->CatDbSelect == NoCatDb)
{
InputInfo->CatDbSelect = SystemCatDb;
GUIDFromWStr(&InputInfo->CatDbGuid, L"{F750E6C3-38EE-11D1-85E5-00C04FC295EE}");
}
if (InputInfo->CatDbSelect == DefaultCatDb)
{
GUIDFromWStr(&InputInfo->CatDbGuid, L"{127D0A1D-4EF2-11D1-8608-00C04FC295EE}");
}
#ifdef SIGNTOOL_LIST
if (InputInfo->wszListFileName && InputInfo->rgwszFileNames)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/l", L"<filename(s)>");
return FALSE; // Can't use /l and other files
}
#endif
if (InputInfo->Quiet && InputInfo->Verbose)
{
#ifdef SIGNTOOL_DEBUG
if (gDebug)
{
InputInfo->Quiet = FALSE;
}
else
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
return FALSE; // Can't use /q and /v together
}
#else
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
return FALSE; // Can't use /q and /v together
#endif
}
return TRUE; // Success
}
// Helper function specifically for the parameters of the Sign command
BOOL _ParseSignInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo)
{
static WCHAR wszEKU[100];
if (argc < 3) // If there's nothing after the "sign"
{
ResErr(IDS_ERR_NO_PARAMS);
PrintUsage(InputInfo);
return FALSE;
}
for (int i=2; i<argc; i++)
{
if ((wcsncmp(wargv[i], L"/", 1) == 0) ||
(wcsncmp(wargv[i], L"-", 1) == 0))
{
// Then it's a switch.
// Begin switch processing
// Switch to mark end of switches --
if (_wcsicmp(wargv[i]+1, L"-") == 0)
{
// Then we should treat all further parameters as filenames
if ((i+1) < argc)
{
InputInfo->rgwszFileNames = &wargv[i+1];
InputInfo->NumFiles = argc - (i+1);
goto CheckParams; // Done parsing.
}
else
{
ResErr(IDS_ERR_MISSING_FILENAME);
return FALSE; // No filename found after end of switches.
}
}
// Help: /? /h
else if ((_wcsicmp(wargv[i]+1, L"?") == 0) ||
(_wcsicmp(wargv[i]+1, L"h") == 0))
{
PrintUsage(InputInfo);
InputInfo->HelpRequest = TRUE;
return FALSE;
}
#ifdef SIGNTOOL_DEBUG
// Debug (secret switch) /#
else if (_wcsicmp(wargv[i]+1, L"#") == 0)
{
gDebug = TRUE;
InputInfo->Verbose = TRUE;
}
#endif
// Automatic /a
else if (_wcsicmp(wargv[i]+1, L"a") == 0)
{
InputInfo->CatDbSelect = FullAutoCatDb;
}
// Certificate Template /c
else if (_wcsicmp(wargv[i]+1, L"c") == 0)
{
if (InputInfo->wszTemplateName)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszTemplateName = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// CSP
else if (_wcsicmp(wargv[i]+1, L"csp") == 0)
{
if (InputInfo->wszCSP)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszCSP = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Description /d
else if (_wcsicmp(wargv[i]+1, L"d") == 0)
{
if (InputInfo->wszDescription)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszDescription = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Description URL /du
else if (_wcsicmp(wargv[i]+1, L"du") == 0)
{
if (InputInfo->wszDescURL)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszDescURL = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Certificate File /f
else if (_wcsicmp(wargv[i]+1, L"f") == 0)
{
if (InputInfo->wszCertFile)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszCertFile = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Issuer /i
else if (_wcsicmp(wargv[i]+1, L"i") == 0)
{
if (InputInfo->wszIssuerName)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszIssuerName = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Key Container /k
else if (_wcsicmp(wargv[i]+1, L"k") == 0)
{
if (InputInfo->wszContainerName)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszContainerName = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
#ifdef SIGNTOOL_LIST
// File List /l
else if (_wcsicmp(wargv[i]+1, L"l") == 0)
{
if (InputInfo->wszListFileName)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszListFileName = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
#endif
// Subject Name /n
else if (_wcsicmp(wargv[i]+1, L"n") == 0)
{
if (InputInfo->wszSubjectName)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszSubjectName = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Password /p
else if (_wcsicmp(wargv[i]+1, L"p") == 0)
{
if (InputInfo->wszPassword)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszPassword = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Quiet /q
else if (_wcsicmp(wargv[i]+1, L"q") == 0)
{
InputInfo->Quiet = TRUE;
}
// Root /r
else if (_wcsicmp(wargv[i]+1, L"r") == 0)
{
if (InputInfo->wszRootName)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszRootName = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Store /s
else if (_wcsicmp(wargv[i]+1, L"s") == 0)
{
if (InputInfo->wszStoreName)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszStoreName = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Machine Store Location
else if (_wcsicmp(wargv[i]+1, L"sm") == 0)
{
InputInfo->OpenMachineStore = TRUE;
}
// SHA1 Hash /sha1
else if (_wcsicmp(wargv[i]+1, L"sha1") == 0)
{
if (InputInfo->SHA1.cbData)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
if (wcslen(wargv[i+1]) == 40)
{
InputInfo->SHA1.pbData = (BYTE*) malloc(20);
if (InputInfo->SHA1.pbData == NULL)
{
FormatErrRet(L"malloc", GetLastError());
return FALSE; // Unable to allocate SHA1 hash
}
InputInfo->SHA1.cbData = 20;
for (DWORD b=0; b<InputInfo->SHA1.cbData; b++)
{
if (swscanf(wargv[i+1]+(2*b), L"%02X",
&(InputInfo->SHA1.pbData[b])) != 1)
{
ResFormatErr(IDS_ERR_INVALID_SHA1, wargv[i+1]);
return FALSE; // Parameter string is invalid
}
}
i++;
}
else
{
ResFormatErr(IDS_ERR_INVALID_SHA1, wargv[i+1]);
return FALSE; // Parameter string is the wrong size
}
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Timestamp Server URL /t
else if (_wcsicmp(wargv[i]+1, L"t") == 0)
{
if (InputInfo->wszTimeStampURL)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
if (_wcsnicmp(wargv[i+1], L"http://", 7) == 0)
{
InputInfo->wszTimeStampURL = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_BAD_TIMESTAMP_URL, wargv[i+1]);
return FALSE; // Timestamp URL does not begin with http://
}
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Usage /u
else if (_wcsicmp(wargv[i]+1, L"u") == 0)
{
if (InputInfo->wszEKU)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszEKU = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Usage (Windows System Component Verification) /uw
else if (_wcsicmp(wargv[i]+1, L"uw") == 0)
{
if (InputInfo->wszEKU)
{
*(wargv[i]+2) = L'?';
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
// Set the Usage to Windows System Component Verification:
wcscpy(wszEKU, L"1.3.6.1.4.1.311.10.3.6");
InputInfo->wszEKU = wszEKU;
}
// Verbose /v
else if (_wcsicmp(wargv[i]+1, L"v") == 0)
{
InputInfo->Verbose = TRUE;
}
else
{
ResFormatErr(IDS_ERR_INVALID_SWITCH, wargv[i]);
return FALSE; // Invalid switch
}
} // End of switch processing
else
{
// It's not a switch
// So it must be the filename(s) at the end.
InputInfo->rgwszFileNames = &wargv[i];
InputInfo->NumFiles = argc - i;
goto CheckParams; // Done parsing.
}
} // End FOR loop
#ifdef SIGNTOOL_LIST
// Handle the case where no files were passed on the command line
if (InputInfo->wszListFileName)
goto CheckParams; // Done Parsing
#endif
// No filename found after end of switches.
ResErr(IDS_ERR_MISSING_FILENAME);
return FALSE;
CheckParams: // Check for invalid combinations of parameters here:
if (InputInfo->wszPassword && (InputInfo->wszCertFile == NULL))
{
ResFormatErr(IDS_ERR_PARAM_DEPENDENCY, L"/p", L"/f");
return FALSE; // Password specified but no cert file specified.
}
if (InputInfo->wszContainerName && (InputInfo->wszCSP == NULL))
{
ResFormatErr(IDS_ERR_PARAM_DEPENDENCY, L"/k", L"/csp");
return FALSE; // Container Name specified, but to CSP Name.
}
if (InputInfo->wszCSP && (InputInfo->wszContainerName == NULL))
{
ResFormatErr(IDS_ERR_PARAM_DEPENDENCY, L"/csp", L"/k");
return FALSE; // CSP Name specified, but no Container Name.
}
if (InputInfo->wszCertFile && (InputInfo->wszStoreName ||
InputInfo->OpenMachineStore))
{
ResFormatErr(IDS_ERR_PARAM_MULTI_INCOMP, L"/f", L"/s /sm");
return FALSE; // /f means use a file, and /s means use a store.
}
#ifdef SIGNTOOL_LIST
if (InputInfo->wszListFileName && InputInfo->rgwszFileNames)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/l", L"<filename(s)>");
return FALSE; // Can't use /l and other files
}
#endif
if (InputInfo->Quiet && InputInfo->Verbose)
{
#ifdef SIGNTOOL_DEBUG
if (gDebug)
{
InputInfo->Quiet = FALSE;
}
else
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
return FALSE; // Can't use /q and /v together
}
#else
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
return FALSE; // Can't use /q and /v together
#endif
}
return TRUE; // Success
}
// Helper function specifically for the parameters of the SignWizard command
BOOL _ParseSignWizardInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo)
{
if (argc < 3) // If there's nothing after the "SignWizard"
{
// No problem.
return TRUE;
}
for (int i=2; i<argc; i++)
{
if ((wcsncmp(wargv[i], L"/", 1) == 0) ||
(wcsncmp(wargv[i], L"-", 1) == 0))
{
// Then it's a switch.
// Begin switch processing
// Switch to mark end of switches --
if (_wcsicmp(wargv[i]+1, L"-") == 0)
{
// Then we should treat all further parameters as filenames
if ((i+1) < argc)
{
InputInfo->rgwszFileNames = &wargv[i+1];
InputInfo->NumFiles = argc - (i+1);
goto CheckParams; // Done parsing.
}
else
{
ResErr(IDS_ERR_MISSING_FILENAME);
return FALSE; // No filename found after end of switches.
}
}
// Help: /? /h
else if ((_wcsicmp(wargv[i]+1, L"?") == 0) ||
(_wcsicmp(wargv[i]+1, L"h") == 0))
{
PrintUsage(InputInfo);
InputInfo->HelpRequest = TRUE;
return FALSE;
}
#ifdef SIGNTOOL_DEBUG
// Debug (secret switch) /#
else if (_wcsicmp(wargv[i]+1, L"#") == 0)
{
gDebug = TRUE;
InputInfo->Verbose = TRUE;
}
#endif
#ifdef SIGNTOOL_LIST
// File List /l
else if (_wcsicmp(wargv[i]+1, L"l") == 0)
{
if (InputInfo->wszListFileName)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszListFileName = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
#endif
// Quiet /q
else if (_wcsicmp(wargv[i]+1, L"q") == 0)
{
InputInfo->Quiet = TRUE;
}
// Verbose /v
else if (_wcsicmp(wargv[i]+1, L"v") == 0)
{
InputInfo->Verbose = TRUE;
}
else
{
ResFormatErr(IDS_ERR_INVALID_SWITCH, wargv[i]);
return FALSE; // Invalid switch
}
} // End of switch processing
else
{
// It's not a switch
// So it must be the filename(s) at the end.
InputInfo->rgwszFileNames = &wargv[i];
InputInfo->NumFiles = argc - i;
goto CheckParams; // Done parsing.
}
} // End FOR loop
// It is OK if no filenames were found after end of switches.
CheckParams:
#ifdef SIGNTOOL_LIST
if (InputInfo->wszListFileName && InputInfo->rgwszFileNames)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/l", L"<filename(s)>");
return FALSE; // Can't use /l and other files
}
#endif
if (InputInfo->Quiet && InputInfo->Verbose)
{
#ifdef SIGNTOOL_DEBUG
if (gDebug)
{
InputInfo->Quiet = FALSE;
}
else
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
return FALSE; // Can't use /q and /v together
}
#else
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
return FALSE; // Can't use /q and /v together
#endif
}
return TRUE; // Success
}
// Helper function specifically for the parameters of the Timestamp command
BOOL _ParseTimestampInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo)
{
if (argc < 3) // If there's nothing after the "timestamp"
{
ResErr(IDS_ERR_NO_PARAMS);
PrintUsage(InputInfo);
return FALSE;
}
for (int i=2; i<argc; i++)
{
if ((wcsncmp(wargv[i], L"/", 1) == 0) ||
(wcsncmp(wargv[i], L"-", 1) == 0))
{
// Then it's a switch.
// Begin switch processing
// Switch to mark end of switches --
if (_wcsicmp(wargv[i]+1, L"-") == 0)
{
// Then we should treat all further parameters as filenames
if ((i+1) < argc)
{
InputInfo->rgwszFileNames = &wargv[i+1];
InputInfo->NumFiles = argc - (i+1);
goto CheckParams; // Done parsing.
}
else
{
ResErr(IDS_ERR_MISSING_FILENAME);
return FALSE; // No filename found after end of switches.
}
}
// Help: /? /h
else if ((_wcsicmp(wargv[i]+1, L"?") == 0) ||
(_wcsicmp(wargv[i]+1, L"h") == 0))
{
PrintUsage(InputInfo);
InputInfo->HelpRequest = TRUE;
return FALSE;
}
#ifdef SIGNTOOL_DEBUG
// Debug (secret switch) /#
else if (_wcsicmp(wargv[i]+1, L"#") == 0)
{
gDebug = TRUE;
InputInfo->Verbose = TRUE;
}
#endif
#ifdef SIGNTOOL_LIST
// File List /l
else if (_wcsicmp(wargv[i]+1, L"l") == 0)
{
if (InputInfo->wszListFileName)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszListFileName = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
#endif
// Timestamp Server URL /t
else if (_wcsicmp(wargv[i]+1, L"t") == 0)
{
if (InputInfo->wszTimeStampURL)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
if (_wcsnicmp(wargv[i+1], L"http://", 7) != 0)
{
ResFormatErr(IDS_ERR_BAD_TIMESTAMP_URL, wargv[i+1]);
return FALSE; // Timestamp URL does not begin with http://
}
InputInfo->wszTimeStampURL = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Quiet /q
else if (_wcsicmp(wargv[i]+1, L"q") == 0)
{
InputInfo->Quiet = TRUE;
}
// Verbose /v
else if (_wcsicmp(wargv[i]+1, L"v") == 0)
{
InputInfo->Verbose = TRUE;
}
else
{
ResFormatErr(IDS_ERR_INVALID_SWITCH, wargv[i]);
return FALSE; // Invalid switch
}
} // End of switch processing
else
{
// It's not a switch
// So it must be the filename(s) at the end.
InputInfo->rgwszFileNames = &wargv[i];
InputInfo->NumFiles = argc - i;
goto CheckParams; // Done parsing.
}
} // End FOR loop
#ifdef SIGNTOOL_LIST
// Handle the case where no files were passed on the command line
if (InputInfo->wszListFileName)
goto CheckParams; // Done Parsing
#endif
// No filename found after end of switches.
ResErr(IDS_ERR_MISSING_FILENAME);
return FALSE;
CheckParams:
if (InputInfo->wszTimeStampURL == NULL)
{
ResFormatErr(IDS_ERR_PARAM_REQUIRED, L"/t");
return FALSE; // /t is required.
}
#ifdef SIGNTOOL_LIST
if (InputInfo->wszListFileName && InputInfo->rgwszFileNames)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/l", L"<filename(s)>");
return FALSE; // Can't use /l and other files
}
#endif
if (InputInfo->Quiet && InputInfo->Verbose)
{
#ifdef SIGNTOOL_DEBUG
if (gDebug)
{
InputInfo->Quiet = FALSE;
}
else
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
return FALSE; // Can't use /q and /v together
}
#else
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
return FALSE; // Can't use /q and /v together
#endif
}
return TRUE; // Success
}
// Helper function specifically for the parameters of the Verify command
BOOL _ParseVerifyInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo)
{
if (argc < 3) // If there's nothing after the "verify"
{
ResErr(IDS_ERR_NO_PARAMS);
PrintUsage(InputInfo);
return FALSE;
}
for (int i=2; i<argc; i++)
{
if ((wcsncmp(wargv[i], L"/", 1) == 0) ||
(wcsncmp(wargv[i], L"-", 1) == 0))
{
// Then it's a switch.
// Begin switch processing
// Switch to mark end of switches --
if (_wcsicmp(wargv[i]+1, L"-") == 0)
{
// Then we should treat all further parameters as filenames
if ((i+1) < argc)
{
InputInfo->rgwszFileNames = &wargv[i+1];
InputInfo->NumFiles = argc - (i+1);
goto CheckParams; // Done parsing.
}
else
{
ResErr(IDS_ERR_MISSING_FILENAME);
return FALSE; // No filename found after end of switches.
}
}
// Help: /? /h
else if ((_wcsicmp(wargv[i]+1, L"?") == 0) ||
(_wcsicmp(wargv[i]+1, L"h") == 0))
{
PrintUsage(InputInfo);
InputInfo->HelpRequest = TRUE;
return FALSE;
}
#ifdef SIGNTOOL_DEBUG
// Debug (secret switch) /#
else if (_wcsicmp(wargv[i]+1, L"#") == 0)
{
gDebug = TRUE;
InputInfo->Verbose = TRUE;
}
#endif
// Automatic (All Catalogs) /a
else if (_wcsicmp(wargv[i]+1, L"a") == 0)
{
if (InputInfo->wszCatFile)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/a");
return FALSE;
}
if (InputInfo->CatDbSelect != NoCatDb)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
InputInfo->CatDbSelect = FullAutoCatDb;
}
// Automatic (Default) /ad
else if (_wcsicmp(wargv[i]+1, L"ad") == 0)
{
if (InputInfo->wszCatFile)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/ad");
return FALSE;
}
if (InputInfo->CatDbSelect != NoCatDb)
{
*(wargv[i]+2) = L'?';
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
InputInfo->CatDbSelect = DefaultCatDb;
GUIDFromWStr(&InputInfo->CatDbGuid, L"{127D0A1D-4EF2-11D1-8608-00C04FC295EE}");
}
// Automatic (System) /as
else if (_wcsicmp(wargv[i]+1, L"as") == 0)
{
if (InputInfo->wszCatFile)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/as");
return FALSE;
}
if (InputInfo->CatDbSelect != NoCatDb)
{
*(wargv[i]+2) = L'?';
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
InputInfo->CatDbSelect = SystemCatDb;
GUIDFromWStr(&InputInfo->CatDbGuid, L"{F750E6C3-38EE-11D1-85E5-00C04FC295EE}");
}
// Automatic (System) /ag
else if (_wcsicmp(wargv[i]+1, L"ag") == 0)
{
if (InputInfo->wszCatFile)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/ag");
return FALSE;
}
if (InputInfo->CatDbSelect != NoCatDb)
{
*(wargv[i]+2) = L'?';
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
InputInfo->CatDbSelect = GuidCatDb;
if ((i+1) < argc)
{
if (GUIDFromWStr(&InputInfo->CatDbGuid, wargv[i+1]))
{
i++;
}
else
{
ResFormatErr(IDS_ERR_INVALID_GUID, wargv[i+1]);
return FALSE; // Invalid GUID format
}
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No GUID found after /ag
}
}
// Catalog File /c
else if (_wcsicmp(wargv[i]+1, L"c") == 0)
{
if (InputInfo->wszCatFile)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if (InputInfo->CatDbSelect == FullAutoCatDb)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/a");
return FALSE; // Incompatible switches
}
if (InputInfo->CatDbSelect == DefaultCatDb)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/ad");
return FALSE; // Incompatible switches
}
if (InputInfo->CatDbSelect == GuidCatDb)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/ag");
return FALSE; // Incompatible switches
}
if (InputInfo->CatDbSelect == SystemCatDb)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/as");
return FALSE; // Incompatible switches
}
if ((i+1) < argc)
{
InputInfo->wszCatFile = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
#ifdef SIGNTOOL_LIST
// File List /l
else if (_wcsicmp(wargv[i]+1, L"l") == 0)
{
if (InputInfo->wszListFileName)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszListFileName = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
#endif
// OS Version /o
else if (_wcsicmp(wargv[i]+1, L"o") == 0)
{
if (InputInfo->wszVersion)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->dwBuildNumber = 0;
if (!((swscanf(wargv[i+1], L"%d:%d.%d.%d",
&InputInfo->dwPlatform,
&InputInfo->dwMajorVersion,
&InputInfo->dwMinorVersion,
&InputInfo->dwBuildNumber) == 4) ||
(swscanf(wargv[i+1], L"%d:%d.%d",
&InputInfo->dwPlatform,
&InputInfo->dwMajorVersion,
&InputInfo->dwMinorVersion) == 3)) ||
(InputInfo->dwPlatform == 0))
{
ResFormatErr(IDS_ERR_INVALID_VERSION, wargv[i+1]);
return FALSE;
}
InputInfo->wszVersion = wargv[i+1];
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// Policy (Default Authenticode) /pa (used to be /pd)
else if ((_wcsicmp(wargv[i]+1, L"pa") == 0) || (_wcsicmp(wargv[i]+1, L"pd") == 0))
{
if (InputInfo->Policy != SystemDriver)
{
*(wargv[i]+2) = L'?';
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
InputInfo->Policy = DefaultAuthenticode;
}
// Policy (Specify by GUID) /pg
else if (_wcsicmp(wargv[i]+1, L"pg") == 0)
{
if (InputInfo->Policy != SystemDriver)
{
*(wargv[i]+2) = L'?';
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
InputInfo->Policy = GuidActionID;
if ((i+1) < argc)
{
if (GUIDFromWStr(&InputInfo->PolicyGuid, wargv[i+1]))
{
i++;
}
else
{
ResFormatErr(IDS_ERR_INVALID_GUID, wargv[i+1]);
return FALSE; // Invalid GUID format
}
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No GUID found after /pg
}
}
// Quiet /q
else if (_wcsicmp(wargv[i]+1, L"q") == 0)
{
InputInfo->Quiet = TRUE;
}
// Root Name /r
else if (_wcsicmp(wargv[i]+1, L"r") == 0)
{
if (InputInfo->wszRootName)
{
ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
return FALSE; // You cannot use the same switch twice.
}
if ((i+1) < argc)
{
InputInfo->wszRootName = wargv[i+1];
// This string will be compared with a lowercased string.
_wcslwr(InputInfo->wszRootName);
i++;
}
else
{
ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
return FALSE; // No Parameter found.
}
}
// TimeStamp Warn /tw
else if (_wcsicmp(wargv[i]+1, L"tw") == 0)
{
InputInfo->TSWarn = TRUE;
}
// Verbose /v
else if (_wcsicmp(wargv[i]+1, L"v") == 0)
{
InputInfo->Verbose = TRUE;
}
else
{
ResFormatErr(IDS_ERR_INVALID_SWITCH, wargv[i]);
return FALSE; // Invalid switch
}
} // End of switch processing
else
{
// It's not a switch
// So it must be the filename(s) at the end.
InputInfo->rgwszFileNames = &wargv[i];
InputInfo->NumFiles = argc - i;
goto CheckParams; // Done parsing.
}
} // End FOR loop
#ifdef SIGNTOOL_LIST
// Handle the case where no files were passed on the command line
if (InputInfo->wszListFileName)
goto CheckParams; // Done Parsing
#endif
// No filename found after end of switches.
ResErr(IDS_ERR_MISSING_FILENAME);
return FALSE;
CheckParams:
if (InputInfo->wszVersion && !((InputInfo->CatDbSelect != NoCatDb) ||
InputInfo->wszCatFile))
{
ResFormatErr(IDS_ERR_PARAM_MULTI_DEP, L"/o", L"/a /ad /ag /as /c");
return FALSE; // OS Version switch requires catalog options (/a? or /c)
}
#ifdef SIGNTOOL_LIST
if (InputInfo->wszListFileName && InputInfo->rgwszFileNames)
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/l", L"<filename(s)>");
return FALSE; // Can't use /l and other files
}
#endif
if (InputInfo->Quiet && InputInfo->Verbose)
{
#ifdef SIGNTOOL_DEBUG
if (gDebug)
{
InputInfo->Quiet = FALSE;
}
else
{
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
return FALSE; // Can't use /q and /v together
}
#else
ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
return FALSE; // Can't use /q and /v together
#endif
}
return TRUE; // Success
}