Source code of Windows XP (NT5)
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.

755 lines
17 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: cwargv.cpp
  8. //
  9. // Contents: argv parsing api
  10. //
  11. // History: 02-Oct-1997 pberkman create
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "global.hxx"
  15. #include "cwargv.hxx"
  16. #include "fparse.hxx"
  17. #define SID_FILES 0
  18. typedef struct ARGVSTORAGE_
  19. {
  20. DWORD dwsidOption;
  21. WCHAR *pwszOption;
  22. DWORD dwsidOptionHelp;
  23. WCHAR *pwszOptionHelp;
  24. BOOL fHiddenCmd;
  25. BOOL fSet;
  26. DWORD dwValueType;
  27. union
  28. {
  29. WCHAR *pwszValue;
  30. WCHAR *pwszCmdFile;
  31. DWORD dwValue;
  32. BOOL fValue;
  33. };
  34. } ARGVSTORAGE;
  35. cWArgv_::cWArgv_(HINSTANCE hInst0, BOOL *pfFailed, BOOL fChkCmdFile)
  36. {
  37. pwszThisFilename = NULL; // don't delete!
  38. pwszUsageWord = NULL;
  39. pwszUsageOptionsText = NULL;
  40. pwszUsageCmdFileText = NULL;
  41. pwszUsageAddText = NULL;
  42. pwszOptionParamText = NULL;
  43. pwszUsageString = NULL;
  44. pwszNonParamArgBlanks = NULL;
  45. fShowHiddenArgs = FALSE;
  46. fNonHiddenParamArgs = FALSE;
  47. dwLongestArg = 0;
  48. this->hInst = hInst0;
  49. this->fChkCmdF = fChkCmdFile;
  50. pArgs = new Stack_(NULL); // no sorting!
  51. if (pArgs == NULL)
  52. {
  53. *pfFailed = TRUE;
  54. }
  55. else
  56. {
  57. *pfFailed = FALSE;
  58. }
  59. }
  60. cWArgv_::~cWArgv_(void)
  61. {
  62. ARGVSTORAGE *pArg;
  63. DWORD dwIdx;
  64. DELETE_OBJECT(pwszUsageWord);
  65. DELETE_OBJECT(pwszUsageOptionsText);
  66. DELETE_OBJECT(pwszUsageCmdFileText);
  67. DELETE_OBJECT(pwszUsageAddText);
  68. DELETE_OBJECT(pwszOptionParamText);
  69. DELETE_OBJECT(pwszUsageString);
  70. DELETE_OBJECT(pwszNonParamArgBlanks);
  71. dwIdx = 0;
  72. while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx))
  73. {
  74. DELETE_OBJECT(pArg->pwszOption);
  75. DELETE_OBJECT(pArg->pwszOptionHelp);
  76. dwIdx++;
  77. }
  78. DELETE_OBJECT(pArgs);
  79. }
  80. void cWArgv_::AddUsageText(DWORD dwsidUsageWord, DWORD dwsidUsageOptions, DWORD dwsidUsageCmdFileText,
  81. DWORD dwsidUsageAddText, DWORD dwsidOptionParamText)
  82. {
  83. WCHAR wszString[MAX_PATH];
  84. wszString[0] = NULL;
  85. LoadStringU(this->hInst, dwsidUsageWord, &wszString[0], MAX_PATH);
  86. if (wszString[0])
  87. {
  88. if (!(pwszUsageWord = new WCHAR[wcslen(&wszString[0]) + 1]))
  89. {
  90. return;
  91. }
  92. wcscpy(pwszUsageWord, &wszString[0]);
  93. }
  94. wszString[0] = NULL;
  95. LoadStringU(this->hInst, dwsidUsageOptions, &wszString[0], MAX_PATH);
  96. if (wszString[0])
  97. {
  98. if (!(pwszUsageOptionsText = new WCHAR[wcslen(&wszString[0]) + 1]))
  99. {
  100. return;
  101. }
  102. wcscpy(pwszUsageOptionsText, &wszString[0]);
  103. }
  104. wszString[0] = NULL;
  105. LoadStringU(this->hInst, dwsidUsageCmdFileText, &wszString[0], MAX_PATH);
  106. if (wszString[0])
  107. {
  108. if (!(pwszUsageCmdFileText = new WCHAR[wcslen(&wszString[0]) + 1]))
  109. {
  110. return;
  111. }
  112. wcscpy(pwszUsageCmdFileText, &wszString[0]);
  113. }
  114. wszString[0] = NULL;
  115. LoadStringU(this->hInst, dwsidOptionParamText, &wszString[0], MAX_PATH);
  116. if (wszString[0])
  117. {
  118. if (!(pwszOptionParamText = new WCHAR[wcslen(&wszString[0]) + 1]))
  119. {
  120. return;
  121. }
  122. wcscpy(pwszOptionParamText, &wszString[0]);
  123. }
  124. wszString[0] = NULL;
  125. LoadStringU(this->hInst, dwsidUsageAddText, &wszString[0], MAX_PATH);
  126. if (wszString[0])
  127. {
  128. if (!(pwszUsageAddText = new WCHAR[wcslen(&wszString[0]) + 1]))
  129. {
  130. return;
  131. }
  132. wcscpy(pwszUsageAddText, &wszString[0]);
  133. }
  134. }
  135. WCHAR *cWArgv_::GetUsageString(void)
  136. {
  137. int i;
  138. if (pwszUsageString)
  139. {
  140. return(pwszUsageString);
  141. }
  142. if (!(pwszThisFilename))
  143. {
  144. return(NULL);
  145. }
  146. DWORD ccLen;
  147. ccLen = wcslen(pwszThisFilename);
  148. if (pwszUsageWord)
  149. {
  150. ccLen += wcslen(pwszUsageWord);
  151. }
  152. if (pwszUsageOptionsText)
  153. {
  154. ccLen += wcslen(pwszUsageOptionsText);
  155. }
  156. if (fChkCmdF)
  157. {
  158. if (pwszUsageCmdFileText)
  159. {
  160. ccLen += wcslen(pwszUsageCmdFileText);
  161. }
  162. }
  163. if (pwszUsageAddText)
  164. {
  165. ccLen += wcslen(pwszUsageAddText);
  166. }
  167. ARGVSTORAGE *pArg;
  168. DWORD dwIdx;
  169. dwIdx = 0;
  170. while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx))
  171. {
  172. if (pArg->dwsidOption != SID_FILES)
  173. {
  174. if (pArg->pwszOption)
  175. {
  176. if ((pArg->fHiddenCmd) && (!(fShowHiddenArgs)))
  177. {
  178. dwIdx++;
  179. continue;
  180. }
  181. ccLen += 6; // 5 spaces + 1 for '-'
  182. ccLen += dwLongestArg; // wcslen(pArg->pwszOption);
  183. if (((fNonHiddenParamArgs) && !(fShowHiddenArgs)) ||
  184. (fShowHiddenArgs))
  185. {
  186. if ((pwszNonParamArgBlanks) && (pwszOptionParamText))
  187. {
  188. ccLen++; // space
  189. ccLen += wcslen(pwszOptionParamText);
  190. }
  191. }
  192. if (pArg->pwszOptionHelp)
  193. {
  194. ccLen += 2; // : + space
  195. ccLen += wcslen(pArg->pwszOptionHelp);
  196. }
  197. ccLen += 2; // cr/lf
  198. }
  199. }
  200. dwIdx++;
  201. }
  202. ccLen += 10;
  203. if (!(pwszUsageString = new WCHAR[ccLen + 1]))
  204. {
  205. return(NULL);
  206. }
  207. swprintf(pwszUsageString, L"%s: %s %s %s %s\r\n",
  208. pwszUsageWord,
  209. pwszThisFilename,
  210. (pwszUsageOptionsText) ? pwszUsageOptionsText : L"",
  211. (pwszUsageCmdFileText && fChkCmdF) ? pwszUsageCmdFileText : L"",
  212. (pwszUsageAddText) ? pwszUsageAddText : L"");
  213. dwIdx = pArgs->Count() - 1;
  214. while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx))
  215. {
  216. if (pArg->dwsidOption != SID_FILES)
  217. {
  218. if (pArg->pwszOption)
  219. {
  220. if ((pArg->fHiddenCmd) && (!(fShowHiddenArgs)))
  221. {
  222. if (dwIdx == 0)
  223. {
  224. break;
  225. }
  226. dwIdx--;
  227. continue;
  228. }
  229. wcscat(pwszUsageString, L" -");
  230. wcscat(pwszUsageString, pArg->pwszOption);
  231. if ((pArg->dwValueType != WARGV_VALUETYPE_BOOL) &&
  232. (pwszOptionParamText))
  233. {
  234. wcscat(pwszUsageString, L" ");
  235. wcscat(pwszUsageString, pwszOptionParamText);
  236. }
  237. if (pArg->pwszOptionHelp)
  238. {
  239. wcscat(pwszUsageString, L": ");
  240. for (i = 0; i < (int)(dwLongestArg - wcslen(pArg->pwszOption)); i++)
  241. {
  242. wcscat(pwszUsageString, L" ");
  243. }
  244. if ((pArg->dwValueType == WARGV_VALUETYPE_BOOL) &&
  245. (((fNonHiddenParamArgs) && !(fShowHiddenArgs)) || (fShowHiddenArgs)) &&
  246. (pwszNonParamArgBlanks))
  247. {
  248. wcscat(pwszUsageString, pwszNonParamArgBlanks);
  249. }
  250. wcscat(pwszUsageString, pArg->pwszOptionHelp);
  251. }
  252. wcscat(pwszUsageString, L"\r\n");
  253. }
  254. }
  255. if (dwIdx == 0)
  256. {
  257. break;
  258. }
  259. dwIdx--;
  260. }
  261. return(pwszUsageString);
  262. }
  263. BOOL cWArgv_::Add2List(DWORD dwsidOption, DWORD dwsidOptionHelp, DWORD dwValueType, void *pvDefaultValue,
  264. BOOL fInternalCmd)
  265. {
  266. if (!(pArgs))
  267. {
  268. return(FALSE);
  269. }
  270. ARGVSTORAGE *pArg;
  271. WCHAR wszString[MAX_PATH];
  272. DWORD i;
  273. if (!(pArg = (ARGVSTORAGE *)pArgs->Add(sizeof(ARGVSTORAGE))))
  274. {
  275. return(FALSE);
  276. }
  277. memset(pArg, 0x00, sizeof(ARGVSTORAGE));
  278. pArg->dwValueType = dwValueType;
  279. if (pArg->dwValueType != WARGV_VALUETYPE_BOOL)
  280. {
  281. if (!(pwszNonParamArgBlanks))
  282. {
  283. if (pwszOptionParamText)
  284. {
  285. if (pwszNonParamArgBlanks = new WCHAR[wcslen(pwszOptionParamText) + 2])
  286. {
  287. for (i = 0; i <= (DWORD)wcslen(pwszOptionParamText); i++)
  288. {
  289. pwszNonParamArgBlanks[i] = L' ';
  290. }
  291. pwszNonParamArgBlanks[i] = NULL;
  292. }
  293. }
  294. }
  295. fNonHiddenParamArgs = TRUE;
  296. }
  297. pArg->fHiddenCmd = fInternalCmd;
  298. pArg->dwsidOption = dwsidOption;
  299. wszString[0] = NULL;
  300. LoadStringU(this->hInst, dwsidOption, &wszString[0], MAX_PATH);
  301. if (wszString[0])
  302. {
  303. if (!(pArg->pwszOption = new WCHAR[wcslen(&wszString[0]) + 1]))
  304. {
  305. return(FALSE);
  306. }
  307. wcscpy(pArg->pwszOption, &wszString[0]);
  308. if ((DWORD)wcslen(&wszString[0]) > dwLongestArg)
  309. {
  310. dwLongestArg = wcslen(&wszString[0]);
  311. }
  312. }
  313. pArg->dwsidOptionHelp = dwsidOptionHelp;
  314. wszString[0] = NULL;
  315. LoadStringU(this->hInst, dwsidOptionHelp, &wszString[0], MAX_PATH);
  316. if (wszString[0])
  317. {
  318. if (!(pArg->pwszOptionHelp = new WCHAR[wcslen(&wszString[0]) + 1]))
  319. {
  320. return(FALSE);
  321. }
  322. wcscpy(pArg->pwszOptionHelp, &wszString[0]);
  323. }
  324. if (pvDefaultValue)
  325. {
  326. switch (dwValueType)
  327. {
  328. case WARGV_VALUETYPE_BOOL: pArg->fValue = (BOOL)((DWORD_PTR)pvDefaultValue); break;
  329. case WARGV_VALUETYPE_DWORDD:
  330. case WARGV_VALUETYPE_DWORDH: pArg->dwValue = (DWORD)((DWORD_PTR)pvDefaultValue); break;
  331. case WARGV_VALUETYPE_WCHAR: pArg->pwszValue = (WCHAR *)pvDefaultValue; break;
  332. default:
  333. return(FALSE);
  334. }
  335. }
  336. return(TRUE);
  337. }
  338. BOOL cWArgv_::Fill(int argc, WCHAR **wargv)
  339. {
  340. if (!(pArgs))
  341. {
  342. return(FALSE);
  343. }
  344. if (!(pwszThisFilename))
  345. {
  346. if (pwszThisFilename = wcsrchr(&wargv[0][0], L'\\'))
  347. {
  348. pwszThisFilename++;
  349. }
  350. else
  351. {
  352. pwszThisFilename = &wargv[0][0];
  353. }
  354. }
  355. int i;
  356. for (i = 1; i < argc; ++i)
  357. {
  358. switch (wargv[i][0])
  359. {
  360. case L'-':
  361. case L'/':
  362. if (wargv[i][1] == L'~')
  363. {
  364. fShowHiddenArgs = TRUE;
  365. return(FALSE);
  366. }
  367. i += this->ProcessArg(argc - i, &wargv[i]);
  368. break;
  369. case L'@':
  370. this->ProcessCommandFile(&wargv[i][1]);
  371. break;
  372. default:
  373. this->AddFile(&wargv[i][0]);
  374. break;
  375. }
  376. }
  377. return(TRUE);
  378. }
  379. int cWArgv_::ProcessArg(int argc, WCHAR **wargv)
  380. {
  381. ARGVSTORAGE *pArg;
  382. DWORD dwIdx;
  383. DWORD ccOption;
  384. WCHAR *pwszArg;
  385. int iRet;
  386. iRet = 0;
  387. pwszArg = &wargv[0][1]; // skip over - or /
  388. dwIdx = 0;
  389. while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx))
  390. {
  391. if (pArg->pwszOption)
  392. {
  393. ccOption = (DWORD)wcslen(pArg->pwszOption);
  394. if (_memicmp(pArg->pwszOption, pwszArg, ccOption * sizeof(WCHAR)) == 0)
  395. {
  396. pArg->fSet = TRUE;
  397. switch (pArg->dwValueType)
  398. {
  399. case WARGV_VALUETYPE_BOOL:
  400. pArg->fValue = TRUE;
  401. return(iRet);
  402. case WARGV_VALUETYPE_DWORDH:
  403. case WARGV_VALUETYPE_DWORDD:
  404. if (!(pwszArg[ccOption]))
  405. {
  406. pwszArg = &wargv[1][0];
  407. iRet++;
  408. }
  409. else
  410. {
  411. pwszArg = &wargv[0][ccOption + 1];
  412. }
  413. if (pArg->dwValueType == WARGV_VALUETYPE_DWORDH)
  414. {
  415. pArg->dwValue = (DWORD)wcstoul(pwszArg, NULL, 16);
  416. }
  417. else
  418. {
  419. pArg->dwValue = (DWORD)wcstoul(pwszArg, NULL, 10);
  420. }
  421. return(iRet);
  422. case WARGV_VALUETYPE_WCHAR:
  423. if (!(pwszArg[ccOption]))
  424. {
  425. pArg->pwszValue = &wargv[1][0];
  426. iRet++;
  427. }
  428. else
  429. {
  430. pArg->pwszValue = &wargv[0][ccOption];
  431. }
  432. return(iRet);
  433. default:
  434. return(iRet);
  435. }
  436. }
  437. }
  438. dwIdx++;
  439. }
  440. return(iRet);
  441. }
  442. BOOL cWArgv_::IsSet(DWORD dwsidOption)
  443. {
  444. ARGVSTORAGE *pArg;
  445. DWORD dwIdx;
  446. dwIdx = 0;
  447. while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx))
  448. {
  449. if (pArg->dwsidOption == dwsidOption)
  450. {
  451. return((pArg->fSet) ? TRUE : FALSE);
  452. }
  453. dwIdx++;
  454. }
  455. return(FALSE);
  456. }
  457. void *cWArgv_::GetValue(DWORD dwsidOption)
  458. {
  459. ARGVSTORAGE *pArg;
  460. DWORD dwIdx;
  461. dwIdx = 0;
  462. while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx))
  463. {
  464. if (pArg->dwsidOption == dwsidOption)
  465. {
  466. switch (pArg->dwValueType)
  467. {
  468. case WARGV_VALUETYPE_BOOL: return((void *)(UINT_PTR)pArg->fValue);
  469. case WARGV_VALUETYPE_DWORDD:
  470. case WARGV_VALUETYPE_DWORDH: return((void *)(UINT_PTR)pArg->dwValue);
  471. case WARGV_VALUETYPE_WCHAR: return((void *)pArg->pwszValue);
  472. default:
  473. return(NULL);
  474. }
  475. }
  476. dwIdx++;
  477. }
  478. return(NULL);
  479. }
  480. WCHAR *cWArgv_::GetOptionHelp(DWORD dwsidOption)
  481. {
  482. if (!(pArgs))
  483. {
  484. return(NULL);
  485. }
  486. ARGVSTORAGE *pArg;
  487. DWORD dwIdx;
  488. dwIdx = 0;
  489. while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx))
  490. {
  491. if (pArg->dwsidOption == dwsidOption)
  492. {
  493. return(pArg->pwszOptionHelp);
  494. }
  495. dwIdx++;
  496. }
  497. return(NULL);
  498. }
  499. WCHAR *cWArgv_::GetOption(DWORD dwsidOption)
  500. {
  501. if (!(pArgs))
  502. {
  503. return(NULL);
  504. }
  505. ARGVSTORAGE *pArg;
  506. DWORD dwIdx;
  507. dwIdx = 0;
  508. while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx))
  509. {
  510. if (pArg->dwsidOption == dwsidOption)
  511. {
  512. return(pArg->pwszOption);
  513. }
  514. dwIdx++;
  515. }
  516. return(NULL);
  517. }
  518. WCHAR *cWArgv_::GetFileName(DWORD *pdwidxLast)
  519. {
  520. if (!(pArgs))
  521. {
  522. return(NULL);
  523. }
  524. ARGVSTORAGE *pArg;
  525. DWORD dwIdx;
  526. DWORD dwFIdx;
  527. dwIdx = 0;
  528. dwFIdx = 1;
  529. while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx))
  530. {
  531. if (pArg->dwsidOption == SID_FILES)
  532. {
  533. if (!(pdwidxLast) || (dwFIdx > *pdwidxLast))
  534. {
  535. return(pArg->pwszValue);
  536. }
  537. dwFIdx++;
  538. }
  539. dwIdx++;
  540. }
  541. return(NULL);
  542. }
  543. BOOL cWArgv_::AddFile(WCHAR *pwszFile)
  544. {
  545. ARGVSTORAGE *pArg;
  546. if (!(pArg = (ARGVSTORAGE *)pArgs->Add(sizeof(ARGVSTORAGE))))
  547. {
  548. return(FALSE);
  549. }
  550. memset(pArg, 0x00, sizeof(ARGVSTORAGE));
  551. pArg->dwsidOption = SID_FILES;
  552. pArg->dwValueType = WARGV_VALUETYPE_WCHAR;
  553. pArg->pwszValue = pwszFile;
  554. this->StripQuotes(pArg->pwszValue);
  555. return(TRUE);
  556. }
  557. BOOL cWArgv_::ProcessCommandFile(WCHAR *pwszFile)
  558. {
  559. if (!(this->fChkCmdF))
  560. {
  561. return(FALSE);
  562. }
  563. HANDLE hFile;
  564. BOOL fFailed = FALSE;
  565. fParse_ fp(pwszFile, &fFailed);
  566. WCHAR *pwsz;
  567. if (fFailed)
  568. {
  569. return FALSE;
  570. }
  571. fp.Reset();
  572. while (fp.GetNextLine())
  573. {
  574. fp.EOLRemove();
  575. if ((fp.GetCurrentLine()) && (fp.GetCurrentLine()[0]))
  576. {
  577. pwsz = fp.GetCurrentLine();
  578. this->Fill(1, &pwsz);
  579. }
  580. }
  581. return(TRUE);
  582. }
  583. void cWArgv_::StripQuotes(WCHAR *pwszIn)
  584. {
  585. DWORD dwSrc;
  586. DWORD dwDst;
  587. DWORD dwLen;
  588. dwSrc = 0;
  589. dwDst = 0;
  590. dwLen = wcslen(pwszIn);
  591. while (dwSrc < dwLen)
  592. {
  593. if (pwszIn[dwSrc] != L'\"')
  594. {
  595. pwszIn[dwDst] = pwszIn[dwSrc];
  596. dwDst++;
  597. }
  598. dwSrc++;
  599. }
  600. pwszIn[dwDst] = NULL;
  601. }