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.

262 lines
6.9 KiB

  1. // Copyright (c) 1998-1999 Microsoft Corporation
  2. /*
  3. *
  4. * Module Name:
  5. *
  6. * toolinit.c
  7. *
  8. * Abstract:
  9. *
  10. * This file contains initialization code that is shared among all
  11. * the command line tools.
  12. *
  13. * Author:
  14. *
  15. * Breen Hagan (BreenH) Dec-16-98
  16. *
  17. * Environment:
  18. *
  19. * User Mode
  20. */
  21. #include <windows.h>
  22. #include <printfoa.h>
  23. /*
  24. * Function Implementations.
  25. */
  26. /*
  27. * MassageCommandLine()
  28. *
  29. * Obtains the command line, parses it as a UNICODE string, and returns
  30. * it in the ANSI argv style.
  31. *
  32. * Parameters:
  33. * IN DWORD dwArgC: The number of arguments on the command line.
  34. *
  35. * Return Values:
  36. * Returns a WCHAR array (WCHAR **), or NULL if an error occurs.
  37. * Extended error information is available from GetLastError().
  38. *
  39. */
  40. WCHAR**
  41. MassageCommandLine(
  42. IN DWORD dwArgC
  43. )
  44. {
  45. BOOL fInQuotes = FALSE, fInWord = TRUE;
  46. DWORD i, j, k, l;
  47. WCHAR *CmdLine;
  48. WCHAR **ArgVW;
  49. /*
  50. * argv can't be used because its always ANSI.
  51. */
  52. CmdLine = GetCommandLineW();
  53. /*
  54. * Convert from OEM character set to ANSI.
  55. */
  56. //OEM2ANSIW(CmdLine, (USHORT)wcslen(CmdLine));
  57. /*
  58. * Massage the new command line to look like an argv type
  59. * because ParseCommandLine() depends on this format
  60. */
  61. ArgVW = (WCHAR **)LocalAlloc(
  62. LPTR,
  63. (dwArgC + 1) * (sizeof(WCHAR *))
  64. );
  65. if(ArgVW == NULL) {
  66. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  67. return(NULL);
  68. }
  69. /*
  70. * Parse CmdLine by spaces (or tabs), ignoring spaces inside double quotes;
  71. * i.e. "1 2" is one argument, but cannot contain the double quotes
  72. * after parsing. Also, multiple spaces inside quotes are maintained,
  73. * while multiple spaces outside of quotes are condensed. Example:
  74. *
  75. * test.exe 1 "2 3" 4"5 6"7 8 '9 10'
  76. * will have as arguments:
  77. *
  78. * 0: test.exe
  79. * 1: 1
  80. * 2: 2 3
  81. * 3: 45 67
  82. * 4: 8
  83. * 5: '9
  84. * 6: 10'
  85. */
  86. i = j = k = 0;
  87. while (CmdLine[i] != (WCHAR)NULL) {
  88. if (CmdLine[i] == L' '||CmdLine[i] == L'\t') {
  89. if (!fInQuotes) {
  90. fInWord = FALSE;
  91. if (i != k) {
  92. CmdLine[i] = (WCHAR)NULL;
  93. ArgVW[j] = (WCHAR *)LocalAlloc(
  94. LPTR,
  95. (i - k + 1) * (sizeof(WCHAR))
  96. );
  97. if (ArgVW[j] != NULL) {
  98. wcscpy(ArgVW[j], &(CmdLine[k]));
  99. k = i + 1;
  100. j++;
  101. if (j > dwArgC) {
  102. SetLastError(ERROR_INVALID_PARAMETER);
  103. goto CleanUp;
  104. }
  105. } else {
  106. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  107. goto CleanUp;
  108. }
  109. } else {
  110. k = i + 1;
  111. }
  112. }
  113. } else if (CmdLine[i] == L'\"') {
  114. DWORD dwLen = wcslen(&(CmdLine[i]));
  115. //Added by a-skuzin
  116. //case when we need to have quota inside parameter and use " \" "
  117. if(i && (CmdLine[i-1] == L'\\')) {
  118. MoveMemory(
  119. &(CmdLine[i-1]),
  120. &(CmdLine[i]),
  121. (dwLen+1) * sizeof(WCHAR) // drop 1 char, add NULL
  122. );
  123. i--;
  124. fInWord = TRUE;
  125. goto increment;
  126. }
  127. //end of "added by a-skuzin"
  128. // Special case a double quote by itself or at the end of the line
  129. if (fInQuotes && (l == i)) {
  130. if ((dwLen == 1) || (CmdLine[i + 1] == L' ') || (CmdLine[i + 1] == L'\t')) {
  131. k = i;
  132. CmdLine[k] = (WCHAR)NULL;
  133. fInQuotes = FALSE;
  134. goto increment;
  135. }
  136. }
  137. if (fInQuotes && fInWord) {
  138. if ((dwLen == 2) && (CmdLine[i + 1] == L'\"')) {
  139. MoveMemory(
  140. &(CmdLine[i]),
  141. &(CmdLine[i + 1]),
  142. dwLen * sizeof(WCHAR) // drop 1 char, add NULL
  143. );
  144. goto increment;
  145. }
  146. if ((dwLen >= 3) &&
  147. (CmdLine[i + 1] == L'\"') &&
  148. (CmdLine[i + 2] != L' ') &&
  149. (CmdLine[i + 2] != L'\t')) {
  150. fInQuotes = FALSE;
  151. MoveMemory(
  152. &(CmdLine[i]),
  153. &(CmdLine[i + 1]),
  154. dwLen * sizeof(WCHAR) // drop 1 char, add NULL
  155. );
  156. goto increment;
  157. }
  158. if ((dwLen >= 3) &&
  159. (CmdLine[i + 1] == L'\"') &&
  160. (CmdLine[i + 2] == L' ') &&
  161. (CmdLine[i + 2] == L'\t')) {
  162. goto increment;
  163. }
  164. }
  165. if (!fInQuotes && fInWord && (dwLen == 1) && (j == 0)) {
  166. goto increment;
  167. }
  168. fInQuotes = !fInQuotes;
  169. if (fInQuotes && !fInWord) {
  170. fInWord = TRUE;
  171. l = i;
  172. }
  173. MoveMemory(
  174. &(CmdLine[i]),
  175. &(CmdLine[i + 1]),
  176. dwLen * sizeof(WCHAR) // drop 1 char, add NULL
  177. );
  178. i--;
  179. } else {
  180. fInWord = TRUE;
  181. }
  182. increment:
  183. i++;
  184. }
  185. if (i != k) {
  186. if (j >= dwArgC) {
  187. SetLastError(ERROR_INVALID_PARAMETER);
  188. goto CleanUp;
  189. }
  190. ArgVW[j] = (WCHAR *)LocalAlloc(
  191. LPTR,
  192. (i - k + 1) * (sizeof(WCHAR))
  193. );
  194. if (ArgVW[j] != NULL) {
  195. wcscpy(ArgVW[j], &(CmdLine[k]));
  196. } else {
  197. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  198. goto CleanUp;
  199. }
  200. } else if (fInQuotes && (l == i)) {
  201. if (j >= dwArgC) {
  202. SetLastError(ERROR_INVALID_PARAMETER);
  203. goto CleanUp;
  204. }
  205. ArgVW[j] = (WCHAR *)LocalAlloc(
  206. LPTR,
  207. (i - k + 1) * (sizeof(WCHAR))
  208. );
  209. if (ArgVW[j] != NULL) {
  210. wcscpy(ArgVW[j], &(CmdLine[k]));
  211. } else {
  212. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  213. goto CleanUp;
  214. }
  215. }
  216. ArgVW[dwArgC] = (WCHAR)NULL;
  217. return(ArgVW);
  218. CleanUp:
  219. for (i = 0; i < dwArgC; i++) {
  220. if (ArgVW[i] != NULL) {
  221. LocalFree(ArgVW[i]);
  222. }
  223. }
  224. LocalFree(ArgVW);
  225. return(NULL);
  226. }