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.

338 lines
7.9 KiB

  1. // xmlint.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. //====================================================================================
  5. // Generic wild-card file finder that calls back to specified function with
  6. // given void* arguments.
  7. typedef HRESULT (*FILECALLBACK)(WCHAR* pszFile, void* arg);
  8. WCHAR* WideString(const char* str)
  9. {
  10. if (str == NULL)
  11. return NULL;
  12. WCHAR * result = new WCHAR[strlen(str) + 1];
  13. WCHAR* p = result;
  14. while (*str)
  15. *p++ = (WCHAR)*str++;
  16. *p = 0;
  17. return result;
  18. }
  19. int ProcessFiles(const char* pszFiles, FILECALLBACK pFunc, void* pArgs)
  20. {
  21. HRESULT hr = S_OK;
  22. int i;
  23. WCHAR* wszArg = WideString(pszFiles);
  24. WIN32_FIND_DATA FindFileData;
  25. HANDLE handle = ::FindFirstFile(wszArg, &FindFileData);
  26. int failed = 0;
  27. if (handle == INVALID_HANDLE_VALUE)
  28. {
  29. // Then maybe it's a URL.
  30. hr = (*pFunc)(wszArg, pArgs);
  31. if (hr != 0) failed++;
  32. goto CleanUp;
  33. }
  34. for ( i = wcslen(wszArg)-1; i >= 0 && wszArg[i] != '\\'; i--)
  35. {
  36. wszArg[i] = 0;
  37. }
  38. while (handle != INVALID_HANDLE_VALUE)
  39. {
  40. ULONG len1 = wcslen(wszArg);
  41. ULONG len2 = wcslen(FindFileData.cFileName);
  42. WCHAR* buffer = new WCHAR[len1 + len2 + 1];
  43. if (buffer == NULL)
  44. {
  45. hr = E_OUTOFMEMORY;
  46. goto CleanUp;
  47. }
  48. memcpy(buffer, wszArg, sizeof(WCHAR) * len1);
  49. memcpy(&buffer[len1], FindFileData.cFileName, sizeof(WCHAR) * len2);
  50. buffer[len1+len2] = '\0';
  51. hr = (*pFunc)(buffer, pArgs);
  52. if (hr != 0) failed++;
  53. delete[] buffer;
  54. if (! ::FindNextFile(handle, &FindFileData))
  55. break;
  56. }
  57. if (handle != INVALID_HANDLE_VALUE)
  58. ::FindClose(handle);
  59. CleanUp:
  60. delete wszArg;
  61. return failed;
  62. }
  63. struct XMLArgs
  64. {
  65. public:
  66. XMLArgs()
  67. {
  68. pDOM = NULL;
  69. pIE4 = NULL;
  70. }
  71. IXMLDOMDocument* pDOM;
  72. IXMLDocument* pIE4;
  73. };
  74. void FormatError(BSTR bstrReason, BSTR bstrURL, BSTR bstrText, long lLine, long lPos)
  75. {
  76. if (bstrReason)
  77. {
  78. printf("\t%S", bstrReason);
  79. }
  80. if (bstrURL)
  81. {
  82. printf("\tURL: %S\n", bstrURL);
  83. }
  84. if (lLine > 0 && bstrText)
  85. {
  86. printf("\tLine %5.5ld: ", lLine);
  87. long lLen = ::SysStringLen(bstrText);
  88. for (int i = 0; i < lLen; i++)
  89. {
  90. if (bstrText[i] == '\t')
  91. printf(" ");
  92. else
  93. printf("%C", bstrText[i]);
  94. }
  95. printf("\n");
  96. if (lPos > 0 || lLen > 0)
  97. {
  98. printf("\tPos %5.5d: ", lPos);
  99. for (int i = 1; i < lPos; i++)
  100. {
  101. printf("-");
  102. }
  103. printf("^\n");
  104. }
  105. }
  106. }
  107. void PrintIE4Error(IXMLDocument* pDoc)
  108. {
  109. IXMLError *pError = NULL ;
  110. XML_ERROR xmle = { 0, 0, 0, 0, 0, 0 };
  111. HRESULT hr = S_OK;
  112. hr = pDoc->QueryInterface(IID_IXMLError, (void **)&pError);
  113. if (FAILED(hr))
  114. {
  115. printf("Error getting error information\n");
  116. goto done;
  117. }
  118. hr = pError->GetErrorInfo(&xmle);
  119. if (FAILED(hr))
  120. {
  121. printf("Error getting error information\n");
  122. goto done;
  123. }
  124. FormatError(xmle._pszFound, NULL, xmle._pchBuf, xmle._nLine, xmle._ich);
  125. done:
  126. SysFreeString(xmle._pszFound);
  127. SysFreeString(xmle._pszExpected);
  128. SysFreeString(xmle._pchBuf);
  129. if (pError) pError->Release();
  130. }
  131. void PrintDOMError(IXMLDOMDocument* pDoc)
  132. {
  133. IXMLDOMParseError* pError;
  134. BSTR bstrReason = NULL;
  135. BSTR bstrText = NULL;
  136. BSTR bstrURL = NULL;
  137. long lPos,lLine = 0;
  138. HRESULT hr = S_OK;
  139. hr = pDoc->get_parseError( &pError);
  140. if (FAILED(hr))
  141. {
  142. printf("Error getting error information\n");
  143. goto done;
  144. }
  145. pError->get_reason(&bstrReason);
  146. pError->get_url(&bstrURL);
  147. pError->get_line(&lLine);
  148. pError->get_srcText(&bstrText);
  149. pError->get_linepos(&lPos);
  150. FormatError(bstrReason, bstrURL, bstrText, lLine, lPos);
  151. done:
  152. SysFreeString( bstrReason);
  153. SysFreeString( bstrText);
  154. SysFreeString( bstrURL);
  155. if (pError) pError->Release();
  156. }
  157. HRESULT xmlint(WCHAR* pszFile, void* arg)
  158. {
  159. HRESULT hr = S_OK;
  160. XMLArgs* pArgs = (XMLArgs*)arg;
  161. printf("%S\n", pszFile);
  162. if (pArgs->pIE4)
  163. {
  164. IXMLElement * root;
  165. hr = pArgs->pIE4->put_URL(pszFile);
  166. pArgs->pIE4->get_root(&root);
  167. if (FAILED(hr) || ! root)
  168. {
  169. PrintIE4Error(pArgs->pIE4);
  170. }
  171. if (root) root->Release();
  172. }
  173. else
  174. {
  175. VARIANT_BOOL bSuccess;
  176. VARIANT url;
  177. url.vt = VT_BSTR;
  178. V_BSTR(&url) = ::SysAllocString(pszFile);
  179. hr = pArgs->pDOM->load(url, &bSuccess);
  180. VariantClear(&url);
  181. if (FAILED(hr) || bSuccess == VARIANT_FALSE)
  182. {
  183. PrintDOMError(pArgs->pDOM);
  184. }
  185. }
  186. return hr;
  187. }
  188. void PrintUsage()
  189. {
  190. printf("Usage: xmlint [options] filename(s)\n");
  191. printf("Checks well-formedness and validation constraints for one or more XML documents.\n");
  192. printf("File names can contain wild cards for validating multiple files (e.g. \"*.xml\")\n");
  193. printf("Example:\n");
  194. printf("\txmlint *.xml\n\n");
  195. printf("Checks that all files ending with .xml are valid xml files.\n\n");
  196. printf("Options:\n");
  197. printf("-w\tOnly perform well-formedness check (no DTD validation)\n");
  198. printf("-ie4\tRun in IE4 compatibility mode (instead of new DOM mode)\n");
  199. }
  200. int __cdecl main(int argc, char* argv[])
  201. {
  202. int count = 0;
  203. XMLArgs args;
  204. bool fIE4 = false;
  205. bool fValidate = true;
  206. bool fPause = false;
  207. HRESULT hr;
  208. int rc = 0;
  209. CoInitialize(NULL);
  210. for (int i = 1; i < argc; i++)
  211. {
  212. char* pszArg = argv[i];
  213. if (*pszArg == '-')
  214. {
  215. if (strcmp(pszArg,"-ie4") == 0)
  216. {
  217. fIE4 = true;
  218. }
  219. else
  220. {
  221. switch (pszArg[1])
  222. {
  223. case 'w':
  224. fValidate = false;
  225. break;
  226. case 'p':
  227. fPause = true;
  228. break;
  229. default:
  230. PrintUsage();
  231. rc = 1;
  232. goto Error;
  233. }
  234. }
  235. }
  236. else
  237. {
  238. count++;
  239. }
  240. }
  241. if (count == 0)
  242. {
  243. PrintUsage();
  244. rc = 1;
  245. goto Error;
  246. }
  247. if (fIE4)
  248. {
  249. hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
  250. IID_IXMLDocument, (void**)&(args.pIE4));
  251. if (FAILED(hr))
  252. {
  253. printf("Error co-creating IE4 XML Document");
  254. goto Error;
  255. }
  256. }
  257. else
  258. {
  259. hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
  260. IID_IXMLDOMDocument, (void**)&(args.pDOM));
  261. if (FAILED(hr))
  262. {
  263. printf("Error co-creating XML DOM Document");
  264. goto Error;
  265. }
  266. args.pDOM->put_validateOnParse(fValidate ? VARIANT_TRUE : VARIANT_FALSE);
  267. args.pDOM->put_async(VARIANT_FALSE);
  268. }
  269. if (fPause)
  270. {
  271. printf("Press any key to continue...");
  272. getchar();
  273. }
  274. for (i = 1; i < argc; i++)
  275. {
  276. char* pszArg = argv[i];
  277. if (*pszArg != '-')
  278. {
  279. rc += ProcessFiles(pszArg, xmlint, &args);
  280. }
  281. }
  282. Error:
  283. if (args.pDOM) args.pDOM->Release();
  284. if (args.pIE4) args.pIE4->Release();
  285. if (fPause)
  286. {
  287. printf("Press any key to continue...");
  288. getchar();
  289. }
  290. CoUninitialize();
  291. return rc;
  292. }