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.

272 lines
8.5 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft OLE
  4. // Copyright (C) Microsoft Corporation, 1996 - 1997.
  5. //
  6. // File: dumpcmd.cpp
  7. //
  8. // Contents: dump commandline intelligently
  9. //
  10. // Functions:
  11. //
  12. // History: 07/29/97 SCousens Created
  13. //
  14. //--------------------------------------------------------------------------
  15. #include <dfheader.hxx>
  16. #pragma hdrstop
  17. // Debug Object declaration
  18. DH_DECLARE;
  19. struct _options
  20. {
  21. LPTSTR name;
  22. LPTSTR value;
  23. };
  24. #define CHSLASH TEXT('/')
  25. #define CHDASH TEXT('-')
  26. #define SAFESTRING(a) a ? a : TEXT("")
  27. #define ABORTIF(a,b) if (a) {hr = b; goto EndOfFunction;}
  28. #define FindNextToken(ptr, tok) \
  29. while (TEXT('\0') != *(ptr) && tok != (*(ptr))) ++(ptr);
  30. inline LPTSTR StringToken (LPTSTR ptr, TCHAR tok)
  31. {
  32. FindNextToken (ptr, tok);
  33. if (tok == *ptr) *ptr = NULL;
  34. else if (TEXT('\0') == *ptr) ptr = NULL;
  35. return ptr;
  36. }
  37. CONST TCHAR chNull = TEXT('\0');
  38. CONST TCHAR szCmdLine[] = TEXT("CommandLine:"); // Used DumpCmdLine
  39. CONST TCHAR szCmdLineFail[] = TEXT("CommandLineFail:"); // Used DumpCmdLine
  40. //+-------------------------------------------------------------------
  41. // Member: DumpCmdLine, public
  42. //
  43. // Synopsis: Gets the commandline via GetCommandLine, appends the
  44. // given string to it (additional options to reproduce
  45. // particular test), and calls TraceMsg to output it.
  46. // Depending on fResult, the key word 'CommandLine' or
  47. // 'CommandLineFail' will be prepended.
  48. //
  49. // Arguments: [fResult]- Pass or fail (to choose keyword).
  50. // [pszFmt] - Trace message format string.
  51. // [...] - Arguments for format string.
  52. //
  53. // Returns: Nothing.
  54. //
  55. // History: 09-Oct-97 SCousens Created
  56. //--------------------------------------------------------------------
  57. void DumpCmdLine (DWORD fResult, LPTSTR pszFmt, ...)
  58. {
  59. va_list varArgs;
  60. LPCTSTR ptKeyWord, ptCmdLine;
  61. TCHAR szBuffer[CCH_MAX_DBG_CHARS];
  62. LPTSTR pRepro = NULL;
  63. // figure out what key word to use
  64. ptKeyWord = (LOG_FAIL == fResult) ? szCmdLineFail : szCmdLine;
  65. // set our buffer...if we are given something format it nicely
  66. if (NULL != pszFmt && TCHAR('\0') != *pszFmt)
  67. {
  68. // format what we are given in the way of text.
  69. va_start(varArgs, pszFmt);
  70. _vsntprintf(szBuffer, CCH_MAX_DBG_CHARS, pszFmt, varArgs);
  71. szBuffer[CCH_MAX_DBG_CHARS-1] = chNull;
  72. va_end(varArgs);
  73. }
  74. else
  75. {
  76. szBuffer[0] = TCHAR('\0');
  77. }
  78. // Get the CommandLine
  79. ptCmdLine = GetCommandLine();
  80. if (NULL == ptCmdLine)
  81. {
  82. ptCmdLine = TEXT("GetCmdLine Error");
  83. }
  84. // now merge the two intelligently. parameters override cmdline
  85. // and dump the commandline and whatever we were given.
  86. if (S_OK == MergeParams (ptCmdLine, szBuffer, &pRepro))
  87. {
  88. DH_TRACE ((DH_LVL_ALWAYS, TEXT("%s:%s"), ptKeyWord, pRepro));
  89. delete []pRepro;
  90. }
  91. else
  92. {
  93. DH_TRACE ((DH_LVL_ALWAYS, TEXT("%s:%s %s"),
  94. ptKeyWord, ptCmdLine, szBuffer));
  95. }
  96. return;
  97. }
  98. //+-------------------------------------------------------------------
  99. // Member: MergeParams, private
  100. //
  101. // Synopsis: Given two sets of parameters, merge the two into one
  102. // set, without duplication. Last one wins.
  103. // given
  104. // program /foo /bar /seed:0 /foo:bar
  105. // /seed:1234 /ms:rules
  106. // returns
  107. // program /foo:bar /bar /seed:1234 /ms:rules
  108. //
  109. // Arguments: [cmdline] - contents of GetCommandLine call.
  110. // [additional] - additional options.
  111. // [repro] - pointer for resulting string
  112. //
  113. // Returns: HRESULT - S_OK or failure
  114. //
  115. // History: 10-Nov-97 SCousens Created
  116. //
  117. // Notes: Caller must call delete [] on returned buffer
  118. //--------------------------------------------------------------------
  119. HRESULT MergeParams (LPCTSTR ptCmdLine, LPCTSTR ptAdditional, LPTSTR *ptRepro)
  120. {
  121. struct _options *pOptions;
  122. int x, y, n, l;
  123. int nParams = 1;
  124. HRESULT hr = S_OK;
  125. LPTSTR pname, pvalue, pnext, ptr;
  126. LPTSTR name, value;
  127. LPTSTR ptCmd = NULL;
  128. //validate our inputs/outputs
  129. DH_VDATESTRINGPTR (ptCmdLine);
  130. if (ptAdditional)
  131. DH_VDATESTRINGPTR (ptAdditional);
  132. DH_VDATEPTROUT (ptRepro, LPTSTR);
  133. // copy the strings into one buffer, coz we are going to stomp on them
  134. // how much space do we need?
  135. l = _tcslen (ptCmdLine);
  136. if (ptAdditional)
  137. l += _tcslen (ptAdditional);
  138. //allocate a buffer
  139. ptCmd = new TCHAR[l + 2];
  140. ABORTIF (NULL == ptCmd, E_OUTOFMEMORY);
  141. memset (ptCmd, 0xFA, l+2); //BUGBUG do this to find why we died in
  142. //FindNextToken at one point. Seem to have
  143. //had a non-terminated string for some reason.
  144. //cat the two strings into the allocd buffer
  145. l = _stprintf (ptCmd, TEXT("%s"), ptCmdLine);
  146. if (ptAdditional)
  147. _stprintf (&ptCmd[l], TEXT(" %s"), ptAdditional);
  148. // count # parameters (ie spaces) in CmdLine
  149. ptr = ptCmd;
  150. while (NULL != *ptr)
  151. {
  152. if (TEXT(' ') == *ptr++)
  153. nParams++;
  154. }
  155. DH_TRACE ((DH_LVL_TRACE4, TEXT("Found %d params"), nParams));
  156. // allocate an _options for each possible parameter
  157. pOptions = new struct _options[nParams];
  158. ABORTIF (NULL == pOptions, E_OUTOFMEMORY);
  159. // go through and setup each of the _options (cmdline and given)
  160. for (pnext = ptCmd, nParams=0, x=0; NULL != pnext; x++)
  161. {
  162. pname = pnext;
  163. pnext = StringToken (pname, TEXT(' ')); //strtok/strchr equivalent
  164. if (pnext && NULL == *pnext) //safety check
  165. pnext++;
  166. //ignore emptys caused by extra spaces
  167. if (NULL == *pname)
  168. continue;
  169. //change '-' to '/' so we are uniform in our comparison
  170. if (CHDASH == *pname)
  171. *pname = CHSLASH;
  172. pvalue = StringToken (pname, TEXT(':'));
  173. //deal with option
  174. name = new TCHAR[_tcslen (pname)+1];
  175. ABORTIF (NULL == name, E_OUTOFMEMORY);
  176. _tcscpy (name, pname);
  177. // if there is a value, deal with that
  178. value = 0;
  179. if (NULL != pvalue)
  180. {
  181. pvalue++; //move past ':'
  182. value = new TCHAR[_tcslen (pvalue)+1];
  183. ABORTIF (NULL == value, E_OUTOFMEMORY);
  184. _tcscpy (value, pvalue);
  185. }
  186. //name is pointing to a string for name
  187. //value is pointing to a string for val, else null
  188. DH_TRACE ((DH_LVL_TRACE4, TEXT("Item[%d]: name:'%s': value:'%s'"),
  189. nParams, name, value ? value : TEXT("null")));
  190. pOptions[nParams].name = name;
  191. pOptions[nParams].value = value;
  192. nParams++;
  193. }
  194. // Now go thru and make a repro line without dups.
  195. // last one wins.
  196. for (x=0, l=0; x<nParams; x++)
  197. {
  198. // if its been used, skip it
  199. if (0 == pOptions[x].name[0])
  200. continue;
  201. n = x;
  202. // look for dups, and if we have a dup, use the second one
  203. for (y=x+1; y<nParams; y++)
  204. {
  205. // if its been canned, skip it
  206. if (0 == pOptions[y].name[0])
  207. continue;
  208. if (!_tcsicmp (pOptions[n].name, pOptions[y].name))
  209. {
  210. pOptions[n].name[0] = 0; //mark 'old' option as used
  211. n = y; // This is the one we will use
  212. }
  213. }
  214. //now n is the last option
  215. //add option[n] to end of line
  216. if (x) //prepend space all except 1st
  217. l+=_stprintf (&ptCmd[l], TEXT(" "));
  218. l+=_stprintf (&ptCmd[l], TEXT("%s"), pOptions[n].name);
  219. if (NULL != pOptions[n].value) //add value if there is one
  220. l+=_stprintf (&ptCmd[l], TEXT(":%s"), pOptions[n].value);
  221. pOptions[n].name[0] = 0; //mark this option as used
  222. }
  223. DH_TRACE ((DH_LVL_TRACE4, TEXT("cmd:%s"), ptCmd));
  224. //now delete the _options we allocated
  225. for (x=0; x<nParams; x++)
  226. {
  227. delete []pOptions[x].name;
  228. delete []pOptions[x].value;
  229. }
  230. delete []pOptions;
  231. //give them what they really want
  232. *ptRepro = ptCmd;
  233. EndOfFunction:
  234. return hr;
  235. }