//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 2001 // // File: signtool.cpp // // Contents: The SignTool console tool // // History: 4/30/2001 SCoyne Created // //---------------------------------------------------------------------------- #include #include #include #include #include #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; irgwszFileNames = &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""); 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; irgwszFileNames = &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; bSHA1.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""); 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; irgwszFileNames = &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""); 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; irgwszFileNames = &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""); 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; irgwszFileNames = &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""); 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 }