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.

335 lines
9.6 KiB

  1. // manifestmanlger.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdinc.h"
  4. #include "atlbase.h"
  5. #include "msxml2.h"
  6. #if defined(JAYKRELL_UPDATEDEPENDENTS_BUILD_FIX)
  7. #include "updatedependents.h"
  8. #endif
  9. BOOL g_bIgnoreMalformedXML = FALSE;
  10. #define MAX_OPERATIONS (20)
  11. extern const wstring ASM_NAMESPACE_URI = (L"urn:schemas-microsoft-com:asm.v1");
  12. WCHAR MicrosoftCopyrightLogo[] = L"Microsoft (R) Side-By-Side Manifest Tool 1.1.0.0\nCopyright (C) Microsoft Corporation 2000-2002. All Rights Reserved.\n\n";
  13. //
  14. // Global flags used in processing
  15. //
  16. ::ATL::CComPtr<IClassFactory> g_XmlDomClassFactory;
  17. #define XMLDOMSOURCE_FILE (1)
  18. #define XMLDOMSOURCE_STRING (2)
  19. #define MAX_ARGUMENTS (500)
  20. #define MAX_ARGUMENT_LENGTH (8192)
  21. bool
  22. InitializeMSXML3()
  23. {
  24. static HMODULE hMsXml3 = NULL;
  25. ::ATL::CComPtr<IClassFactory> pFactory;
  26. HRESULT hr;
  27. typedef HRESULT (__stdcall * PFN_DLL_GET_CLASS_OBJECT)(REFCLSID, REFIID, LPVOID*);
  28. PFN_DLL_GET_CLASS_OBJECT pfnGetClassObject = NULL;
  29. if (hMsXml3 == NULL)
  30. {
  31. hMsXml3 = LoadLibraryA("msxml3.dll");
  32. if (hMsXml3 == NULL)
  33. {
  34. wcerr << "Unable to load msxml3, trying msxml2" << endl;
  35. hMsXml3 = LoadLibraryA("msxml2.dll");
  36. if (hMsXml3 == NULL)
  37. {
  38. wcerr << "Unable to load msxml2, trying msxml" << endl;
  39. hMsXml3 = LoadLibraryA("msxml.dll");
  40. }
  41. }
  42. }
  43. if (hMsXml3 == NULL) {
  44. wcerr << "Very Bad Things - no msxml exists on this machine?" << endl;
  45. return false;
  46. }
  47. pfnGetClassObject = (PFN_DLL_GET_CLASS_OBJECT)GetProcAddress(hMsXml3, "DllGetClassObject");
  48. if (!pfnGetClassObject)
  49. {
  50. return false;
  51. }
  52. hr = pfnGetClassObject(__uuidof(MSXML2::DOMDocument30), __uuidof(pFactory), (void**)&pFactory);
  53. if (FAILED(hr))
  54. {
  55. wcerr << "Can't load version 3.0, trying 2.6" << endl;
  56. hr = pfnGetClassObject(__uuidof(MSXML2::DOMDocument26), __uuidof(pFactory), (void**)&pFactory);
  57. if (FAILED(hr))
  58. {
  59. wcerr << "Can't load version 2.6, trying 1.0" << endl;
  60. // from msxml.h, not msxml2.h
  61. // hr = pfnGetClassObject(__uuidof(DOMDocument), __uuidof(pFactory), (void**)&pFactory);
  62. if (FAILED(hr))
  63. {
  64. wcerr << "Poked: no XML v1.0" << endl;
  65. }
  66. }
  67. }
  68. if (FAILED(hr))
  69. {
  70. return false;
  71. }
  72. g_XmlDomClassFactory = pFactory;
  73. return true;
  74. }
  75. HRESULT
  76. ConstructXMLDOMObject(
  77. wstring SourceName,
  78. ISXSManifestPtr &document
  79. )
  80. {
  81. HRESULT hr = S_OK;
  82. VARIANT_BOOL vb;
  83. hr = g_XmlDomClassFactory->CreateInstance(NULL, __uuidof(document), (void**)&document);
  84. if (FAILED(hr))
  85. {
  86. return hr;
  87. }
  88. //
  89. // If they're willing to deal with bad XML, then so be it.
  90. //
  91. if (FAILED(hr = document->put_validateOnParse(VARIANT_FALSE)))
  92. {
  93. wstringstream ss;
  94. ss << wstring(L"MSXMLDOM Refuses to be let the wool be pulled over its eyes!");
  95. ReportError(ErrorSpew, ss);
  96. }
  97. hr = document->put_preserveWhiteSpace(VARIANT_TRUE);
  98. hr = document->put_resolveExternals(VARIANT_FALSE);
  99. CFileStreamBase *fsbase = new CFileStreamBase; // LEAK out of paranoia
  100. ::ATL::CComPtr<IStream> istream = fsbase;
  101. if (!fsbase->OpenForRead(SourceName))
  102. {
  103. wstringstream ss;
  104. ss << wstring(L"Failed opening ") << SourceName << wstring(L" for read.");
  105. ReportError(ErrorFatal, ss);
  106. return E_FAIL;
  107. }
  108. hr = document->load(_variant_t(istream), &vb);
  109. if (vb != VARIANT_TRUE)
  110. {
  111. ::ATL::CComPtr<IXMLDOMParseError> perror;
  112. hr = document->get_parseError(&perror);
  113. long ecode, filepos, linenumber, linepos;
  114. BSTR reason, src;
  115. perror->get_errorCode(&ecode);
  116. perror->get_filepos(&filepos);
  117. perror->get_line(&linenumber);
  118. perror->get_linepos(&linepos);
  119. perror->get_reason(&reason);
  120. perror->get_srcText(&src);
  121. wstringstream ss;
  122. ss << wstring(L"Error: ") << hex << ecode << dec << wstring(L" ") << (char*)_bstr_t(reason)
  123. << wstring(L" at position ") << filepos << wstring(L", line ") << linenumber << wstring(L" column ")
  124. << linepos << endl
  125. << wstring(L" the text was: ") << endl << wstring(_bstr_t(src)) << endl;
  126. ReportError(ErrorFatal, ss);
  127. hr = E_FAIL;
  128. }
  129. fsbase->Close();
  130. return hr;
  131. }
  132. void dispUsage()
  133. {
  134. const WCHAR HelpMessage[] =
  135. L"Modes of operation:\n"
  136. L" -hashupdate Update hashes of member files\n"
  137. L" -makecdfs Generate CDF files to make catalogs\n"
  138. L" -verbose Disply piles of debugging information\n"
  139. L"\n"
  140. L"Modifiers:\n"
  141. L" -manifest <foo.man> The name of the manifest to work with\n"
  142. L"\n"
  143. L"Normal usage:"
  144. L" mt.exe -hashupdate -makecdfs -manifest foo.man\n"
  145. L"\n";
  146. wcout << wstring(HelpMessage);
  147. }
  148. CParameters g_GlobalParameters;
  149. int __cdecl wmain(int argc, WCHAR* argv[])
  150. {
  151. using namespace std;
  152. HRESULT hr;
  153. switch(g_GlobalParameters.SetComandLine(argc, argv))
  154. {
  155. case CParameters::eCommandLine_normal:
  156. wcout << wstring(MicrosoftCopyrightLogo);
  157. break;
  158. case CParameters::eCommandLine_usage:
  159. wcout << wstring(MicrosoftCopyrightLogo);
  160. dispUsage();
  161. return -1;
  162. }
  163. //
  164. // Start COM
  165. //
  166. if (FAILED(hr = ::CoInitialize(NULL)))
  167. {
  168. wstringstream ss;
  169. ss << "Unable to start com, error " << hex << hr;
  170. ReportError(ErrorFatal, ss);
  171. return 1;
  172. }
  173. if (!InitializeMSXML3())
  174. {
  175. return 2;
  176. }
  177. if (g_GlobalParameters.m_fSingleItem)
  178. {
  179. PostbuildEntries.push_back(g_GlobalParameters.m_SinglePostbuildItem);
  180. goto StartProcessing;
  181. }
  182. //
  183. // Populate the processing list, but only if we're really in a Razzle
  184. // environment
  185. //
  186. if (g_GlobalParameters.m_fDuringRazzle)
  187. {
  188. // wstring chName = convertWCharToAnsi(argv[1]);
  189. ifstream BinplaceLog;
  190. BinplaceLog.open(ConvertWString(g_GlobalParameters.m_BinplaceLog).c_str());
  191. if (!BinplaceLog.is_open()) {
  192. wcerr << wstring(L"Failed opening '") << g_GlobalParameters.m_BinplaceLog
  193. << wstring(L"' as the binplace log?") << endl
  194. << wstring(L"Ensure that the path passed by '-binplacelog' is valid.") << endl;
  195. return 1;
  196. }
  197. while (!BinplaceLog.eof())
  198. {
  199. string sourceLine;
  200. wstring wSourceLine;
  201. CPostbuildProcessListEntry item;
  202. StringStringMap ValuePairs;
  203. getline(BinplaceLog, sourceLine);
  204. wSourceLine = ConvertString(sourceLine);
  205. ValuePairs = MapFromDefLine(wSourceLine);
  206. if (!ValuePairs.size())
  207. continue;
  208. item.name = ValuePairs[L"SXS_ASSEMBLY_NAME"];
  209. item.version = ValuePairs[L"SXS_ASSEMBLY_VERSION"];
  210. item.language = ValuePairs[L"SXS_ASSEMBLY_LANGUAGE"];
  211. item.setManifestLocation(g_GlobalParameters.m_AsmsRoot, ValuePairs[L"SXS_MANIFEST"]);
  212. if (item.getManifestFullPath().find(L"asms\\") == -1) {
  213. wstringstream ss;
  214. ss << wstring(L"Skipping manifested item ") << item << wstring(L" because it's not under asms.");
  215. ReportError(ErrorSpew, ss);
  216. } else {
  217. PostbuildEntries.push_back(item);
  218. }
  219. }
  220. std::sort(PostbuildEntries.begin(), PostbuildEntries.end());
  221. PostbuildEntries.resize(std::unique(PostbuildEntries.begin(), PostbuildEntries.end()) - PostbuildEntries.begin());
  222. }
  223. else if (!g_GlobalParameters.m_fSingleItem)
  224. {
  225. //
  226. // No -razzle and no -manifest? Whoops...
  227. //
  228. dispUsage();
  229. return 1;
  230. }
  231. StartProcessing:
  232. if (!g_GlobalParameters.m_fCreateCdfs &&
  233. !g_GlobalParameters.m_fUpdateHash &&
  234. (g_GlobalParameters.m_InjectDependencies.size() == 0) &&
  235. !g_GlobalParameters.m_fCreateNewAssembly)
  236. {
  237. wcout << wstring(L"Nothing to do!") << endl;
  238. dispUsage();
  239. return 1;
  240. }
  241. for (vector<CPostbuildProcessListEntry>::const_iterator cursor = PostbuildEntries.begin(); cursor != PostbuildEntries.end(); cursor++)
  242. {
  243. #if defined(JAYKRELL_UPDATEDEPENDENTS_BUILD_FIX)
  244. //
  245. // If we were supposed to be making this into a new assembly, then do so.
  246. //
  247. if (g_GlobalParameters.m_fCreateNewAssembly)
  248. CreateNewManifest(*cursor, g_GlobalParameters.m_SingleEntry);
  249. #endif
  250. //
  251. // First, mash the hashes around.
  252. //
  253. if (g_GlobalParameters.m_fUpdateHash)
  254. UpdateManifestHashes(*cursor);
  255. //
  256. // Then, inject dependencies
  257. //
  258. if (g_GlobalParameters.m_InjectDependencies.size() != 0)
  259. {
  260. #if defined(JAYKRELL_UPDATEDEPENDENTS_BUILD_FIX)
  261. AddManifestDependencies(*cursor, g_GlobalParameters.m_InjectDependencies);
  262. #endif
  263. }
  264. //
  265. // Second, generate catalogs
  266. //
  267. if (g_GlobalParameters.m_fCreateCdfs)
  268. GenerateCatalogContents(*cursor);
  269. }
  270. hr = S_OK;
  271. return (hr == S_OK) ? 0 : 1;
  272. }
  273. CPostbuildItemVector PostbuildEntries;