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.

500 lines
12 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. Module Name:
  4. tclHelp
  5. Abstract:
  6. Routines to simplify Tcl command line parsing.
  7. Author:
  8. Doug Barlow (dbarlow) 9/16/1997
  9. Environment:
  10. Tcl for Windows NT.
  11. Notes:
  12. --*/
  13. #ifndef WIN32_LEAN_AND_MEAN
  14. #define WIN32_LEAN_AND_MEAN
  15. #endif
  16. #include <windows.h> // All the Windows definitions.
  17. #ifndef __STDC__
  18. #define __STDC__ 1
  19. #endif
  20. #include "tclhelp.h"
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <stdarg.h>
  24. char outfile[FILENAME_MAX];
  25. int
  26. commonParams(
  27. Tcl_Interp *interp,
  28. int argc,
  29. char *argv[],
  30. unsigned long int *cmdIndex,
  31. formatType *inFormat,
  32. formatType *outFormat)
  33. {
  34. if (NULL != inFormat)
  35. *inFormat = format_hexidecimal;
  36. if (NULL != outFormat)
  37. {
  38. *outFormat = format_hexidecimal;
  39. outfile[0] = '\000';
  40. }
  41. while (*cmdIndex < (unsigned long int)argc)
  42. {
  43. switch (poption(argv[(*cmdIndex)++],
  44. "-INPUT", "/INPUT", "-OUTPUT", "/OUTPUT", NULL))
  45. {
  46. case 1: // -input { text | hexidecimal | file }
  47. case 2:
  48. if (NULL == inFormat)
  49. {
  50. badSyntax(interp, argv, --(*cmdIndex));
  51. goto ErrorExit;
  52. }
  53. if (*cmdIndex == (unsigned long int)argc)
  54. {
  55. Tcl_AppendResult(interp, "Insufficient parameters", NULL);
  56. goto ErrorExit;
  57. }
  58. switch (poption(argv[(*cmdIndex)++],
  59. "TEXT", "HEXIDECIMAL", "FILE", NULL))
  60. {
  61. case 1:
  62. *inFormat = format_text;
  63. break;
  64. case 2:
  65. *inFormat = format_hexidecimal;
  66. break;
  67. case 3:
  68. *inFormat = format_file;
  69. break;
  70. default:
  71. Tcl_AppendResult(interp, "Unknown input format", NULL);
  72. goto ErrorExit;
  73. }
  74. break;
  75. case 3: // -output { text | hexidecimal | file <filename> }
  76. case 4:
  77. if (NULL == outFormat)
  78. {
  79. badSyntax(interp, argv, --(*cmdIndex));
  80. goto ErrorExit;
  81. }
  82. if (*cmdIndex == (unsigned long int)argc)
  83. {
  84. Tcl_AppendResult(interp, "Insufficient parameters", NULL);
  85. goto ErrorExit;
  86. }
  87. switch (poption(argv[(*cmdIndex)++],
  88. "TEXT", "HEXIDECIMAL", "FILE", "DROP", NULL))
  89. {
  90. case 1:
  91. *outFormat = format_text;
  92. break;
  93. case 2:
  94. *outFormat = format_hexidecimal;
  95. break;
  96. case 3:
  97. if (*cmdIndex == (unsigned long int)argc)
  98. {
  99. Tcl_AppendResult(interp, "Insufficient parameters", NULL);
  100. goto ErrorExit;
  101. }
  102. strcpy(outfile, argv[(*cmdIndex)++]);
  103. *outFormat = format_file;
  104. break;
  105. case 4:
  106. *outFormat = format_empty;
  107. break;
  108. default:
  109. Tcl_AppendResult(interp, "Unknown output format", NULL);
  110. goto ErrorExit;
  111. }
  112. break;
  113. default:
  114. *cmdIndex -= 1;
  115. return TCL_OK;
  116. }
  117. }
  118. return TCL_OK;
  119. ErrorExit:
  120. return TCL_ERROR;
  121. }
  122. int
  123. setResult(
  124. Tcl_Interp *interp,
  125. BYTE *aResult,
  126. BYTE aResultLen,
  127. formatType outFormat)
  128. {
  129. static char
  130. hexbuf[514];
  131. DWORD
  132. index;
  133. FILE *
  134. fid
  135. = NULL;
  136. switch (outFormat)
  137. {
  138. case format_empty:
  139. break;
  140. case format_text:
  141. aResult[aResultLen] = '\000';
  142. Tcl_AppendResult(interp, aResult, NULL);
  143. break;
  144. case format_hexidecimal:
  145. for (index = 0; index < aResultLen; index += 1)
  146. sprintf(&hexbuf[index * 2], "%02x", aResult[index]);
  147. hexbuf[aResultLen * 2] = '\000';
  148. Tcl_AppendResult(interp, hexbuf, NULL);
  149. break;
  150. case format_file:
  151. if ('\000' == outfile[0])
  152. {
  153. Tcl_AppendResult(interp, "Illegal output format", NULL);
  154. goto ErrorExit;
  155. }
  156. fid = fopen(outfile, "wb");
  157. index = fwrite(aResult, sizeof(BYTE), aResultLen, fid);
  158. if (index != aResultLen)
  159. {
  160. Tcl_AppendResult(interp, ErrorString(GetLastError()), NULL);
  161. goto ErrorExit;
  162. }
  163. fclose(fid);
  164. Tcl_AppendResult(interp, outfile, NULL);
  165. break;
  166. default:
  167. Tcl_AppendResult(interp, "Unknown output format", NULL);
  168. goto ErrorExit;
  169. }
  170. return TCL_OK;
  171. ErrorExit:
  172. if (NULL != fid)
  173. fclose(fid);
  174. return TCL_ERROR;
  175. }
  176. int
  177. inParam(
  178. Tcl_Interp *interp,
  179. BYTE **output,
  180. BYTE *length,
  181. char *input,
  182. formatType format)
  183. {
  184. static BYTE
  185. buffer[256];
  186. unsigned long int
  187. len, index, hex;
  188. FILE *
  189. fid = NULL;
  190. len = strlen(input);
  191. switch (format)
  192. {
  193. case format_text:
  194. if (255 < len)
  195. {
  196. Tcl_AppendResult(interp, "Input too long.", NULL);
  197. goto ErrorExit;
  198. }
  199. *output = (BYTE *)input;
  200. *length = (BYTE)len;
  201. break;
  202. case format_hexidecimal:
  203. if (510 < len)
  204. {
  205. Tcl_AppendResult(interp, "Input too long.", NULL);
  206. goto ErrorExit;
  207. }
  208. if (len != strspn(input, "0123456789ABCDEFabcdef"))
  209. {
  210. fprintf(stderr, "Invalid Hex number.\n");
  211. goto ErrorExit;
  212. }
  213. for (index = 0; index < len; index += 2)
  214. {
  215. sscanf(&input[index], " %2lx", &hex);
  216. buffer[index / 2] = (BYTE)hex;
  217. }
  218. *output = buffer;
  219. *length = (BYTE)((0 == (len & 0x01)) ? (len / 2) : (len / 2 + 1));
  220. break;
  221. case format_file:
  222. fid = fopen(input, "rb");
  223. if (NULL == fid)
  224. {
  225. Tcl_AppendResult(interp, ErrorString(GetLastError()), NULL);
  226. goto ErrorExit;
  227. }
  228. *length = (BYTE)fread(buffer, sizeof(BYTE), sizeof(buffer), fid);
  229. if (0 != ferror(fid))
  230. {
  231. Tcl_AppendResult(interp, ErrorString(GetLastError()), NULL);
  232. goto ErrorExit;
  233. }
  234. *output = buffer;
  235. fclose(fid);
  236. break;
  237. default:
  238. Tcl_AppendResult(interp, "Unknown input format", NULL);
  239. goto ErrorExit;
  240. }
  241. return TCL_OK;
  242. ErrorExit:
  243. if (NULL != fid)
  244. fclose(fid);
  245. return TCL_ERROR;
  246. }
  247. BOOL
  248. ParamCount(
  249. Tcl_Interp *interp,
  250. DWORD argc,
  251. DWORD cmdIndex,
  252. DWORD dwCount)
  253. {
  254. BOOL fSts = TRUE;
  255. if (cmdIndex + dwCount > (unsigned long int)argc)
  256. {
  257. Tcl_AppendResult(interp, "Insufficient parameters", NULL);
  258. fSts = FALSE;
  259. }
  260. return fSts;
  261. }
  262. void
  263. badSyntax(
  264. Tcl_Interp *interp,
  265. char *argv[],
  266. unsigned long int cmdIndex)
  267. {
  268. unsigned long int
  269. index;
  270. Tcl_ResetResult(interp);
  271. Tcl_AppendResult(interp, "Invalid option '", NULL);
  272. Tcl_AppendResult(interp, argv[cmdIndex], NULL);
  273. Tcl_AppendResult(interp, "' to the '", NULL);
  274. for (index = 0; index < cmdIndex; index += 1)
  275. Tcl_AppendResult(interp, argv[index], " ", NULL);
  276. Tcl_AppendResult(interp, "...' command.", NULL);
  277. }
  278. void
  279. SetMultiResult(
  280. Tcl_Interp *interp,
  281. LPTSTR mszResult)
  282. {
  283. LPTSTR sz = mszResult;
  284. while (0 != *sz)
  285. {
  286. Tcl_AppendElement(interp, sz);
  287. sz += strlen(sz) + 1;
  288. }
  289. }
  290. LPWSTR
  291. Unicode(
  292. LPCSTR sz)
  293. {
  294. static WCHAR szUnicode[2048];
  295. int length;
  296. length =
  297. MultiByteToWideChar(
  298. CP_ACP,
  299. MB_PRECOMPOSED,
  300. sz,
  301. strlen(sz),
  302. szUnicode,
  303. sizeof(szUnicode) / sizeof(WCHAR));
  304. szUnicode[length] = 0;
  305. return szUnicode;
  306. }
  307. static char *
  308. ErrorBuffer
  309. = NULL;
  310. char *
  311. ErrorString(
  312. long theError)
  313. {
  314. if (NULL != ErrorBuffer)
  315. {
  316. LocalFree(ErrorBuffer);
  317. ErrorBuffer = NULL;
  318. }
  319. if (0 == FormatMessage(
  320. FORMAT_MESSAGE_ALLOCATE_BUFFER
  321. | FORMAT_MESSAGE_FROM_SYSTEM,
  322. NULL,
  323. theError,
  324. LANG_NEUTRAL,
  325. (LPTSTR)&ErrorBuffer,
  326. 0,
  327. NULL))
  328. {
  329. if (0 == FormatMessage(
  330. FORMAT_MESSAGE_ALLOCATE_BUFFER
  331. | FORMAT_MESSAGE_FROM_HMODULE,
  332. GetModuleHandle(NULL),
  333. theError,
  334. LANG_NEUTRAL,
  335. (LPTSTR)&ErrorBuffer,
  336. 0,
  337. NULL))
  338. {
  339. if (0 == FormatMessage(
  340. FORMAT_MESSAGE_ALLOCATE_BUFFER
  341. | FORMAT_MESSAGE_FROM_HMODULE,
  342. GetModuleHandle(TEXT("winscard")),
  343. theError,
  344. LANG_NEUTRAL,
  345. (LPTSTR)&ErrorBuffer,
  346. 0,
  347. NULL))
  348. {
  349. ErrorBuffer = LocalAlloc(LMEM_FIXED, 32 * sizeof(TCHAR));
  350. sprintf(ErrorBuffer, "Unknown error code 0x%08x", theError);
  351. }
  352. }
  353. }
  354. return ErrorBuffer;
  355. } /* end LastErrorString */
  356. void
  357. FreeErrorString(
  358. void)
  359. {
  360. if (NULL != ErrorBuffer)
  361. LocalFree(ErrorBuffer);
  362. ErrorBuffer = NULL;
  363. } /* end FreeErrorString */
  364. int
  365. poption(
  366. const char *opt,
  367. ...)
  368. /*
  369. *
  370. * Function description:
  371. *
  372. * poption takes a list of keywords, supplied by parameters, and returns
  373. * the number in the list that matches the input option in the first
  374. * parameter. If the input option doesn't match any in the list, then a
  375. * zero is returned. If the input option is an abbreviation of an option,
  376. * then the match completes. For example, an input option of "de" would
  377. * match "debug" or "decode". If both were present in the possible
  378. * options list, then a match would be declared for the first possible
  379. * option encountered.
  380. *
  381. *
  382. * Arguments:
  383. *
  384. * opt - The option to match against.
  385. *
  386. * opt1, opt2, ... - Pointers to null terminated strings containing
  387. * the possible options to look for. The last option must be NULL,
  388. * indicating the end of the list.
  389. *
  390. *
  391. * Return value:
  392. *
  393. * 0 - No match found
  394. * 1-n - Match on option number i, 0 < i <= n, where n is the number
  395. * of options given, excluding the terminating NULL.
  396. *
  397. *
  398. * Side effects:
  399. *
  400. * None.
  401. *
  402. */
  403. {
  404. /*
  405. * Local Variable Definitions: %local-vars%
  406. *
  407. Variable Description
  408. -------- --------------------------------------------*/
  409. va_list
  410. ap; /* My parameter context. */
  411. int
  412. len, /* Length of the option string. */
  413. ret /* The return value. */
  414. = 0,
  415. index /* loop index. */
  416. = 1;
  417. char
  418. *kw; /* Pointer to the next option */
  419. /*
  420. * Start of Code.
  421. */
  422. va_start(ap, opt);
  423. /*
  424. * Step through each input parameter until we find an exact match.
  425. */
  426. len = strlen(opt);
  427. if (0 == len)
  428. return 0; /* Empty strings don't match anything. */
  429. kw = va_arg(ap, char*);
  430. while (NULL != kw)
  431. {
  432. if (0 == _strnicmp(kw, opt, len))
  433. {
  434. ret = index;
  435. break;
  436. }
  437. kw = va_arg(ap, char*);
  438. index += 1;
  439. }
  440. va_end(ap);
  441. return ret;
  442. } /* end poption */