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.

539 lines
15 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000
  5. //
  6. // File: parserutil.cpp
  7. //
  8. // Contents: Helpful functions for manipulating and validating
  9. // generic command line arguments
  10. //
  11. // History: 07-Sep-2000 JeffJon Created
  12. //
  13. //
  14. //--------------------------------------------------------------------------
  15. #include "pch.h"
  16. #include "iostream.h"
  17. //+--------------------------------------------------------------------------
  18. //
  19. // Function: GetPasswdStr
  20. //
  21. // Synopsis: Reads a password string from stdin without echoing the keystrokes
  22. //
  23. // Arguments: [buf - OUT] : buffer to put string in
  24. // [buflen - IN] : size of the buffer
  25. // [&len - OUT] : length of the string placed into the buffer
  26. //
  27. // Returns: DWORD : 0 or ERROR_INSUFFICIENT_BUFFER if user typed too much.
  28. // Buffer contents are only valid on 0 return.
  29. //
  30. // History: 07-Sep-2000 JeffJon Created
  31. //
  32. //---------------------------------------------------------------------------
  33. #define CR 0xD
  34. #define BACKSPACE 0x8
  35. DWORD GetPasswdStr(LPTSTR buf,
  36. DWORD buflen,
  37. PDWORD len)
  38. {
  39. TCHAR ch;
  40. TCHAR *bufPtr = buf;
  41. DWORD c;
  42. int err;
  43. DWORD mode;
  44. buflen -= 1; /* make space for null terminator */
  45. *len = 0; /* GP fault probe (a la API's) */
  46. GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode);
  47. SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
  48. (~(ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT)) & mode);
  49. while (TRUE)
  50. {
  51. err = ReadConsole(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &c, 0);
  52. if (!err || c != 1)
  53. ch = 0xffff;
  54. if ((ch == CR) || (ch == 0xffff)) /* end of the line */
  55. break;
  56. if (ch == BACKSPACE)
  57. { /* back up one or two */
  58. /*
  59. * IF bufPtr == buf then the next two lines are
  60. * a no op.
  61. */
  62. if (bufPtr != buf)
  63. {
  64. bufPtr--;
  65. (*len)--;
  66. }
  67. }
  68. else
  69. {
  70. *bufPtr = ch;
  71. if (*len < buflen)
  72. bufPtr++ ; /* don't overflow buf */
  73. (*len)++; /* always increment len */
  74. }
  75. }
  76. SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
  77. *bufPtr = TEXT('\0'); /* null terminate the string */
  78. putwchar(TEXT('\n'));
  79. return ((*len <= buflen) ? 0 : ERROR_INSUFFICIENT_BUFFER);
  80. }
  81. //+--------------------------------------------------------------------------
  82. //
  83. // Function: ValidatePassword
  84. //
  85. // Synopsis: Password validation function called by parser
  86. //
  87. // Arguments: [pArg - IN] : pointer argument structure which contains
  88. // the value to be validated
  89. //
  90. // Returns: DWORD : ERROR_INVALID_PARAMETER if the argument record or
  91. // the value it contains is not valid
  92. // ERROR_NOT_ENOUGH_MEMORY
  93. // ERROR_SUCCESS if everything succeeded and it is a
  94. // valid password
  95. // Otherwise it is an error condition returned from
  96. // GetPasswdStr
  97. //
  98. // History: 07-Sep-2000 JeffJon Created
  99. //
  100. //---------------------------------------------------------------------------
  101. DWORD ValidatePassword(PVOID pArg, UINT IdStr)
  102. {
  103. PARG_RECORD pRec = (PARG_RECORD)pArg;
  104. if(!pRec || !pRec->strValue)
  105. return ERROR_INVALID_PARAMETER;
  106. if(wcscmp(pRec->strValue, L"*") != 0 )
  107. return ERROR_SUCCESS;
  108. CComBSTR sbstrPrompt;
  109. if(sbstrPrompt.LoadString(::GetModuleHandle(NULL),IdStr))
  110. {
  111. DisplayOutput(sbstrPrompt);
  112. }
  113. else
  114. DisplayOutput(L"Enter Password\n");
  115. WCHAR buffer[MAX_PASSWORD_LENGTH];
  116. DWORD len = 0;
  117. DWORD dwErr = GetPasswdStr(buffer,MAX_PASSWORD_LENGTH,&len);
  118. if(dwErr != ERROR_SUCCESS)
  119. return dwErr;
  120. LocalFree(pRec->strValue);
  121. pRec->strValue = (LPWSTR)LocalAlloc(LPTR,sizeof(WCHAR)*(len+1));
  122. if(!pRec->strValue)
  123. return ERROR_NOT_ENOUGH_MEMORY;
  124. else
  125. {
  126. wcscpy(pRec->strValue,buffer);
  127. return ERROR_SUCCESS;
  128. }
  129. }
  130. //+--------------------------------------------------------------------------
  131. //
  132. // Function: ValidateAdminPassword
  133. //
  134. // Synopsis: Password validation function called by parser for Admin
  135. //
  136. // Arguments: [pArg - IN] : pointer argument structure which contains
  137. // the value to be validated
  138. //
  139. // Returns: DWORD : ERROR_INVALID_PARAMETER if the argument record or
  140. // the value it contains is not valid
  141. // ERROR_SUCCESS if everything succeeded and it is a
  142. // valid password
  143. //
  144. // History: 07-Sep-2000 Hiteshr Created
  145. //
  146. //---------------------------------------------------------------------------
  147. DWORD ValidateAdminPassword(PVOID pArg)
  148. {
  149. return ValidatePassword(pArg,IDS_ADMIN_PASSWORD_PROMPT);
  150. }
  151. //+--------------------------------------------------------------------------
  152. //
  153. // Function: ValidateUserPassword
  154. //
  155. // Synopsis: Password validation function called by parser for Admin
  156. //
  157. // Arguments: [pArg - IN] : pointer argument structure which contains
  158. // the value to be validated
  159. //
  160. // Returns: DWORD : Same as ValidatePassword
  161. //
  162. // History: 07-Sep-2000 Hiteshr Created
  163. //
  164. //---------------------------------------------------------------------------
  165. DWORD ValidateUserPassword(PVOID pArg)
  166. {
  167. return ValidatePassword(pArg, IDS_USER_PASSWORD_PROMPT);
  168. }
  169. //+--------------------------------------------------------------------------
  170. //
  171. // Function: ValidateYesNo
  172. //
  173. // Synopsis: Password validation function called by parser for Admin
  174. //
  175. // Arguments: [pArg - IN] : pointer argument structure which contains
  176. // the value to be validated
  177. //
  178. // Returns: DWORD : Same as ValidatePassword
  179. //
  180. // History: 07-Sep-2000 Hiteshr Created
  181. //
  182. //---------------------------------------------------------------------------
  183. DWORD ValidateYesNo(PVOID pArg)
  184. {
  185. PARG_RECORD pRec = (PARG_RECORD)pArg;
  186. if(!pRec || !pRec->strValue)
  187. return ERROR_INVALID_PARAMETER;
  188. CComBSTR sbstrYes;
  189. CComBSTR sbstrNo;
  190. CComBSTR sbstrInput;
  191. if(!sbstrYes.LoadString(::GetModuleHandle(NULL),IDS_YES))
  192. {
  193. return ERROR_RESOURCE_DATA_NOT_FOUND;
  194. }
  195. if(!sbstrNo.LoadString(::GetModuleHandle(NULL), IDS_NO))
  196. {
  197. return ERROR_RESOURCE_DATA_NOT_FOUND;
  198. }
  199. sbstrYes.ToLower();
  200. sbstrNo.ToLower();
  201. sbstrInput = pRec->strValue;
  202. sbstrInput.ToLower();
  203. if( sbstrInput == sbstrYes )
  204. {
  205. LocalFree(pRec->strValue);
  206. pRec->bValue = TRUE;
  207. }
  208. else if( sbstrInput == sbstrNo )
  209. {
  210. LocalFree(pRec->strValue);
  211. pRec->bValue = FALSE;
  212. }
  213. else
  214. return ERROR_INVALID_PARAMETER;
  215. //
  216. // Have to set this to bool or else
  217. // FreeCmd will try to free the string
  218. // which AVs when the bool is true
  219. //
  220. pRec->fType = ARG_TYPE_BOOL;
  221. return ERROR_SUCCESS;
  222. }
  223. //+--------------------------------------------------------------------------
  224. //
  225. // Function: ValidateNever
  226. //
  227. // Synopsis: Password validation function called by parser for Admin
  228. // Verifies the value contains digits or "NEVER"
  229. //
  230. // Arguments: [pArg - IN] : pointer argument structure which contains
  231. // the value to be validated
  232. //
  233. // Returns: DWORD : Same as ValidatePassword
  234. //
  235. // History: 07-Sep-2000 JeffJon Created
  236. //
  237. //---------------------------------------------------------------------------
  238. DWORD ValidateNever(PVOID pArg)
  239. {
  240. PARG_RECORD pRec = (PARG_RECORD)pArg;
  241. if(!pRec)
  242. return ERROR_INVALID_PARAMETER;
  243. if (pRec->fType == ARG_TYPE_STR)
  244. {
  245. CComBSTR sbstrInput;
  246. sbstrInput = pRec->strValue;
  247. if( _wcsicmp(sbstrInput, g_bstrNever) )
  248. {
  249. return ERROR_INVALID_PARAMETER;
  250. }
  251. }
  252. return ERROR_SUCCESS;
  253. }
  254. //+--------------------------------------------------------------------------
  255. //
  256. // Function: ValidateGroupScope
  257. //
  258. // Synopsis: Makes sure that the value following the -scope switch is one
  259. // of (l/g/u)
  260. //
  261. // Arguments: [pArg - IN] : pointer argument structure which contains
  262. // the value to be validated
  263. //
  264. // Returns: DWORD : Same as ValidatePassword
  265. //
  266. // History: 18-Sep-2000 JeffJon Created
  267. //
  268. //---------------------------------------------------------------------------
  269. DWORD ValidateGroupScope(PVOID pArg)
  270. {
  271. DWORD dwReturn = ERROR_SUCCESS;
  272. PARG_RECORD pRec = (PARG_RECORD)pArg;
  273. if(!pRec || !pRec->strValue)
  274. return ERROR_INVALID_PARAMETER;
  275. CComBSTR sbstrInput;
  276. sbstrInput = pRec->strValue;
  277. sbstrInput.ToLower();
  278. if(sbstrInput == _T("l") ||
  279. sbstrInput == _T("g") ||
  280. sbstrInput == _T("u"))
  281. {
  282. dwReturn = ERROR_SUCCESS;
  283. }
  284. else
  285. {
  286. dwReturn = ERROR_INVALID_PARAMETER;
  287. }
  288. return dwReturn;
  289. }
  290. //+--------------------------------------------------------------------------
  291. //
  292. // Function: MergeArgCommand
  293. //
  294. // Synopsis: Combines two ARG_RECORD arrays into a single
  295. //
  296. // Arguments: [pCommand1 - IN] : first ARG_RECORD array to merge
  297. // [pCommand2 - IN] : second ARG_RECORD array to merge
  298. // [ppOutCommand - OUT] : the array that results from the merge
  299. //
  300. // Returns: HRESULT : S_OK on success
  301. // E_OUTOFMEMORY if failed to allocate memory for new array
  302. //
  303. // History: 08-Sep-2000 JeffJon Created
  304. //
  305. //---------------------------------------------------------------------------
  306. HRESULT MergeArgCommand(PARG_RECORD pCommand1,
  307. PARG_RECORD pCommand2,
  308. PARG_RECORD *ppOutCommand)
  309. {
  310. HRESULT hr = S_OK;
  311. //
  312. // Verify parameters
  313. //
  314. if (!pCommand1 && pCommand2)
  315. {
  316. *ppOutCommand = pCommand2;
  317. return hr;
  318. }
  319. else if (pCommand1 && !pCommand2)
  320. {
  321. *ppOutCommand = pCommand1;
  322. return hr;
  323. }
  324. else if (!pCommand1 && !pCommand2)
  325. {
  326. return E_INVALIDARG;
  327. }
  328. LONG nSize1 = 0;
  329. LONG nSize2 = 0;
  330. UINT i = 0;
  331. for(i=0; pCommand1[i].fType != ARG_TYPE_LAST ;i++)
  332. {
  333. ++nSize1;
  334. }
  335. for(i=0; pCommand2[i].fType != ARG_TYPE_LAST ;i++)
  336. {
  337. ++nSize2;
  338. }
  339. *ppOutCommand = (PARG_RECORD)LocalAlloc(LPTR, sizeof(ARG_RECORD)*(nSize1+nSize2+1));
  340. if(!*ppOutCommand)
  341. {
  342. return E_OUTOFMEMORY;
  343. }
  344. memcpy(*ppOutCommand,pCommand1,sizeof(ARG_RECORD)*nSize1);
  345. memcpy((*ppOutCommand+nSize1),pCommand2,sizeof(ARG_RECORD)*(nSize2+1));
  346. return hr;
  347. }
  348. //+--------------------------------------------------------------------------
  349. //
  350. // Function: ParseStringByChar
  351. //
  352. // Synopsis: Parses a string into elements separated by the given character
  353. //
  354. // Arguments: [psz - IN] : string to be parsed
  355. // [tchar - IN] : character that is to be used as the separator
  356. // [pszArr - OUT] : the array to receive the parsed strings
  357. // [pnArrEntries - OUT] : the number of strings parsed from the list
  358. //
  359. // Returns:
  360. //
  361. // History: 18-Sep-2000 JeffJon Created
  362. // 14-Apr-2001 JeffJon Modified to separate on a generic character
  363. //
  364. //---------------------------------------------------------------------------
  365. void ParseStringByChar(PTSTR psz,
  366. TCHAR tchar,
  367. PTSTR** ppszArr,
  368. UINT* pnArrEntries)
  369. {
  370. //
  371. // Verify parameters
  372. //
  373. if (!psz ||
  374. !ppszArr ||
  375. !pnArrEntries)
  376. {
  377. ASSERT(psz);
  378. ASSERT(ppszArr);
  379. ASSERT(pnArrEntries);
  380. return;
  381. }
  382. //
  383. // Count the number of strings
  384. //
  385. UINT nCount = 0;
  386. PTSTR pszTemp = psz;
  387. while (true)
  388. {
  389. if (pszTemp[0] == tchar &&
  390. pszTemp[1] == tchar)
  391. {
  392. nCount++;
  393. break;
  394. }
  395. else if (pszTemp[0] == tchar &&
  396. pszTemp[1] != tchar)
  397. {
  398. nCount++;
  399. pszTemp++;
  400. }
  401. else
  402. {
  403. pszTemp++;
  404. }
  405. }
  406. *pnArrEntries = nCount;
  407. //
  408. // Allocate the array
  409. //
  410. *ppszArr = (PTSTR*)LocalAlloc(LPTR, nCount * sizeof(PTSTR));
  411. if (*ppszArr)
  412. {
  413. //
  414. // Copy the string pointers into the array
  415. //
  416. UINT nIdx = 0;
  417. pszTemp = psz;
  418. (*ppszArr)[nIdx] = pszTemp;
  419. nIdx++;
  420. while (true)
  421. {
  422. if (pszTemp[0] == tchar &&
  423. pszTemp[1] == tchar)
  424. {
  425. break;
  426. }
  427. else if (pszTemp[0] == tchar &&
  428. pszTemp[1] != tchar)
  429. {
  430. (*ppszArr)[nIdx] = &(pszTemp[1]);
  431. nIdx++;
  432. pszTemp++;
  433. }
  434. else
  435. {
  436. pszTemp++;
  437. }
  438. }
  439. }
  440. }
  441. //+--------------------------------------------------------------------------
  442. //
  443. // Function: ParseNullSeparatedString
  444. //
  445. // Synopsis: Parses a '\0' separated list that ends in "\0\0" into a string
  446. // array
  447. //
  448. // Arguments: [psz - IN] : '\0' separated string to be parsed
  449. // [pszArr - OUT] : the array to receive the parsed strings
  450. // [pnArrEntries - OUT] : the number of strings parsed from the list
  451. //
  452. // Returns:
  453. //
  454. // History: 14-Apr-2001 JeffJon Created
  455. //
  456. //---------------------------------------------------------------------------
  457. void ParseNullSeparatedString(PTSTR psz,
  458. PTSTR** ppszArr,
  459. UINT* pnArrEntries)
  460. {
  461. ParseStringByChar(psz,
  462. L'\0',
  463. ppszArr,
  464. pnArrEntries);
  465. }
  466. //+--------------------------------------------------------------------------
  467. //
  468. // Function: ParseSemicolonSeparatedString
  469. //
  470. // Synopsis: Parses a ';' separated list
  471. //
  472. // Arguments: [psz - IN] : ';' separated string to be parsed
  473. // [pszArr - OUT] : the array to receive the parsed strings
  474. // [pnArrEntries - OUT] : the number of strings parsed from the list
  475. //
  476. // Returns:
  477. //
  478. // History: 14-Apr-2001 JeffJon Created
  479. //
  480. //---------------------------------------------------------------------------
  481. void ParseSemicolonSeparatedString(PTSTR psz,
  482. PTSTR** ppszArr,
  483. UINT* pnArrEntries)
  484. {
  485. ParseStringByChar(psz,
  486. L';',
  487. ppszArr,
  488. pnArrEntries);
  489. }