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

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2001
  5. //
  6. // File: signtool.cpp
  7. //
  8. // Contents: The SignTool console tool
  9. //
  10. // History: 4/30/2001 SCoyne Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <windows.h>
  16. #include <unicode.h>
  17. #include <locale.h>
  18. #include "resource.h"
  19. #include "signtool.h"
  20. #ifdef SIGNTOOL_DEBUG
  21. #include "signtooldebug.h"
  22. BOOL gDebug; // Global
  23. #endif
  24. typedef WINBASEAPI BOOL (*FUNC_ISWOW64) (HANDLE, PBOOL);
  25. // Global Variables:
  26. HINSTANCE hModule;
  27. // wmain returns 0 on success, 1 on error, and 2 on warning
  28. extern "C" int __cdecl wmain(int argc, WCHAR **wargv)
  29. {
  30. INPUTINFO InputInfo;
  31. WCHAR wszResource[MAX_RES_LEN];
  32. WCHAR *wszLocale = NULL;
  33. HMODULE hModTemp;
  34. FUNC_ISWOW64 fnIsWow64;
  35. BOOL fTemp;
  36. int iReturn;
  37. // Initialize InputInfo
  38. memset(&InputInfo, 0, sizeof(INPUTINFO));
  39. // Initialize Module Handle
  40. if ((hModule=GetModuleHandleA(NULL)) == NULL)
  41. {
  42. // In this case resources cannot be loaded, so English will have to do:
  43. wprintf(L"SignTool Error: GetModuleHandle returned: 0x%08X\n",
  44. GetLastError());
  45. iReturn = 1; // Initialization Error
  46. goto Cleanup;
  47. }
  48. // Set Locale
  49. if (LoadStringU(hModule, IDS_LOCALE, wszResource, MAX_RES_LEN))
  50. {
  51. wszLocale = _wsetlocale(LC_ALL, wszResource);
  52. }
  53. #ifdef SIGNTOOL_DEBUG
  54. if (!wszLocale)
  55. {
  56. wprintf(L"Failed to set locale to: %s\n", wszResource);
  57. }
  58. #endif
  59. // Parse Arguments into InputInfo structure
  60. if (!ParseInputs(argc, wargv, &InputInfo))
  61. {
  62. if (InputInfo.HelpRequest)
  63. {
  64. return 0; // Successfully completed user request for help
  65. }
  66. else
  67. {
  68. iReturn = 1; // Any other Parameter-Parsing Error
  69. goto Cleanup;
  70. }
  71. }
  72. // Determine if we are under WOW64
  73. hModTemp = GetModuleHandleA("kernel32.dll");
  74. if (hModTemp)
  75. {
  76. fnIsWow64 = (FUNC_ISWOW64) GetProcAddress(hModTemp, "IsWow64Process");
  77. if (fnIsWow64 &&
  78. fnIsWow64(GetCurrentProcess(), &fTemp))
  79. {
  80. InputInfo.fIsWow64Process = fTemp;
  81. }
  82. }
  83. #ifdef SIGNTOOL_DEBUG
  84. // Print debug info if debug support is compiled in, and the debug
  85. // switch was specified:
  86. if (gDebug)
  87. PrintInputInfo(&InputInfo);
  88. #endif
  89. // Perform the requested action:
  90. switch (InputInfo.Command)
  91. {
  92. case CatDb:
  93. iReturn = SignTool_CatDb(&InputInfo);
  94. break;
  95. case Sign:
  96. iReturn = SignTool_Sign(&InputInfo);
  97. break;
  98. case SignWizard:
  99. iReturn = SignTool_SignWizard(&InputInfo);
  100. break;
  101. case Timestamp:
  102. iReturn = SignTool_Timestamp(&InputInfo);
  103. break;
  104. case Verify:
  105. iReturn = SignTool_Verify(&InputInfo);
  106. break;
  107. default:
  108. ResErr(IDS_ERR_UNEXPECTED); // This should never happen
  109. iReturn = 1; // Error
  110. }
  111. Cleanup:
  112. #ifdef SIGNTOOL_LIST
  113. if (InputInfo.wszListFileContents)
  114. free(InputInfo.wszListFileContents);
  115. #endif
  116. return iReturn;
  117. }
  118. // PrintUsage automatically prints the relevant Usage based on InputInfo.
  119. void PrintUsage(INPUTINFO *InputInfo)
  120. {
  121. switch (InputInfo->Command)
  122. {
  123. default:
  124. case CommandNone: // Then print top-level Usage
  125. ResErr(IDS_SIGNTOOL_USAGE);
  126. break;
  127. case CatDb:
  128. ResErr(IDS_CATDB_USAGE);
  129. ResErr(IDS_CATDB_DB_SELECT_OPTIONS);
  130. ResErr(IDS_CATDB_D);
  131. ResErr(IDS_CATDB_G);
  132. ResErr(IDS_CATDB_OTHER_OPTIONS);
  133. ResErr(IDS_CATDB_Q);
  134. ResErr(IDS_CATDB_R);
  135. ResErr(IDS_CATDB_U);
  136. ResErr(IDS_CATDB_V);
  137. break;
  138. case Sign:
  139. ResErr(IDS_SIGN_USAGE);
  140. ResErr(IDS_SIGN_CERT_OPTIONS);
  141. ResErr(IDS_SIGN_A);
  142. ResErr(IDS_SIGN_C);
  143. ResErr(IDS_SIGN_F);
  144. ResErr(IDS_SIGN_I);
  145. ResErr(IDS_SIGN_N);
  146. ResErr(IDS_SIGN_P);
  147. ResErr(IDS_SIGN_R);
  148. ResErr(IDS_SIGN_S);
  149. ResErr(IDS_SIGN_SM);
  150. ResErr(IDS_SIGN_SHA1);
  151. ResErr(IDS_SIGN_U);
  152. ResErr(IDS_SIGN_UW);
  153. ResErr(IDS_SIGN_PRIV_KEY_OPTIONS);
  154. ResErr(IDS_SIGN_CSP);
  155. ResErr(IDS_SIGN_K);
  156. ResErr(IDS_SIGN_SIGNING_OPTIONS);
  157. ResErr(IDS_SIGN_D);
  158. ResErr(IDS_SIGN_DU);
  159. ResErr(IDS_SIGN_T);
  160. ResErr(IDS_SIGN_OTHER_OPTIONS);
  161. ResErr(IDS_SIGN_Q);
  162. ResErr(IDS_SIGN_V);
  163. break;
  164. case SignWizard:
  165. ResErr(IDS_SIGNWIZARD_USAGE);
  166. ResErr(IDS_SIGNWIZARD_OPTIONS);
  167. ResErr(IDS_SIGNWIZARD_Q);
  168. ResErr(IDS_SIGNWIZARD_V);
  169. break;
  170. case Timestamp:
  171. ResErr(IDS_TIMESTAMP_USAGE);
  172. ResErr(IDS_TIMESTAMP_Q);
  173. ResErr(IDS_TIMESTAMP_T);
  174. ResErr(IDS_TIMESTAMP_V);
  175. break;
  176. case Verify:
  177. ResErr(IDS_VERIFY_USAGE);
  178. ResErr(IDS_VERIFY_CATALOG_OPTIONS);
  179. ResErr(IDS_VERIFY_A);
  180. ResErr(IDS_VERIFY_AD);
  181. ResErr(IDS_VERIFY_AS);
  182. ResErr(IDS_VERIFY_AG);
  183. ResErr(IDS_VERIFY_C);
  184. ResErr(IDS_VERIFY_O);
  185. ResErr(IDS_VERIFY_POLICY_OPTIONS);
  186. ResErr(IDS_VERIFY_PD);
  187. ResErr(IDS_VERIFY_PG);
  188. ResErr(IDS_VERIFY_SIG_OPTIONS);
  189. ResErr(IDS_VERIFY_R);
  190. ResErr(IDS_VERIFY_TW);
  191. ResErr(IDS_VERIFY_OTHER_OPTIONS);
  192. ResErr(IDS_VERIFY_Q);
  193. ResErr(IDS_VERIFY_V);
  194. break;
  195. }
  196. }
  197. // Error Functions:
  198. void Res_Err(DWORD dwRes)
  199. {
  200. static WCHAR wszResource[MAX_RES_LEN];
  201. if (LoadStringU(hModule, dwRes, wszResource, MAX_RES_LEN))
  202. {
  203. fwprintf(stderr, L"%s", wszResource);
  204. }
  205. else
  206. {
  207. fwprintf(stderr, L"********** %u **********\n", dwRes);
  208. }
  209. }
  210. void ResOut(DWORD dwRes)
  211. {
  212. static WCHAR wszResource[MAX_RES_LEN];
  213. if (LoadStringU(hModule, dwRes, wszResource, MAX_RES_LEN))
  214. {
  215. wprintf(L"%s", wszResource);
  216. }
  217. else
  218. {
  219. wprintf(L"********** %u **********\n", dwRes);
  220. }
  221. }
  222. void ResFormat_Err(DWORD dwRes, ...)
  223. {
  224. static WCHAR wszResource[MAX_RES_LEN];
  225. static WCHAR *lpMsgBuf = NULL;
  226. static va_list vaList;
  227. va_start(vaList, dwRes);
  228. if (LoadStringU(hModule, dwRes, wszResource, MAX_RES_LEN) &&
  229. FormatMessageU(FORMAT_MESSAGE_FROM_STRING |
  230. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  231. wszResource,
  232. 0,
  233. 0,
  234. (LPWSTR) &lpMsgBuf,
  235. MAX_RES_LEN,
  236. &vaList))
  237. {
  238. fwprintf(stderr, L"%s", lpMsgBuf);
  239. LocalFree(lpMsgBuf);
  240. }
  241. else
  242. {
  243. fwprintf(stderr, L"********** %u **********\n", dwRes);
  244. }
  245. va_end(vaList);
  246. }
  247. void ResFormatOut(DWORD dwRes, ...)
  248. {
  249. static WCHAR wszResource[MAX_RES_LEN];
  250. static WCHAR *lpMsgBuf = NULL;
  251. static va_list vaList;
  252. va_start(vaList, dwRes);
  253. if (LoadStringU(hModule, dwRes, wszResource, MAX_RES_LEN) &&
  254. FormatMessageU(FORMAT_MESSAGE_FROM_STRING |
  255. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  256. wszResource,
  257. 0,
  258. 0,
  259. (LPWSTR) &lpMsgBuf,
  260. MAX_RES_LEN,
  261. &vaList))
  262. {
  263. wprintf(L"%s", lpMsgBuf);
  264. LocalFree(lpMsgBuf);
  265. }
  266. else
  267. {
  268. wprintf(L"********** %u **********\n", dwRes);
  269. }
  270. va_end(vaList);
  271. }
  272. void Format_ErrRet(WCHAR *wszFunc, DWORD dwErr)
  273. {
  274. WCHAR *lpMsgBuf = NULL;
  275. if (FormatMessageU(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  276. FORMAT_MESSAGE_FROM_SYSTEM |
  277. FORMAT_MESSAGE_IGNORE_INSERTS,
  278. NULL,
  279. dwErr,
  280. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  281. (LPWSTR) &lpMsgBuf,
  282. 0,
  283. NULL))
  284. {
  285. ResFormat_Err(IDS_ERR_FUNCTION, wszFunc, dwErr, lpMsgBuf);
  286. LocalFree(lpMsgBuf);
  287. }
  288. else
  289. {
  290. ResFormat_Err(IDS_ERR_FUNCTION, wszFunc, dwErr, L"");
  291. }
  292. }
  293. BOOL GUIDFromWStr(GUID *guid, LPWSTR str)
  294. {
  295. DWORD i;
  296. DWORD temp[8];
  297. if ((wcslen(str) == 38) &&
  298. (wcsncmp(str, L"{", 1) == 0) &&
  299. (wcsncmp(&(str[37]), L"}", 1) == 0) &&
  300. (swscanf(str,
  301. L"{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  302. &guid->Data1, &guid->Data2, &guid->Data3, &temp[0],
  303. &temp[1], &temp[2], &temp[3], &temp[4],
  304. &temp[5], &temp[6], &temp[7]) == 11))
  305. {
  306. for (i=0; i<8; i++)
  307. guid->Data4[i] = (BYTE) temp[i];
  308. return TRUE;
  309. }
  310. else
  311. memset(guid, 0, sizeof(GUID));
  312. return FALSE;
  313. }
  314. /*********************************************************************
  315. * *
  316. * Command Parsing section: *
  317. * *
  318. *********************************************************************/
  319. // ParseInputs returns TRUE if parameters were parsed successfully,
  320. // FALSE otherwise.
  321. BOOL ParseInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo)
  322. {
  323. FILE *hFileList;
  324. LPWSTR wszTemp;
  325. WCHAR wc;
  326. DWORD dwSize;
  327. DWORD dwRead;
  328. DWORD dwCount;
  329. // Private Function Declarations:
  330. BOOL _ParseCatDbInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo);
  331. BOOL _ParseSignInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo);
  332. BOOL _ParseSignWizardInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo);
  333. BOOL _ParseTimestampInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo);
  334. BOOL _ParseVerifyInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo);
  335. // (These should never be called from any other functions)
  336. if (argc <= 1) // If no parameters were specified
  337. {
  338. ResErr(IDS_ERR_NO_PARAMS);
  339. PrintUsage(InputInfo);
  340. return FALSE; // Print Usage
  341. }
  342. // Check the first parameter to see which command we are performing:
  343. // Is it "CATDB" ?
  344. if (_wcsicmp(wargv[1], L"CATDB") == 0)
  345. {
  346. InputInfo->Command = CatDb;
  347. if (!_ParseCatDbInputs(argc, wargv, InputInfo))
  348. return FALSE;
  349. }
  350. // Is it "SIGN" ?
  351. else if (_wcsicmp(wargv[1], L"SIGN") == 0)
  352. {
  353. InputInfo->Command = Sign;
  354. if (!_ParseSignInputs(argc, wargv, InputInfo))
  355. return FALSE;
  356. }
  357. // Is it "SIGNWIZARD" ?
  358. else if (_wcsicmp(wargv[1], L"SIGNWIZARD") == 0)
  359. {
  360. InputInfo->Command = SignWizard;
  361. if (!_ParseSignWizardInputs(argc, wargv, InputInfo))
  362. return FALSE;
  363. }
  364. // Is it "TIMESTAMP" ?
  365. else if (_wcsicmp(wargv[1], L"TIMESTAMP") == 0)
  366. {
  367. InputInfo->Command = Timestamp;
  368. if (!_ParseTimestampInputs(argc, wargv, InputInfo))
  369. return FALSE;
  370. }
  371. // Is it "VERIFY" ?
  372. else if (_wcsicmp(wargv[1], L"VERIFY") == 0)
  373. {
  374. InputInfo->Command = Verify;
  375. if (!_ParseVerifyInputs(argc, wargv, InputInfo))
  376. return FALSE;
  377. }
  378. // Is it a request for help?
  379. else if ((_wcsicmp(wargv[1], L"/?") == 0) ||
  380. (_wcsicmp(wargv[1], L"-?") == 0) ||
  381. (_wcsicmp(wargv[1], L"/h") == 0) ||
  382. (_wcsicmp(wargv[1], L"-h") == 0))
  383. {
  384. PrintUsage(InputInfo);
  385. InputInfo->HelpRequest = TRUE;
  386. return FALSE;
  387. }
  388. // Or is it unrecognized?
  389. else
  390. {
  391. ResFormatErr(IDS_ERR_INVALID_COMMAND, wargv[1]);
  392. PrintUsage(InputInfo);
  393. return FALSE;
  394. }
  395. // To reach here, one of the _Parse_X_Inputs must have succeeded
  396. #ifdef SIGNTOOL_LIST
  397. // Expand the File List if necessary
  398. if (InputInfo->wszListFileName)
  399. {
  400. // Open the file
  401. hFileList = _wfopen(InputInfo->wszListFileName, L"rt");
  402. if (hFileList == NULL)
  403. {
  404. ResFormatErr(IDS_ERR_OPENING_FILE_LIST, InputInfo->wszListFileName);
  405. PrintUsage(InputInfo);
  406. return FALSE;
  407. }
  408. // Go to the beginning
  409. if (fseek(hFileList, SEEK_SET, 0) != 0)
  410. {
  411. ResErr(IDS_ERR_UNEXPECTED);
  412. fclose(hFileList);
  413. return FALSE;
  414. }
  415. // Get the full file size
  416. // Do it this way to actually count the number of characters in the file
  417. dwSize = 0;
  418. while (fgetwc(hFileList) != WEOF)
  419. {
  420. dwSize++;
  421. }
  422. // Go back to the beginning
  423. if (fseek(hFileList, SEEK_SET, 0) != 0)
  424. {
  425. ResErr(IDS_ERR_UNEXPECTED);
  426. fclose(hFileList);
  427. return FALSE;
  428. }
  429. // Allocate a buffer big enough for all of it
  430. InputInfo->wszListFileContents = (WCHAR*) malloc((dwSize + 1) * sizeof(WCHAR));
  431. if (InputInfo->wszListFileContents == NULL)
  432. {
  433. FormatErrRet(L"malloc", ERROR_OUTOFMEMORY);
  434. fclose(hFileList);
  435. return FALSE;
  436. }
  437. // Read the file into the buffer
  438. dwRead = 0;
  439. while ((dwRead < dwSize) && ((wc = getwc(hFileList)) != WEOF))
  440. {
  441. InputInfo->wszListFileContents[dwRead] = wc;
  442. dwRead++;
  443. }
  444. // Sanity Check
  445. if (dwRead != dwSize)
  446. {
  447. ResErr(IDS_ERR_UNEXPECTED);
  448. fclose(hFileList);
  449. return FALSE;
  450. }
  451. // Adjust for Unicode header if necessary
  452. // if ((lSize > 1) && (InputInfo->wszListFileContents[0] == 0xFEFF))
  453. // {
  454. // InputInfo->wszListFileContents++;
  455. // lSize--;
  456. // }
  457. // NULL terminate the final string (to be safe)
  458. InputInfo->wszListFileContents[dwSize] = L'\0';
  459. // Count the number of lines
  460. wszTemp = InputInfo->wszListFileContents;
  461. dwCount = 1;
  462. while ((wszTemp = wcschr(wszTemp, L'\n')) != NULL)
  463. {
  464. wszTemp++;
  465. dwCount++;
  466. }
  467. // Allocate the buffer for the pointers
  468. InputInfo->rgwszFileNames = (LPWSTR*) malloc(dwCount * sizeof(LPWSTR));
  469. if (InputInfo->rgwszFileNames == NULL)
  470. {
  471. FormatErrRet(L"malloc", ERROR_OUTOFMEMORY);
  472. fclose(hFileList);
  473. return FALSE;
  474. }
  475. // Assign the lines to the FileNames array
  476. wszTemp = InputInfo->wszListFileContents;
  477. InputInfo->NumFiles = 0;
  478. while (wszTemp)
  479. {
  480. InputInfo->rgwszFileNames[InputInfo->NumFiles] = wszTemp;
  481. wszTemp = wcschr(wszTemp, L'\n');
  482. if (wszTemp)
  483. {
  484. *wszTemp = L'\0';
  485. wszTemp++;
  486. }
  487. if (wcslen(InputInfo->rgwszFileNames[InputInfo->NumFiles]) > 0)
  488. InputInfo->NumFiles++;
  489. }
  490. fclose(hFileList);
  491. }
  492. #endif // SIGNTOOL_LIST
  493. return TRUE;
  494. }
  495. // Helper function specifically for the parameters of the CatDb command
  496. BOOL _ParseCatDbInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo)
  497. {
  498. if (argc < 3) // If there's nothing after the "CatDb"
  499. {
  500. ResErr(IDS_ERR_NO_PARAMS);
  501. PrintUsage(InputInfo);
  502. return FALSE;
  503. }
  504. for (int i=2; i<argc; i++)
  505. {
  506. if ((wcsncmp(wargv[i], L"/", 1) == 0) ||
  507. (wcsncmp(wargv[i], L"-", 1) == 0))
  508. {
  509. // Then it's a switch.
  510. // Begin switch processing
  511. // Switch to mark end of switches --
  512. if (_wcsicmp(wargv[i]+1, L"-") == 0)
  513. {
  514. // Then we should treat all further parameters as filenames
  515. if ((i+1) < argc)
  516. {
  517. InputInfo->rgwszFileNames = &wargv[i+1];
  518. InputInfo->NumFiles = argc - (i+1);
  519. goto CheckParams; // Done parsing.
  520. }
  521. else
  522. {
  523. ResErr(IDS_ERR_MISSING_FILENAME);
  524. return FALSE; // No filename found after end of switches.
  525. }
  526. }
  527. // Help: /? /h
  528. else if ((_wcsicmp(wargv[i]+1, L"?") == 0) ||
  529. (_wcsicmp(wargv[i]+1, L"h") == 0))
  530. {
  531. PrintUsage(InputInfo);
  532. InputInfo->HelpRequest = TRUE;
  533. return FALSE;
  534. }
  535. #ifdef SIGNTOOL_DEBUG
  536. // Debug (secret switch) /#
  537. else if (_wcsicmp(wargv[i]+1, L"#") == 0)
  538. {
  539. gDebug = TRUE;
  540. InputInfo->Verbose = TRUE;
  541. }
  542. #endif
  543. // Use Default CatDb /d
  544. else if (_wcsicmp(wargv[i]+1, L"d") == 0)
  545. {
  546. switch (InputInfo->CatDbSelect)
  547. {
  548. case GuidCatDb:
  549. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/d", L"/g");
  550. return FALSE; // You cannot use the same type of switch twice.
  551. case DefaultCatDb:
  552. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  553. return FALSE; // You cannot use the same switch twice.
  554. case NoCatDb:
  555. InputInfo->CatDbSelect = DefaultCatDb;
  556. break;
  557. default:
  558. ResErr(IDS_ERR_UNEXPECTED); // This should never happen
  559. return FALSE; // Error
  560. }
  561. }
  562. // CatDb Guid /g
  563. else if (_wcsicmp(wargv[i]+1, L"g") == 0)
  564. {
  565. switch (InputInfo->CatDbSelect)
  566. {
  567. case GuidCatDb:
  568. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  569. return FALSE; // You cannot use the same switch twice.
  570. case DefaultCatDb:
  571. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/g", L"/d");
  572. return FALSE; // You cannot use the same type of switch twice.
  573. case NoCatDb:
  574. if ((i+1) < argc)
  575. {
  576. if (GUIDFromWStr(&InputInfo->CatDbGuid, wargv[i+1]))
  577. {
  578. InputInfo->CatDbSelect = GuidCatDb;
  579. i++;
  580. }
  581. else
  582. {
  583. ResFormatErr(IDS_ERR_INVALID_GUID, wargv[i+1]);
  584. return FALSE; // Invalid GUID format
  585. }
  586. }
  587. else
  588. {
  589. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  590. return FALSE; // No GUID found after /g
  591. }
  592. break;
  593. default:
  594. ResErr(IDS_ERR_UNEXPECTED); // This should never happen
  595. return FALSE; // Error
  596. }
  597. }
  598. #ifdef SIGNTOOL_LIST
  599. // File List /l
  600. else if (_wcsicmp(wargv[i]+1, L"l") == 0)
  601. {
  602. if (InputInfo->wszListFileName)
  603. {
  604. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  605. return FALSE; // You cannot use the same switch twice.
  606. }
  607. if ((i+1) < argc)
  608. {
  609. InputInfo->wszListFileName = wargv[i+1];
  610. i++;
  611. }
  612. else
  613. {
  614. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  615. return FALSE; // No Parameter found.
  616. }
  617. }
  618. #endif
  619. // Quiet /q
  620. else if (_wcsicmp(wargv[i]+1, L"q") == 0)
  621. {
  622. InputInfo->Quiet = TRUE;
  623. }
  624. // Remove Catalogs /r
  625. else if (_wcsicmp(wargv[i]+1, L"r") == 0)
  626. {
  627. switch (InputInfo->CatDbCommand)
  628. {
  629. case UpdateCat:
  630. InputInfo->CatDbCommand = RemoveCat;
  631. break;
  632. case AddUniqueCat:
  633. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/u", L"/r");
  634. return FALSE; // You cannot use the same type of switch twice.
  635. case RemoveCat:
  636. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  637. return FALSE; // You cannot use the same switch twice.
  638. default:
  639. ResErr(IDS_ERR_UNEXPECTED); // This should never happen
  640. return FALSE; // Error
  641. }
  642. }
  643. // Add Catalog with Unique Names /u
  644. else if (_wcsicmp(wargv[i]+1, L"u") == 0)
  645. {
  646. switch (InputInfo->CatDbCommand)
  647. {
  648. case UpdateCat:
  649. InputInfo->CatDbCommand = AddUniqueCat;
  650. break;
  651. case AddUniqueCat:
  652. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  653. return FALSE; // You cannot use the same switch twice.
  654. case RemoveCat:
  655. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/r", L"/u");
  656. return FALSE; // You cannot use the same type of switch twice.
  657. default:
  658. ResErr(IDS_ERR_UNEXPECTED); // This should never happen
  659. return FALSE; // Error
  660. }
  661. }
  662. // Verbose /v
  663. else if (_wcsicmp(wargv[i]+1, L"v") == 0)
  664. {
  665. InputInfo->Verbose = TRUE;
  666. }
  667. else
  668. {
  669. ResFormatErr(IDS_ERR_INVALID_SWITCH, wargv[i]);
  670. return FALSE; // Invalid switch
  671. }
  672. } // End of switch processing
  673. else
  674. {
  675. // It's not a switch
  676. // So it must be the filename(s) at the end.
  677. InputInfo->rgwszFileNames = &wargv[i];
  678. InputInfo->NumFiles = argc - i;
  679. goto CheckParams; // Done parsing.
  680. }
  681. } // End FOR loop
  682. #ifdef SIGNTOOL_LIST
  683. // Handle the case where no files were passed on the command line
  684. if (InputInfo->wszListFileName)
  685. goto CheckParams; // Done Parsing
  686. #endif
  687. // No filename found after end of switches.
  688. ResErr(IDS_ERR_MISSING_FILENAME);
  689. return FALSE;
  690. CheckParams:
  691. if (InputInfo->CatDbSelect == NoCatDb)
  692. {
  693. InputInfo->CatDbSelect = SystemCatDb;
  694. GUIDFromWStr(&InputInfo->CatDbGuid, L"{F750E6C3-38EE-11D1-85E5-00C04FC295EE}");
  695. }
  696. if (InputInfo->CatDbSelect == DefaultCatDb)
  697. {
  698. GUIDFromWStr(&InputInfo->CatDbGuid, L"{127D0A1D-4EF2-11D1-8608-00C04FC295EE}");
  699. }
  700. #ifdef SIGNTOOL_LIST
  701. if (InputInfo->wszListFileName && InputInfo->rgwszFileNames)
  702. {
  703. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/l", L"<filename(s)>");
  704. return FALSE; // Can't use /l and other files
  705. }
  706. #endif
  707. if (InputInfo->Quiet && InputInfo->Verbose)
  708. {
  709. #ifdef SIGNTOOL_DEBUG
  710. if (gDebug)
  711. {
  712. InputInfo->Quiet = FALSE;
  713. }
  714. else
  715. {
  716. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
  717. return FALSE; // Can't use /q and /v together
  718. }
  719. #else
  720. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
  721. return FALSE; // Can't use /q and /v together
  722. #endif
  723. }
  724. return TRUE; // Success
  725. }
  726. // Helper function specifically for the parameters of the Sign command
  727. BOOL _ParseSignInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo)
  728. {
  729. static WCHAR wszEKU[100];
  730. if (argc < 3) // If there's nothing after the "sign"
  731. {
  732. ResErr(IDS_ERR_NO_PARAMS);
  733. PrintUsage(InputInfo);
  734. return FALSE;
  735. }
  736. for (int i=2; i<argc; i++)
  737. {
  738. if ((wcsncmp(wargv[i], L"/", 1) == 0) ||
  739. (wcsncmp(wargv[i], L"-", 1) == 0))
  740. {
  741. // Then it's a switch.
  742. // Begin switch processing
  743. // Switch to mark end of switches --
  744. if (_wcsicmp(wargv[i]+1, L"-") == 0)
  745. {
  746. // Then we should treat all further parameters as filenames
  747. if ((i+1) < argc)
  748. {
  749. InputInfo->rgwszFileNames = &wargv[i+1];
  750. InputInfo->NumFiles = argc - (i+1);
  751. goto CheckParams; // Done parsing.
  752. }
  753. else
  754. {
  755. ResErr(IDS_ERR_MISSING_FILENAME);
  756. return FALSE; // No filename found after end of switches.
  757. }
  758. }
  759. // Help: /? /h
  760. else if ((_wcsicmp(wargv[i]+1, L"?") == 0) ||
  761. (_wcsicmp(wargv[i]+1, L"h") == 0))
  762. {
  763. PrintUsage(InputInfo);
  764. InputInfo->HelpRequest = TRUE;
  765. return FALSE;
  766. }
  767. #ifdef SIGNTOOL_DEBUG
  768. // Debug (secret switch) /#
  769. else if (_wcsicmp(wargv[i]+1, L"#") == 0)
  770. {
  771. gDebug = TRUE;
  772. InputInfo->Verbose = TRUE;
  773. }
  774. #endif
  775. // Automatic /a
  776. else if (_wcsicmp(wargv[i]+1, L"a") == 0)
  777. {
  778. InputInfo->CatDbSelect = FullAutoCatDb;
  779. }
  780. // Certificate Template /c
  781. else if (_wcsicmp(wargv[i]+1, L"c") == 0)
  782. {
  783. if (InputInfo->wszTemplateName)
  784. {
  785. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  786. return FALSE; // You cannot use the same switch twice.
  787. }
  788. if ((i+1) < argc)
  789. {
  790. InputInfo->wszTemplateName = wargv[i+1];
  791. i++;
  792. }
  793. else
  794. {
  795. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  796. return FALSE; // No Parameter found.
  797. }
  798. }
  799. // CSP
  800. else if (_wcsicmp(wargv[i]+1, L"csp") == 0)
  801. {
  802. if (InputInfo->wszCSP)
  803. {
  804. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  805. return FALSE; // You cannot use the same switch twice.
  806. }
  807. if ((i+1) < argc)
  808. {
  809. InputInfo->wszCSP = wargv[i+1];
  810. i++;
  811. }
  812. else
  813. {
  814. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  815. return FALSE; // No Parameter found.
  816. }
  817. }
  818. // Description /d
  819. else if (_wcsicmp(wargv[i]+1, L"d") == 0)
  820. {
  821. if (InputInfo->wszDescription)
  822. {
  823. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  824. return FALSE; // You cannot use the same switch twice.
  825. }
  826. if ((i+1) < argc)
  827. {
  828. InputInfo->wszDescription = wargv[i+1];
  829. i++;
  830. }
  831. else
  832. {
  833. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  834. return FALSE; // No Parameter found.
  835. }
  836. }
  837. // Description URL /du
  838. else if (_wcsicmp(wargv[i]+1, L"du") == 0)
  839. {
  840. if (InputInfo->wszDescURL)
  841. {
  842. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  843. return FALSE; // You cannot use the same switch twice.
  844. }
  845. if ((i+1) < argc)
  846. {
  847. InputInfo->wszDescURL = wargv[i+1];
  848. i++;
  849. }
  850. else
  851. {
  852. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  853. return FALSE; // No Parameter found.
  854. }
  855. }
  856. // Certificate File /f
  857. else if (_wcsicmp(wargv[i]+1, L"f") == 0)
  858. {
  859. if (InputInfo->wszCertFile)
  860. {
  861. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  862. return FALSE; // You cannot use the same switch twice.
  863. }
  864. if ((i+1) < argc)
  865. {
  866. InputInfo->wszCertFile = wargv[i+1];
  867. i++;
  868. }
  869. else
  870. {
  871. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  872. return FALSE; // No Parameter found.
  873. }
  874. }
  875. // Issuer /i
  876. else if (_wcsicmp(wargv[i]+1, L"i") == 0)
  877. {
  878. if (InputInfo->wszIssuerName)
  879. {
  880. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  881. return FALSE; // You cannot use the same switch twice.
  882. }
  883. if ((i+1) < argc)
  884. {
  885. InputInfo->wszIssuerName = wargv[i+1];
  886. i++;
  887. }
  888. else
  889. {
  890. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  891. return FALSE; // No Parameter found.
  892. }
  893. }
  894. // Key Container /k
  895. else if (_wcsicmp(wargv[i]+1, L"k") == 0)
  896. {
  897. if (InputInfo->wszContainerName)
  898. {
  899. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  900. return FALSE; // You cannot use the same switch twice.
  901. }
  902. if ((i+1) < argc)
  903. {
  904. InputInfo->wszContainerName = wargv[i+1];
  905. i++;
  906. }
  907. else
  908. {
  909. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  910. return FALSE; // No Parameter found.
  911. }
  912. }
  913. #ifdef SIGNTOOL_LIST
  914. // File List /l
  915. else if (_wcsicmp(wargv[i]+1, L"l") == 0)
  916. {
  917. if (InputInfo->wszListFileName)
  918. {
  919. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  920. return FALSE; // You cannot use the same switch twice.
  921. }
  922. if ((i+1) < argc)
  923. {
  924. InputInfo->wszListFileName = wargv[i+1];
  925. i++;
  926. }
  927. else
  928. {
  929. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  930. return FALSE; // No Parameter found.
  931. }
  932. }
  933. #endif
  934. // Subject Name /n
  935. else if (_wcsicmp(wargv[i]+1, L"n") == 0)
  936. {
  937. if (InputInfo->wszSubjectName)
  938. {
  939. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  940. return FALSE; // You cannot use the same switch twice.
  941. }
  942. if ((i+1) < argc)
  943. {
  944. InputInfo->wszSubjectName = wargv[i+1];
  945. i++;
  946. }
  947. else
  948. {
  949. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  950. return FALSE; // No Parameter found.
  951. }
  952. }
  953. // Password /p
  954. else if (_wcsicmp(wargv[i]+1, L"p") == 0)
  955. {
  956. if (InputInfo->wszPassword)
  957. {
  958. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  959. return FALSE; // You cannot use the same switch twice.
  960. }
  961. if ((i+1) < argc)
  962. {
  963. InputInfo->wszPassword = wargv[i+1];
  964. i++;
  965. }
  966. else
  967. {
  968. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  969. return FALSE; // No Parameter found.
  970. }
  971. }
  972. // Quiet /q
  973. else if (_wcsicmp(wargv[i]+1, L"q") == 0)
  974. {
  975. InputInfo->Quiet = TRUE;
  976. }
  977. // Root /r
  978. else if (_wcsicmp(wargv[i]+1, L"r") == 0)
  979. {
  980. if (InputInfo->wszRootName)
  981. {
  982. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  983. return FALSE; // You cannot use the same switch twice.
  984. }
  985. if ((i+1) < argc)
  986. {
  987. InputInfo->wszRootName = wargv[i+1];
  988. i++;
  989. }
  990. else
  991. {
  992. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  993. return FALSE; // No Parameter found.
  994. }
  995. }
  996. // Store /s
  997. else if (_wcsicmp(wargv[i]+1, L"s") == 0)
  998. {
  999. if (InputInfo->wszStoreName)
  1000. {
  1001. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1002. return FALSE; // You cannot use the same switch twice.
  1003. }
  1004. if ((i+1) < argc)
  1005. {
  1006. InputInfo->wszStoreName = wargv[i+1];
  1007. i++;
  1008. }
  1009. else
  1010. {
  1011. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1012. return FALSE; // No Parameter found.
  1013. }
  1014. }
  1015. // Machine Store Location
  1016. else if (_wcsicmp(wargv[i]+1, L"sm") == 0)
  1017. {
  1018. InputInfo->OpenMachineStore = TRUE;
  1019. }
  1020. // SHA1 Hash /sha1
  1021. else if (_wcsicmp(wargv[i]+1, L"sha1") == 0)
  1022. {
  1023. if (InputInfo->SHA1.cbData)
  1024. {
  1025. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1026. return FALSE; // You cannot use the same switch twice.
  1027. }
  1028. if ((i+1) < argc)
  1029. {
  1030. if (wcslen(wargv[i+1]) == 40)
  1031. {
  1032. InputInfo->SHA1.pbData = (BYTE*) malloc(20);
  1033. if (InputInfo->SHA1.pbData == NULL)
  1034. {
  1035. FormatErrRet(L"malloc", GetLastError());
  1036. return FALSE; // Unable to allocate SHA1 hash
  1037. }
  1038. InputInfo->SHA1.cbData = 20;
  1039. for (DWORD b=0; b<InputInfo->SHA1.cbData; b++)
  1040. {
  1041. if (swscanf(wargv[i+1]+(2*b), L"%02X",
  1042. &(InputInfo->SHA1.pbData[b])) != 1)
  1043. {
  1044. ResFormatErr(IDS_ERR_INVALID_SHA1, wargv[i+1]);
  1045. return FALSE; // Parameter string is invalid
  1046. }
  1047. }
  1048. i++;
  1049. }
  1050. else
  1051. {
  1052. ResFormatErr(IDS_ERR_INVALID_SHA1, wargv[i+1]);
  1053. return FALSE; // Parameter string is the wrong size
  1054. }
  1055. }
  1056. else
  1057. {
  1058. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1059. return FALSE; // No Parameter found.
  1060. }
  1061. }
  1062. // Timestamp Server URL /t
  1063. else if (_wcsicmp(wargv[i]+1, L"t") == 0)
  1064. {
  1065. if (InputInfo->wszTimeStampURL)
  1066. {
  1067. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1068. return FALSE; // You cannot use the same switch twice.
  1069. }
  1070. if ((i+1) < argc)
  1071. {
  1072. if (_wcsnicmp(wargv[i+1], L"http://", 7) == 0)
  1073. {
  1074. InputInfo->wszTimeStampURL = wargv[i+1];
  1075. i++;
  1076. }
  1077. else
  1078. {
  1079. ResFormatErr(IDS_ERR_BAD_TIMESTAMP_URL, wargv[i+1]);
  1080. return FALSE; // Timestamp URL does not begin with http://
  1081. }
  1082. }
  1083. else
  1084. {
  1085. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1086. return FALSE; // No Parameter found.
  1087. }
  1088. }
  1089. // Usage /u
  1090. else if (_wcsicmp(wargv[i]+1, L"u") == 0)
  1091. {
  1092. if (InputInfo->wszEKU)
  1093. {
  1094. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1095. return FALSE; // You cannot use the same switch twice.
  1096. }
  1097. if ((i+1) < argc)
  1098. {
  1099. InputInfo->wszEKU = wargv[i+1];
  1100. i++;
  1101. }
  1102. else
  1103. {
  1104. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1105. return FALSE; // No Parameter found.
  1106. }
  1107. }
  1108. // Usage (Windows System Component Verification) /uw
  1109. else if (_wcsicmp(wargv[i]+1, L"uw") == 0)
  1110. {
  1111. if (InputInfo->wszEKU)
  1112. {
  1113. *(wargv[i]+2) = L'?';
  1114. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1115. return FALSE; // You cannot use the same switch twice.
  1116. }
  1117. // Set the Usage to Windows System Component Verification:
  1118. wcscpy(wszEKU, L"1.3.6.1.4.1.311.10.3.6");
  1119. InputInfo->wszEKU = wszEKU;
  1120. }
  1121. // Verbose /v
  1122. else if (_wcsicmp(wargv[i]+1, L"v") == 0)
  1123. {
  1124. InputInfo->Verbose = TRUE;
  1125. }
  1126. else
  1127. {
  1128. ResFormatErr(IDS_ERR_INVALID_SWITCH, wargv[i]);
  1129. return FALSE; // Invalid switch
  1130. }
  1131. } // End of switch processing
  1132. else
  1133. {
  1134. // It's not a switch
  1135. // So it must be the filename(s) at the end.
  1136. InputInfo->rgwszFileNames = &wargv[i];
  1137. InputInfo->NumFiles = argc - i;
  1138. goto CheckParams; // Done parsing.
  1139. }
  1140. } // End FOR loop
  1141. #ifdef SIGNTOOL_LIST
  1142. // Handle the case where no files were passed on the command line
  1143. if (InputInfo->wszListFileName)
  1144. goto CheckParams; // Done Parsing
  1145. #endif
  1146. // No filename found after end of switches.
  1147. ResErr(IDS_ERR_MISSING_FILENAME);
  1148. return FALSE;
  1149. CheckParams: // Check for invalid combinations of parameters here:
  1150. if (InputInfo->wszPassword && (InputInfo->wszCertFile == NULL))
  1151. {
  1152. ResFormatErr(IDS_ERR_PARAM_DEPENDENCY, L"/p", L"/f");
  1153. return FALSE; // Password specified but no cert file specified.
  1154. }
  1155. if (InputInfo->wszContainerName && (InputInfo->wszCSP == NULL))
  1156. {
  1157. ResFormatErr(IDS_ERR_PARAM_DEPENDENCY, L"/k", L"/csp");
  1158. return FALSE; // Container Name specified, but to CSP Name.
  1159. }
  1160. if (InputInfo->wszCSP && (InputInfo->wszContainerName == NULL))
  1161. {
  1162. ResFormatErr(IDS_ERR_PARAM_DEPENDENCY, L"/csp", L"/k");
  1163. return FALSE; // CSP Name specified, but no Container Name.
  1164. }
  1165. if (InputInfo->wszCertFile && (InputInfo->wszStoreName ||
  1166. InputInfo->OpenMachineStore))
  1167. {
  1168. ResFormatErr(IDS_ERR_PARAM_MULTI_INCOMP, L"/f", L"/s /sm");
  1169. return FALSE; // /f means use a file, and /s means use a store.
  1170. }
  1171. #ifdef SIGNTOOL_LIST
  1172. if (InputInfo->wszListFileName && InputInfo->rgwszFileNames)
  1173. {
  1174. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/l", L"<filename(s)>");
  1175. return FALSE; // Can't use /l and other files
  1176. }
  1177. #endif
  1178. if (InputInfo->Quiet && InputInfo->Verbose)
  1179. {
  1180. #ifdef SIGNTOOL_DEBUG
  1181. if (gDebug)
  1182. {
  1183. InputInfo->Quiet = FALSE;
  1184. }
  1185. else
  1186. {
  1187. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
  1188. return FALSE; // Can't use /q and /v together
  1189. }
  1190. #else
  1191. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
  1192. return FALSE; // Can't use /q and /v together
  1193. #endif
  1194. }
  1195. return TRUE; // Success
  1196. }
  1197. // Helper function specifically for the parameters of the SignWizard command
  1198. BOOL _ParseSignWizardInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo)
  1199. {
  1200. if (argc < 3) // If there's nothing after the "SignWizard"
  1201. {
  1202. // No problem.
  1203. return TRUE;
  1204. }
  1205. for (int i=2; i<argc; i++)
  1206. {
  1207. if ((wcsncmp(wargv[i], L"/", 1) == 0) ||
  1208. (wcsncmp(wargv[i], L"-", 1) == 0))
  1209. {
  1210. // Then it's a switch.
  1211. // Begin switch processing
  1212. // Switch to mark end of switches --
  1213. if (_wcsicmp(wargv[i]+1, L"-") == 0)
  1214. {
  1215. // Then we should treat all further parameters as filenames
  1216. if ((i+1) < argc)
  1217. {
  1218. InputInfo->rgwszFileNames = &wargv[i+1];
  1219. InputInfo->NumFiles = argc - (i+1);
  1220. goto CheckParams; // Done parsing.
  1221. }
  1222. else
  1223. {
  1224. ResErr(IDS_ERR_MISSING_FILENAME);
  1225. return FALSE; // No filename found after end of switches.
  1226. }
  1227. }
  1228. // Help: /? /h
  1229. else if ((_wcsicmp(wargv[i]+1, L"?") == 0) ||
  1230. (_wcsicmp(wargv[i]+1, L"h") == 0))
  1231. {
  1232. PrintUsage(InputInfo);
  1233. InputInfo->HelpRequest = TRUE;
  1234. return FALSE;
  1235. }
  1236. #ifdef SIGNTOOL_DEBUG
  1237. // Debug (secret switch) /#
  1238. else if (_wcsicmp(wargv[i]+1, L"#") == 0)
  1239. {
  1240. gDebug = TRUE;
  1241. InputInfo->Verbose = TRUE;
  1242. }
  1243. #endif
  1244. #ifdef SIGNTOOL_LIST
  1245. // File List /l
  1246. else if (_wcsicmp(wargv[i]+1, L"l") == 0)
  1247. {
  1248. if (InputInfo->wszListFileName)
  1249. {
  1250. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1251. return FALSE; // You cannot use the same switch twice.
  1252. }
  1253. if ((i+1) < argc)
  1254. {
  1255. InputInfo->wszListFileName = wargv[i+1];
  1256. i++;
  1257. }
  1258. else
  1259. {
  1260. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1261. return FALSE; // No Parameter found.
  1262. }
  1263. }
  1264. #endif
  1265. // Quiet /q
  1266. else if (_wcsicmp(wargv[i]+1, L"q") == 0)
  1267. {
  1268. InputInfo->Quiet = TRUE;
  1269. }
  1270. // Verbose /v
  1271. else if (_wcsicmp(wargv[i]+1, L"v") == 0)
  1272. {
  1273. InputInfo->Verbose = TRUE;
  1274. }
  1275. else
  1276. {
  1277. ResFormatErr(IDS_ERR_INVALID_SWITCH, wargv[i]);
  1278. return FALSE; // Invalid switch
  1279. }
  1280. } // End of switch processing
  1281. else
  1282. {
  1283. // It's not a switch
  1284. // So it must be the filename(s) at the end.
  1285. InputInfo->rgwszFileNames = &wargv[i];
  1286. InputInfo->NumFiles = argc - i;
  1287. goto CheckParams; // Done parsing.
  1288. }
  1289. } // End FOR loop
  1290. // It is OK if no filenames were found after end of switches.
  1291. CheckParams:
  1292. #ifdef SIGNTOOL_LIST
  1293. if (InputInfo->wszListFileName && InputInfo->rgwszFileNames)
  1294. {
  1295. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/l", L"<filename(s)>");
  1296. return FALSE; // Can't use /l and other files
  1297. }
  1298. #endif
  1299. if (InputInfo->Quiet && InputInfo->Verbose)
  1300. {
  1301. #ifdef SIGNTOOL_DEBUG
  1302. if (gDebug)
  1303. {
  1304. InputInfo->Quiet = FALSE;
  1305. }
  1306. else
  1307. {
  1308. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
  1309. return FALSE; // Can't use /q and /v together
  1310. }
  1311. #else
  1312. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
  1313. return FALSE; // Can't use /q and /v together
  1314. #endif
  1315. }
  1316. return TRUE; // Success
  1317. }
  1318. // Helper function specifically for the parameters of the Timestamp command
  1319. BOOL _ParseTimestampInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo)
  1320. {
  1321. if (argc < 3) // If there's nothing after the "timestamp"
  1322. {
  1323. ResErr(IDS_ERR_NO_PARAMS);
  1324. PrintUsage(InputInfo);
  1325. return FALSE;
  1326. }
  1327. for (int i=2; i<argc; i++)
  1328. {
  1329. if ((wcsncmp(wargv[i], L"/", 1) == 0) ||
  1330. (wcsncmp(wargv[i], L"-", 1) == 0))
  1331. {
  1332. // Then it's a switch.
  1333. // Begin switch processing
  1334. // Switch to mark end of switches --
  1335. if (_wcsicmp(wargv[i]+1, L"-") == 0)
  1336. {
  1337. // Then we should treat all further parameters as filenames
  1338. if ((i+1) < argc)
  1339. {
  1340. InputInfo->rgwszFileNames = &wargv[i+1];
  1341. InputInfo->NumFiles = argc - (i+1);
  1342. goto CheckParams; // Done parsing.
  1343. }
  1344. else
  1345. {
  1346. ResErr(IDS_ERR_MISSING_FILENAME);
  1347. return FALSE; // No filename found after end of switches.
  1348. }
  1349. }
  1350. // Help: /? /h
  1351. else if ((_wcsicmp(wargv[i]+1, L"?") == 0) ||
  1352. (_wcsicmp(wargv[i]+1, L"h") == 0))
  1353. {
  1354. PrintUsage(InputInfo);
  1355. InputInfo->HelpRequest = TRUE;
  1356. return FALSE;
  1357. }
  1358. #ifdef SIGNTOOL_DEBUG
  1359. // Debug (secret switch) /#
  1360. else if (_wcsicmp(wargv[i]+1, L"#") == 0)
  1361. {
  1362. gDebug = TRUE;
  1363. InputInfo->Verbose = TRUE;
  1364. }
  1365. #endif
  1366. #ifdef SIGNTOOL_LIST
  1367. // File List /l
  1368. else if (_wcsicmp(wargv[i]+1, L"l") == 0)
  1369. {
  1370. if (InputInfo->wszListFileName)
  1371. {
  1372. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1373. return FALSE; // You cannot use the same switch twice.
  1374. }
  1375. if ((i+1) < argc)
  1376. {
  1377. InputInfo->wszListFileName = wargv[i+1];
  1378. i++;
  1379. }
  1380. else
  1381. {
  1382. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1383. return FALSE; // No Parameter found.
  1384. }
  1385. }
  1386. #endif
  1387. // Timestamp Server URL /t
  1388. else if (_wcsicmp(wargv[i]+1, L"t") == 0)
  1389. {
  1390. if (InputInfo->wszTimeStampURL)
  1391. {
  1392. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1393. return FALSE; // You cannot use the same switch twice.
  1394. }
  1395. if ((i+1) < argc)
  1396. {
  1397. if (_wcsnicmp(wargv[i+1], L"http://", 7) != 0)
  1398. {
  1399. ResFormatErr(IDS_ERR_BAD_TIMESTAMP_URL, wargv[i+1]);
  1400. return FALSE; // Timestamp URL does not begin with http://
  1401. }
  1402. InputInfo->wszTimeStampURL = wargv[i+1];
  1403. i++;
  1404. }
  1405. else
  1406. {
  1407. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1408. return FALSE; // No Parameter found.
  1409. }
  1410. }
  1411. // Quiet /q
  1412. else if (_wcsicmp(wargv[i]+1, L"q") == 0)
  1413. {
  1414. InputInfo->Quiet = TRUE;
  1415. }
  1416. // Verbose /v
  1417. else if (_wcsicmp(wargv[i]+1, L"v") == 0)
  1418. {
  1419. InputInfo->Verbose = TRUE;
  1420. }
  1421. else
  1422. {
  1423. ResFormatErr(IDS_ERR_INVALID_SWITCH, wargv[i]);
  1424. return FALSE; // Invalid switch
  1425. }
  1426. } // End of switch processing
  1427. else
  1428. {
  1429. // It's not a switch
  1430. // So it must be the filename(s) at the end.
  1431. InputInfo->rgwszFileNames = &wargv[i];
  1432. InputInfo->NumFiles = argc - i;
  1433. goto CheckParams; // Done parsing.
  1434. }
  1435. } // End FOR loop
  1436. #ifdef SIGNTOOL_LIST
  1437. // Handle the case where no files were passed on the command line
  1438. if (InputInfo->wszListFileName)
  1439. goto CheckParams; // Done Parsing
  1440. #endif
  1441. // No filename found after end of switches.
  1442. ResErr(IDS_ERR_MISSING_FILENAME);
  1443. return FALSE;
  1444. CheckParams:
  1445. if (InputInfo->wszTimeStampURL == NULL)
  1446. {
  1447. ResFormatErr(IDS_ERR_PARAM_REQUIRED, L"/t");
  1448. return FALSE; // /t is required.
  1449. }
  1450. #ifdef SIGNTOOL_LIST
  1451. if (InputInfo->wszListFileName && InputInfo->rgwszFileNames)
  1452. {
  1453. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/l", L"<filename(s)>");
  1454. return FALSE; // Can't use /l and other files
  1455. }
  1456. #endif
  1457. if (InputInfo->Quiet && InputInfo->Verbose)
  1458. {
  1459. #ifdef SIGNTOOL_DEBUG
  1460. if (gDebug)
  1461. {
  1462. InputInfo->Quiet = FALSE;
  1463. }
  1464. else
  1465. {
  1466. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
  1467. return FALSE; // Can't use /q and /v together
  1468. }
  1469. #else
  1470. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
  1471. return FALSE; // Can't use /q and /v together
  1472. #endif
  1473. }
  1474. return TRUE; // Success
  1475. }
  1476. // Helper function specifically for the parameters of the Verify command
  1477. BOOL _ParseVerifyInputs(int argc, WCHAR **wargv, INPUTINFO *InputInfo)
  1478. {
  1479. if (argc < 3) // If there's nothing after the "verify"
  1480. {
  1481. ResErr(IDS_ERR_NO_PARAMS);
  1482. PrintUsage(InputInfo);
  1483. return FALSE;
  1484. }
  1485. for (int i=2; i<argc; i++)
  1486. {
  1487. if ((wcsncmp(wargv[i], L"/", 1) == 0) ||
  1488. (wcsncmp(wargv[i], L"-", 1) == 0))
  1489. {
  1490. // Then it's a switch.
  1491. // Begin switch processing
  1492. // Switch to mark end of switches --
  1493. if (_wcsicmp(wargv[i]+1, L"-") == 0)
  1494. {
  1495. // Then we should treat all further parameters as filenames
  1496. if ((i+1) < argc)
  1497. {
  1498. InputInfo->rgwszFileNames = &wargv[i+1];
  1499. InputInfo->NumFiles = argc - (i+1);
  1500. goto CheckParams; // Done parsing.
  1501. }
  1502. else
  1503. {
  1504. ResErr(IDS_ERR_MISSING_FILENAME);
  1505. return FALSE; // No filename found after end of switches.
  1506. }
  1507. }
  1508. // Help: /? /h
  1509. else if ((_wcsicmp(wargv[i]+1, L"?") == 0) ||
  1510. (_wcsicmp(wargv[i]+1, L"h") == 0))
  1511. {
  1512. PrintUsage(InputInfo);
  1513. InputInfo->HelpRequest = TRUE;
  1514. return FALSE;
  1515. }
  1516. #ifdef SIGNTOOL_DEBUG
  1517. // Debug (secret switch) /#
  1518. else if (_wcsicmp(wargv[i]+1, L"#") == 0)
  1519. {
  1520. gDebug = TRUE;
  1521. InputInfo->Verbose = TRUE;
  1522. }
  1523. #endif
  1524. // Automatic (All Catalogs) /a
  1525. else if (_wcsicmp(wargv[i]+1, L"a") == 0)
  1526. {
  1527. if (InputInfo->wszCatFile)
  1528. {
  1529. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/a");
  1530. return FALSE;
  1531. }
  1532. if (InputInfo->CatDbSelect != NoCatDb)
  1533. {
  1534. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1535. return FALSE; // You cannot use the same switch twice.
  1536. }
  1537. InputInfo->CatDbSelect = FullAutoCatDb;
  1538. }
  1539. // Automatic (Default) /ad
  1540. else if (_wcsicmp(wargv[i]+1, L"ad") == 0)
  1541. {
  1542. if (InputInfo->wszCatFile)
  1543. {
  1544. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/ad");
  1545. return FALSE;
  1546. }
  1547. if (InputInfo->CatDbSelect != NoCatDb)
  1548. {
  1549. *(wargv[i]+2) = L'?';
  1550. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1551. return FALSE; // You cannot use the same switch twice.
  1552. }
  1553. InputInfo->CatDbSelect = DefaultCatDb;
  1554. GUIDFromWStr(&InputInfo->CatDbGuid, L"{127D0A1D-4EF2-11D1-8608-00C04FC295EE}");
  1555. }
  1556. // Automatic (System) /as
  1557. else if (_wcsicmp(wargv[i]+1, L"as") == 0)
  1558. {
  1559. if (InputInfo->wszCatFile)
  1560. {
  1561. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/as");
  1562. return FALSE;
  1563. }
  1564. if (InputInfo->CatDbSelect != NoCatDb)
  1565. {
  1566. *(wargv[i]+2) = L'?';
  1567. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1568. return FALSE; // You cannot use the same switch twice.
  1569. }
  1570. InputInfo->CatDbSelect = SystemCatDb;
  1571. GUIDFromWStr(&InputInfo->CatDbGuid, L"{F750E6C3-38EE-11D1-85E5-00C04FC295EE}");
  1572. }
  1573. // Automatic (System) /ag
  1574. else if (_wcsicmp(wargv[i]+1, L"ag") == 0)
  1575. {
  1576. if (InputInfo->wszCatFile)
  1577. {
  1578. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/ag");
  1579. return FALSE;
  1580. }
  1581. if (InputInfo->CatDbSelect != NoCatDb)
  1582. {
  1583. *(wargv[i]+2) = L'?';
  1584. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1585. return FALSE; // You cannot use the same switch twice.
  1586. }
  1587. InputInfo->CatDbSelect = GuidCatDb;
  1588. if ((i+1) < argc)
  1589. {
  1590. if (GUIDFromWStr(&InputInfo->CatDbGuid, wargv[i+1]))
  1591. {
  1592. i++;
  1593. }
  1594. else
  1595. {
  1596. ResFormatErr(IDS_ERR_INVALID_GUID, wargv[i+1]);
  1597. return FALSE; // Invalid GUID format
  1598. }
  1599. }
  1600. else
  1601. {
  1602. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1603. return FALSE; // No GUID found after /ag
  1604. }
  1605. }
  1606. // Catalog File /c
  1607. else if (_wcsicmp(wargv[i]+1, L"c") == 0)
  1608. {
  1609. if (InputInfo->wszCatFile)
  1610. {
  1611. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1612. return FALSE; // You cannot use the same switch twice.
  1613. }
  1614. if (InputInfo->CatDbSelect == FullAutoCatDb)
  1615. {
  1616. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/a");
  1617. return FALSE; // Incompatible switches
  1618. }
  1619. if (InputInfo->CatDbSelect == DefaultCatDb)
  1620. {
  1621. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/ad");
  1622. return FALSE; // Incompatible switches
  1623. }
  1624. if (InputInfo->CatDbSelect == GuidCatDb)
  1625. {
  1626. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/ag");
  1627. return FALSE; // Incompatible switches
  1628. }
  1629. if (InputInfo->CatDbSelect == SystemCatDb)
  1630. {
  1631. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/c", L"/as");
  1632. return FALSE; // Incompatible switches
  1633. }
  1634. if ((i+1) < argc)
  1635. {
  1636. InputInfo->wszCatFile = wargv[i+1];
  1637. i++;
  1638. }
  1639. else
  1640. {
  1641. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1642. return FALSE; // No Parameter found.
  1643. }
  1644. }
  1645. #ifdef SIGNTOOL_LIST
  1646. // File List /l
  1647. else if (_wcsicmp(wargv[i]+1, L"l") == 0)
  1648. {
  1649. if (InputInfo->wszListFileName)
  1650. {
  1651. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1652. return FALSE; // You cannot use the same switch twice.
  1653. }
  1654. if ((i+1) < argc)
  1655. {
  1656. InputInfo->wszListFileName = wargv[i+1];
  1657. i++;
  1658. }
  1659. else
  1660. {
  1661. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1662. return FALSE; // No Parameter found.
  1663. }
  1664. }
  1665. #endif
  1666. // OS Version /o
  1667. else if (_wcsicmp(wargv[i]+1, L"o") == 0)
  1668. {
  1669. if (InputInfo->wszVersion)
  1670. {
  1671. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1672. return FALSE; // You cannot use the same switch twice.
  1673. }
  1674. if ((i+1) < argc)
  1675. {
  1676. InputInfo->dwBuildNumber = 0;
  1677. if (!((swscanf(wargv[i+1], L"%d:%d.%d.%d",
  1678. &InputInfo->dwPlatform,
  1679. &InputInfo->dwMajorVersion,
  1680. &InputInfo->dwMinorVersion,
  1681. &InputInfo->dwBuildNumber) == 4) ||
  1682. (swscanf(wargv[i+1], L"%d:%d.%d",
  1683. &InputInfo->dwPlatform,
  1684. &InputInfo->dwMajorVersion,
  1685. &InputInfo->dwMinorVersion) == 3)) ||
  1686. (InputInfo->dwPlatform == 0))
  1687. {
  1688. ResFormatErr(IDS_ERR_INVALID_VERSION, wargv[i+1]);
  1689. return FALSE;
  1690. }
  1691. InputInfo->wszVersion = wargv[i+1];
  1692. i++;
  1693. }
  1694. else
  1695. {
  1696. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1697. return FALSE; // No Parameter found.
  1698. }
  1699. }
  1700. // Policy (Default Authenticode) /pa (used to be /pd)
  1701. else if ((_wcsicmp(wargv[i]+1, L"pa") == 0) || (_wcsicmp(wargv[i]+1, L"pd") == 0))
  1702. {
  1703. if (InputInfo->Policy != SystemDriver)
  1704. {
  1705. *(wargv[i]+2) = L'?';
  1706. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1707. return FALSE; // You cannot use the same switch twice.
  1708. }
  1709. InputInfo->Policy = DefaultAuthenticode;
  1710. }
  1711. // Policy (Specify by GUID) /pg
  1712. else if (_wcsicmp(wargv[i]+1, L"pg") == 0)
  1713. {
  1714. if (InputInfo->Policy != SystemDriver)
  1715. {
  1716. *(wargv[i]+2) = L'?';
  1717. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1718. return FALSE; // You cannot use the same switch twice.
  1719. }
  1720. InputInfo->Policy = GuidActionID;
  1721. if ((i+1) < argc)
  1722. {
  1723. if (GUIDFromWStr(&InputInfo->PolicyGuid, wargv[i+1]))
  1724. {
  1725. i++;
  1726. }
  1727. else
  1728. {
  1729. ResFormatErr(IDS_ERR_INVALID_GUID, wargv[i+1]);
  1730. return FALSE; // Invalid GUID format
  1731. }
  1732. }
  1733. else
  1734. {
  1735. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1736. return FALSE; // No GUID found after /pg
  1737. }
  1738. }
  1739. // Quiet /q
  1740. else if (_wcsicmp(wargv[i]+1, L"q") == 0)
  1741. {
  1742. InputInfo->Quiet = TRUE;
  1743. }
  1744. // Root Name /r
  1745. else if (_wcsicmp(wargv[i]+1, L"r") == 0)
  1746. {
  1747. if (InputInfo->wszRootName)
  1748. {
  1749. ResFormatErr(IDS_ERR_DUP_SWITCH, wargv[i]);
  1750. return FALSE; // You cannot use the same switch twice.
  1751. }
  1752. if ((i+1) < argc)
  1753. {
  1754. InputInfo->wszRootName = wargv[i+1];
  1755. // This string will be compared with a lowercased string.
  1756. _wcslwr(InputInfo->wszRootName);
  1757. i++;
  1758. }
  1759. else
  1760. {
  1761. ResFormatErr(IDS_ERR_NO_PARAM, wargv[i]);
  1762. return FALSE; // No Parameter found.
  1763. }
  1764. }
  1765. // TimeStamp Warn /tw
  1766. else if (_wcsicmp(wargv[i]+1, L"tw") == 0)
  1767. {
  1768. InputInfo->TSWarn = TRUE;
  1769. }
  1770. // Verbose /v
  1771. else if (_wcsicmp(wargv[i]+1, L"v") == 0)
  1772. {
  1773. InputInfo->Verbose = TRUE;
  1774. }
  1775. else
  1776. {
  1777. ResFormatErr(IDS_ERR_INVALID_SWITCH, wargv[i]);
  1778. return FALSE; // Invalid switch
  1779. }
  1780. } // End of switch processing
  1781. else
  1782. {
  1783. // It's not a switch
  1784. // So it must be the filename(s) at the end.
  1785. InputInfo->rgwszFileNames = &wargv[i];
  1786. InputInfo->NumFiles = argc - i;
  1787. goto CheckParams; // Done parsing.
  1788. }
  1789. } // End FOR loop
  1790. #ifdef SIGNTOOL_LIST
  1791. // Handle the case where no files were passed on the command line
  1792. if (InputInfo->wszListFileName)
  1793. goto CheckParams; // Done Parsing
  1794. #endif
  1795. // No filename found after end of switches.
  1796. ResErr(IDS_ERR_MISSING_FILENAME);
  1797. return FALSE;
  1798. CheckParams:
  1799. if (InputInfo->wszVersion && !((InputInfo->CatDbSelect != NoCatDb) ||
  1800. InputInfo->wszCatFile))
  1801. {
  1802. ResFormatErr(IDS_ERR_PARAM_MULTI_DEP, L"/o", L"/a /ad /ag /as /c");
  1803. return FALSE; // OS Version switch requires catalog options (/a? or /c)
  1804. }
  1805. #ifdef SIGNTOOL_LIST
  1806. if (InputInfo->wszListFileName && InputInfo->rgwszFileNames)
  1807. {
  1808. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/l", L"<filename(s)>");
  1809. return FALSE; // Can't use /l and other files
  1810. }
  1811. #endif
  1812. if (InputInfo->Quiet && InputInfo->Verbose)
  1813. {
  1814. #ifdef SIGNTOOL_DEBUG
  1815. if (gDebug)
  1816. {
  1817. InputInfo->Quiet = FALSE;
  1818. }
  1819. else
  1820. {
  1821. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
  1822. return FALSE; // Can't use /q and /v together
  1823. }
  1824. #else
  1825. ResFormatErr(IDS_ERR_PARAM_INCOMPATIBLE, L"/q", L"/v");
  1826. return FALSE; // Can't use /q and /v together
  1827. #endif
  1828. }
  1829. return TRUE; // Success
  1830. }