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.

1259 lines
38 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. msmgen.cpp
  5. Abstract:
  6. Main Function calls for msm generation
  7. Author:
  8. Xiaoyu Wu(xiaoyuw) 01-Aug-2001
  9. --*/
  10. #include "msmgen.h"
  11. #include "util.h"
  12. #include "objbase.h"
  13. #include "initguid.h"
  14. #include "coguid.h"
  15. #include "msidefs.h"
  16. #include <string.h>
  17. #define DEFAULT_MODULE_IDENTIFIER_PREFIX L"Module0"
  18. #define MSMGEN_FROM_MANFILE 0
  19. #define MSMGEN_FROM_MANLIST 1
  20. #define MSMGEN_FROM_MANGROUP 2
  21. extern void MsmToUpper(CBaseStringBuffer &);
  22. //
  23. // global variables
  24. //
  25. CStringBuffer g_sbTemplateFile;
  26. ASSEMBLY_INFO curAsmInfo;
  27. MSM_INFO g_MsmInfo;
  28. //
  29. // function declaration
  30. //
  31. DECLARE_FUNCTION(_file);
  32. DECLARE_FUNCTION(_assemblyIdentity);
  33. DECLARE_FUNCTION(_comClass);
  34. DECLARE_FUNCTION(_typelib);
  35. static MSM_DOMNODE_WORKER s_msm_worker[]={
  36. DEFINE_ATTRIBUTE_MSM_INTERESTED(file),
  37. DEFINE_ATTRIBUTE_MSM_INTERESTED(assemblyIdentity),
  38. DEFINE_ATTRIBUTE_MSM_INTERESTED(comClass),
  39. DEFINE_ATTRIBUTE_MSM_INTERESTED(typelib)
  40. };
  41. void PrintUsage()
  42. {
  43. WCHAR filename[MAX_PATH];
  44. PWSTR exe = NULL;
  45. if (GetModuleFileNameW(NULL, filename, NUMBER_OF(filename)) > 0)
  46. {
  47. exe = wcsrchr(filename, L'\\');
  48. if (exe == NULL)
  49. {
  50. wcscpy(filename, L"msmgen exe ");
  51. exe = filename;
  52. }else
  53. exe ++;
  54. }
  55. else
  56. {
  57. wcscpy(filename, L"msmgen exe ");
  58. exe = filename;
  59. }
  60. fprintf(stderr, "Generate .msm for an assembly\n\n");
  61. fprintf(stderr, "%S manfile manifest_file.manifest [-compid {guid}] [-msmid {guid}] [-msm file.msm] [-template templatefile.msm]\n", exe);
  62. fprintf(stderr, "%S manlist manifest_list.txt [-msmid {guid}] [-msm file.msm] [-template templatefile.msm]\n", exe);
  63. fprintf(stderr, "%S mangroup manifest_group.txt [-template templatefile.msm]\n", exe);
  64. exit(0);
  65. }
  66. VOID ZeroOutCurrentAssemblyInfo()
  67. {
  68. curAsmInfo.m_sbAssemblyPath.Left(0);
  69. curAsmInfo.m_sbManifestFileName.Left(0);
  70. curAsmInfo.m_sbCatalogFileName.Left(0);
  71. curAsmInfo.m_CchAssemblyPath = 0;
  72. curAsmInfo.m_CchManifestFileName = 0;
  73. curAsmInfo.m_CchCatalogFileName = 0;
  74. curAsmInfo.m_sbComponentID.Left(0);
  75. curAsmInfo.m_sbLangID.Left(0);
  76. curAsmInfo.m_sbComponentIdentifier.Left(0);
  77. curAsmInfo.m_fComponentTableSet = FALSE;
  78. }
  79. VOID ZeroOutMsmInfo()
  80. {
  81. g_MsmInfo.m_guidModuleID = GUID_NULL;
  82. g_MsmInfo.m_sbModuleGuidStr.Left(0);
  83. g_MsmInfo.m_hfci = NULL;
  84. g_MsmInfo.m_sbMsmFileName.Left(0);
  85. g_MsmInfo.m_hdb = NULL;
  86. g_MsmInfo.m_sbModuleIdentifier.Left(0);
  87. g_MsmInfo.m_sLanguageID = 0;
  88. g_MsmInfo.m_sbCabinet.Left(0);
  89. //g_MsmInfo.m_sbMsmTemplateFile.Left(0);
  90. }
  91. HRESULT ValidateCurrentMsmInfo()
  92. {
  93. HRESULT hr = S_OK;
  94. INTERNAL_ERROR_CHECK_NTC(g_MsmInfo.m_sbMsmFileName.Cch() != 0);
  95. INTERNAL_ERROR_CHECK_NTC(g_MsmInfo.m_sbMsmTemplateFile.Cch() != 0);
  96. INTERNAL_ERROR_CHECK_NTC(g_MsmInfo.m_guidModuleID != GUID_NULL);
  97. INTERNAL_ERROR_CHECK_NTC(g_MsmInfo.m_sbModuleGuidStr.Cch() != 0);
  98. hr = S_OK;
  99. Exit:
  100. return hr;
  101. }
  102. HRESULT LoadManifestToDOMDocument(IXMLDOMDocument *pDoc)
  103. {
  104. VARIANT vURL;
  105. VARIANT_BOOL vb;
  106. HRESULT hr = S_OK;
  107. BSTR bstr = NULL;
  108. CurrentAssemblyRealign;
  109. IFFALSE_EXIT(curAsmInfo.m_sbAssemblyPath.Win32Append(curAsmInfo.m_sbManifestFileName));
  110. bstr = SysAllocString(curAsmInfo.m_sbAssemblyPath);
  111. IFFAILED_EXIT(pDoc->put_async(VARIANT_FALSE));
  112. // Load xml document from the given URL or file path
  113. VariantInit(&vURL);
  114. vURL.vt = VT_BSTR;
  115. V_BSTR(&vURL) = bstr;
  116. IFFAILED_EXIT(pDoc->load(vURL, &vb));
  117. Exit:
  118. SysFreeString(bstr);
  119. return hr;
  120. }
  121. HRESULT PopulateDOMNode(IXMLDOMNode * node)
  122. {
  123. HRESULT hr = S_OK;
  124. BSTR nodeName = NULL;
  125. DOMNodeType nodetype;
  126. IFFAILED_EXIT(node->get_nodeType(&nodetype));
  127. if(nodetype == NODE_ELEMENT)
  128. {
  129. IFFAILED_EXIT(node->get_nodeName(&nodeName));
  130. for ( DWORD i = 0 ; i < NUMBER_OF(s_msm_worker); i++)
  131. {
  132. if (wcscmp(s_msm_worker[i].pwszNodeName, nodeName) == 0)
  133. {
  134. IFFAILED_EXIT(s_msm_worker[i].pfn(node));
  135. break;
  136. }
  137. }
  138. }
  139. Exit:
  140. SysFreeString(nodeName);
  141. return hr;
  142. }
  143. HRESULT WalkDomTree(IXMLDOMNode * node)
  144. {
  145. HRESULT hr = S_OK;
  146. IXMLDOMNode* pChild = NULL, *pNext = NULL;
  147. IFFAILED_EXIT(PopulateDOMNode(node));
  148. node->get_firstChild(&pChild);
  149. while (pChild)
  150. {
  151. IFFAILED_EXIT(WalkDomTree(pChild));
  152. pChild->get_nextSibling(&pNext);
  153. pChild->Release();
  154. pChild = NULL;
  155. pChild = pNext;
  156. pNext = NULL;
  157. }
  158. Exit:
  159. if (pChild)
  160. pChild->Release();
  161. if(pNext)
  162. pNext->Release();
  163. return hr;
  164. }
  165. HRESULT PopulateAssemblyManifest()
  166. {
  167. HRESULT hr = S_OK;
  168. IXMLDOMDocument *pDoc = NULL;
  169. IXMLDOMNode *pNode = NULL;
  170. IFFAILED_EXIT(CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pDoc));
  171. IFFAILED_EXIT(LoadManifestToDOMDocument(pDoc));
  172. IFFAILED_EXIT(pDoc->QueryInterface(IID_IXMLDOMNode,(void**)&pNode));
  173. IFFAILED_EXIT(WalkDomTree(pNode));
  174. Exit:
  175. SAFE_RELEASE_COMPOINTER(pDoc);
  176. SAFE_RELEASE_COMPOINTER(pNode);
  177. return hr;
  178. }
  179. HRESULT PrepareMergeModuleOutputFileFromScratch()
  180. {
  181. HRESULT hr = S_OK;
  182. LPOLESTR tmpstr = NULL;
  183. PMSIHANDLE hSummaryInfo = NULL;
  184. CurrentAssemblyRealign;
  185. // make sure that msm, template and msm-guid has been set
  186. IFFAILED_EXIT(ValidateCurrentMsmInfo());
  187. //
  188. // set cabinet output filename
  189. //
  190. IFFALSE_EXIT(g_MsmInfo.m_sbCabinet.Win32Assign(g_MsmInfo.m_sbMsmFileName));
  191. IFFALSE_EXIT(g_MsmInfo.m_sbCabinet.Win32RemoveLastPathElement());
  192. IFFALSE_EXIT(g_MsmInfo.m_sbCabinet.Win32EnsureTrailingPathSeparator());
  193. IFFALSE_EXIT(g_MsmInfo.m_sbCabinet.Win32Append(MERGEMODULE_CABINET_FILENAME, NUMBER_OF(MERGEMODULE_CABINET_FILENAME) -1));
  194. IFFAILED_EXIT(InitializeCabinetForWrite());
  195. // open msm as a database
  196. ASSERT_NTC(g_MsmInfo.m_hdb == NULL);
  197. ASSERT_NTC(g_MsmInfo.m_sbMsmTemplateFile.IsEmpty() == FALSE);
  198. IFFALSE_EXIT(CopyFileW(g_MsmInfo.m_sbMsmTemplateFile, g_MsmInfo.m_sbMsmFileName, FALSE));
  199. IFFALSE_EXIT(SetFileAttributesW(g_MsmInfo.m_sbMsmFileName, FILE_ATTRIBUTE_NORMAL));
  200. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiOpenDatabaseW(g_MsmInfo.m_sbMsmFileName, (LPCWSTR)(MSIDBOPEN_DIRECT), &g_MsmInfo.m_hdb));
  201. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiGetSummaryInformation(g_MsmInfo.m_hdb, NULL, 3, &hSummaryInfo));
  202. INTERNAL_ERROR_CHECK_NTC(g_MsmInfo.m_guidModuleID != GUID_NULL);
  203. IFFAILED_EXIT(StringFromCLSID(g_MsmInfo.m_guidModuleID, &tmpstr));
  204. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiSummaryInfoSetProperty(hSummaryInfo, PID_REVNUMBER, VT_LPSTR, 0,0, tmpstr));
  205. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiSummaryInfoSetProperty(hSummaryInfo, PID_PAGECOUNT, VT_I4, 150, 0, 0));
  206. //
  207. // write ModuleSiguature table using version
  208. //
  209. ASSERT_NTC(g_MsmInfo.m_sbModuleIdentifier.Cch() != 0);
  210. IFFAILED_EXIT(ExecuteInsertTableSQL(OPT_MODULESIGNATURE,
  211. NUMBER_OF_PARAM_TO_INSERT_TABLE_MODULESIGNATURE,
  212. MAKE_PCWSTR(g_MsmInfo.m_sbModuleIdentifier),
  213. MAKE_PCWSTR(L"1.0.0.0")));
  214. Exit:
  215. MsiSummaryInfoPersist(hSummaryInfo);
  216. CoTaskMemFree(tmpstr);
  217. return hr;
  218. }
  219. #define MSMGEN_CREATE_MSM_ALWAYS 0x01
  220. #define MSMGEN_ADD_ASSEMBLY_INTO_EXIST_MSM 0x02
  221. HRESULT PutAssemblyIntoMergeModule(DWORD dwFlags)
  222. {
  223. HRESULT hr = S_OK;
  224. PARAMETER_CHECK_NTC((dwFlags == MSMGEN_CREATE_MSM_ALWAYS) || (dwFlags == MSMGEN_ADD_ASSEMBLY_INTO_EXIST_MSM));
  225. ASSERT_NTC(curAsmInfo.m_sbAssemblyPath.Cch() != 0);
  226. ASSERT_NTC(curAsmInfo.m_sbManifestFileName.Cch() != 0);
  227. ASSERT_NTC(curAsmInfo.m_sbCatalogFileName.Cch() != 0);
  228. ASSERT_NTC(curAsmInfo.m_sbComponentID.Cch() != 0);
  229. ASSERT_NTC(g_MsmInfo.m_sbMsmFileName.Cch() != NULL);
  230. // validate global structure of msmInfo and asmInfo
  231. if (dwFlags == MSMGEN_CREATE_MSM_ALWAYS)
  232. {
  233. // delete mam if exist
  234. SetFileAttributesW(g_MsmInfo.m_sbMsmFileName, FILE_ATTRIBUTE_NORMAL);
  235. DeleteFileW(g_MsmInfo.m_sbMsmFileName);
  236. if (GetFileAttributesW(g_MsmInfo.m_sbMsmFileName) != (DWORD) (-1))
  237. {
  238. ReportError("failed to create a new msm. The msm file, %S, could not be removed!", (PCWSTR)g_MsmInfo.m_sbMsmFileName);
  239. SETFAIL_AND_EXIT;
  240. }
  241. else if (::GetLastError() != ERROR_FILE_NOT_FOUND)
  242. {
  243. if (::GetLastError() == ERROR_PATH_NOT_FOUND)
  244. {
  245. CStringBuffer sb;
  246. IFFALSE_EXIT(sb.Win32Assign(g_MsmInfo.m_sbMsmFileName));
  247. IFFALSE_EXIT(sb.Win32RemoveLastPathElement());
  248. IFFALSE_EXIT(FusionpCreateDirectories(sb, sb.Cch()));
  249. goto MsmContinue;
  250. }
  251. ReportError("failed to create a new msm. GetFileAttribute for %S return error other than NOT_FOUND, win32 err code = %d\n", (PCWSTR)g_MsmInfo.m_sbMsmFileName, ::GetLastError());
  252. SETFAIL_AND_EXIT;
  253. }
  254. MsmContinue:
  255. IFFAILED_EXIT(PrepareMergeModuleOutputFileFromScratch());
  256. IFFAILED_EXIT(PopulateAssemblyManifest());
  257. }
  258. else if (dwFlags == MSMGEN_ADD_ASSEMBLY_INTO_EXIST_MSM)
  259. {
  260. if (GetFileAttributesW(g_MsmInfo.m_sbMsmFileName) == (DWORD) (-1))
  261. {
  262. ReportError("failed to add assembly into a msm. The msm file, %S, does not exist!", (PCWSTR)g_MsmInfo.m_sbMsmFileName);
  263. SETFAIL_AND_EXIT;
  264. }
  265. IFFAILED_EXIT(PopulateAssemblyManifest());
  266. }
  267. Exit:
  268. return hr;
  269. }
  270. void Msmgen_TracingFunctionFailure(PWSTR x, PSTR func, DWORD line)
  271. {
  272. PWSTR p = x;
  273. PWSTR q;
  274. WCHAR Callee[256];
  275. while ((p != NULL) && ((*p == L' ') || (*p == L'(')))
  276. p ++;
  277. q = p;
  278. if (p != NULL)
  279. q = wcschr(p , L'(');
  280. if (q != NULL)
  281. {
  282. wcsncpy(Callee, p, q - p);
  283. ReportError("%S called in %s at line %2d failed!", Callee, func, line);
  284. }else
  285. {
  286. ReportError("Function called in %s at line %2d failed!", func, line);
  287. }
  288. return;
  289. }
  290. //
  291. // make msi-specified guid string ready : uppercase and replace "-" with "_"
  292. //
  293. HRESULT GetMsiGUIDStrFromGUID(DWORD dwFlags, GUID & guid, CSmallStringBuffer & str)
  294. {
  295. HRESULT hr = S_OK;
  296. WCHAR tmpbuf[MAX_PATH];
  297. LPOLESTR tmpstr = NULL;
  298. IFFAILED_EXIT(StringFromCLSID(guid, &tmpstr));
  299. wcscpy(tmpbuf, tmpstr);
  300. for (DWORD i=0; i < wcslen(tmpbuf); i++)
  301. {
  302. if (tmpbuf[i] == L'-')
  303. tmpbuf[i] = L'_';
  304. else
  305. tmpbuf[i]= towupper(tmpbuf[i]);
  306. }
  307. if (dwFlags & MSIGUIDSTR_WITH_PREPEND_DOT)
  308. {
  309. tmpbuf[0] = L'.';
  310. IFFALSE_EXIT(str.Win32Assign(tmpbuf, wcslen(tmpbuf) - 1 )); // has prepend "."
  311. }else
  312. IFFALSE_EXIT(str.Win32Assign(tmpbuf + 1 , wcslen(tmpbuf) - 2 )); // get rid of "{" and "}"
  313. Exit:
  314. CoTaskMemFree(tmpstr);
  315. return hr;
  316. }
  317. HRESULT FillMsmForInitialize()
  318. {
  319. HRESULT hr = S_OK;
  320. WCHAR buf[MAX_PATH];
  321. if (GetFileAttributesW(g_MsmInfo.m_sbMsmFileName) != DWORD(-1))
  322. {
  323. SetFileAttributesW(g_MsmInfo.m_sbMsmFileName, FILE_ATTRIBUTE_NORMAL);
  324. DeleteFileW(g_MsmInfo.m_sbMsmFileName);
  325. if (GetFileAttributesW(g_MsmInfo.m_sbMsmFileName) != DWORD(-1))
  326. {
  327. ReportError("the output %s already exist, please rename or delete it.\n");
  328. hr = E_INVALIDARG;
  329. goto Exit;
  330. }
  331. }
  332. //
  333. // set template filename
  334. //
  335. if (g_MsmInfo.m_sbMsmTemplateFile.Cch() == 0)
  336. {
  337. if (FALSE == g_sbTemplateFile.IsEmpty())
  338. {
  339. IFFALSE_EXIT(g_MsmInfo.m_sbMsmTemplateFile.Win32Assign(g_sbTemplateFile));
  340. } else
  341. {
  342. //
  343. // get template file from current directory
  344. //
  345. DWORD dwRet;
  346. dwRet = GetModuleFileNameW(NULL, buf, NUMBER_OF(buf));
  347. if ((dwRet == 0) || (dwRet >= NUMBER_OF(buf)))
  348. SET_HRERR_AND_EXIT(::GetLastError());
  349. IFFALSE_EXIT(g_MsmInfo.m_sbMsmTemplateFile.Win32Assign(buf, wcslen(buf)));
  350. IFFALSE_EXIT(g_MsmInfo.m_sbMsmTemplateFile.Win32ChangePathExtension(L"msm", 3, eErrorIfNoExtension));
  351. }
  352. }
  353. // make sure that the template file must exist!
  354. if (::GetFileAttributesW(g_MsmInfo.m_sbMsmTemplateFile) == (DWORD) -1)
  355. {
  356. fprintf(stderr, "the specified Msm TemplateFile %S does not exist!\n", g_MsmInfo.m_sbMsmTemplateFile);
  357. SET_HRERR_AND_EXIT(::GetLastError());
  358. }
  359. // set msm ID
  360. if (g_MsmInfo.m_guidModuleID == GUID_NULL)
  361. {
  362. IFFAILED_EXIT(::CoCreateGuid(&g_MsmInfo.m_guidModuleID));
  363. }
  364. IFFAILED_EXIT(GetMsiGUIDStrFromGUID(MSIGUIDSTR_WITH_PREPEND_DOT, g_MsmInfo.m_guidModuleID, g_MsmInfo.m_sbModuleGuidStr));
  365. // unset until we get textual assembly identity
  366. IFFALSE_EXIT(g_MsmInfo.m_sbModuleIdentifier.Win32Assign(L"_", 1)); //make sure that ModuleID does not start with a "_"
  367. IFFALSE_EXIT(g_MsmInfo.m_sbModuleIdentifier.Win32Append(g_MsmInfo.m_sbModuleGuidStr + 1, g_MsmInfo.m_sbModuleGuidStr.Cch() -1));
  368. hr= S_OK;
  369. Exit:
  370. return hr;
  371. }
  372. #define FILE_EXTENSION_MSM L"msm"
  373. #define FILE_EXTENSION_MSM_CCH 3
  374. using namespace std;
  375. #include <string>
  376. HRESULT InitializeMsmA(string & strManFile, string & strMsmFile, string & strMsmID, string & strTemplateFile)
  377. {
  378. HRESULT hr = S_OK;
  379. LPOLESTR tmpstr = NULL;
  380. PARAMETER_CHECK_NTC(!strManFile.empty());
  381. ZeroOutMsmInfo(); // void function
  382. //
  383. // set output msm filename
  384. //
  385. if (strMsmFile.empty())
  386. {
  387. IFFALSE_EXIT(g_MsmInfo.m_sbMsmFileName.Win32Assign(strManFile.c_str(), strManFile.length()));
  388. IFFALSE_EXIT(g_MsmInfo.m_sbMsmFileName.Win32ChangePathExtension(FILE_EXTENSION_MSM, FILE_EXTENSION_MSM_CCH, eErrorIfNoExtension));
  389. }
  390. else
  391. {
  392. IFFALSE_EXIT(g_MsmInfo.m_sbMsmFileName.Win32Assign(strMsmFile.c_str(), strMsmFile.length()));
  393. }
  394. //
  395. // set template filename
  396. //
  397. if (!strTemplateFile.empty())
  398. {
  399. IFFALSE_EXIT(g_MsmInfo.m_sbMsmTemplateFile.Win32Assign(strTemplateFile.c_str(), strTemplateFile.length()));
  400. }
  401. // set msm ID
  402. g_MsmInfo.m_guidModuleID = GUID_NULL;
  403. if (!strMsmID.empty())
  404. {
  405. //
  406. // get ModuleID from msm and save it into the global structure
  407. //
  408. CStringBuffer sb;
  409. IFFALSE_EXIT(sb.Win32Assign(strMsmID.c_str(), strMsmID.length()));
  410. IFFAILED_EXIT(CLSIDFromString(LPOLESTR(PCWSTR(sb)), &g_MsmInfo.m_guidModuleID));
  411. }
  412. IFFAILED_EXIT(FillMsmForInitialize());
  413. hr = S_OK;
  414. Exit:
  415. CoTaskMemFree(tmpstr);
  416. return hr;
  417. }
  418. HRESULT InitializeMsmW(PCWSTR pszManFile, PCWSTR pszMsmFile, PCWSTR pszMsmID, PCWSTR pszTemplateFile)
  419. {
  420. HRESULT hr = S_OK;
  421. PMSIHANDLE hSummaryInfo = NULL;\
  422. PARAMETER_CHECK_NTC(pszManFile != NULL);
  423. ZeroOutMsmInfo(); // void function
  424. //
  425. // set output msm filename
  426. //
  427. if (pszMsmFile == NULL)
  428. {
  429. IFFALSE_EXIT(g_MsmInfo.m_sbMsmFileName.Win32Assign(pszManFile, wcslen(pszManFile)));
  430. IFFALSE_EXIT(g_MsmInfo.m_sbMsmFileName.Win32ChangePathExtension(FILE_EXTENSION_MSM, FILE_EXTENSION_MSM_CCH, eErrorIfNoExtension));
  431. }
  432. else
  433. {
  434. IFFALSE_EXIT(g_MsmInfo.m_sbMsmFileName.Win32Assign(pszMsmFile, wcslen(pszMsmFile)));
  435. }
  436. //
  437. // set template filename
  438. //
  439. if (pszTemplateFile != NULL)
  440. {
  441. IFFALSE_EXIT(g_MsmInfo.m_sbMsmTemplateFile.Win32Assign(pszTemplateFile, wcslen(pszTemplateFile)));
  442. }
  443. // set msm ID
  444. g_MsmInfo.m_guidModuleID = GUID_NULL;
  445. if (pszMsmID != NULL)
  446. {
  447. //
  448. // get ModuleID from msm and save it into the global structure
  449. //
  450. IFFAILED_EXIT(CLSIDFromString(LPOLESTR(pszMsmID), &g_MsmInfo.m_guidModuleID));
  451. }
  452. IFFAILED_EXIT(FillMsmForInitialize());
  453. hr = S_OK;
  454. Exit:
  455. return hr;
  456. }
  457. HRESULT GetInfoMsmgenCommandLineParameters(const DWORD dwGenFlag, wchar_t ** Options, DWORD NumOptions, PWSTR * pszComponentID, PWSTR * pszMsmFile, PWSTR * pszMsmID, PWSTR * pszTemplateFile)
  458. {
  459. HRESULT hr = S_OK;
  460. DWORD i = 0;
  461. PARAMETER_CHECK_NTC((dwGenFlag == MSMGEN_FROM_MANFILE) || (dwGenFlag == MSMGEN_FROM_MANLIST));
  462. PARAMETER_CHECK_NTC(NumOptions % 2 == 0);
  463. *pszComponentID = NULL;
  464. *pszMsmFile = NULL;
  465. *pszMsmID = NULL;
  466. *pszTemplateFile = NULL;
  467. while ( i < NumOptions)
  468. {
  469. if (Options[i][0] != L'-') // must begin with "-"
  470. goto InvalidOption;
  471. if (_wcsicmp(Options[i], L"-msm") == 0 )
  472. {
  473. if (*pszMsmFile != NULL)
  474. {
  475. ReportError("output msm is specified more than once\n");
  476. goto InvalidOption;
  477. } else
  478. {
  479. *pszMsmFile = Options[i + 1];
  480. }
  481. }
  482. else if (_wcsicmp(Options[i], L"-template") == 0 )
  483. {
  484. if (*pszTemplateFile != NULL)
  485. {
  486. ReportError("TemplateFile is specified more than once\n");
  487. goto InvalidOption;
  488. } else
  489. {
  490. *pszTemplateFile = Options[i + 1];
  491. }
  492. }
  493. else if (_wcsicmp(Options[i], L"-compid") == 0 )
  494. {
  495. if (dwGenFlag == MSMGEN_FROM_MANLIST)
  496. {
  497. ReportError("ComponentID should not be specified for manlist\n");
  498. goto InvalidOption;
  499. }
  500. if (*pszComponentID != NULL)
  501. {
  502. ReportError("ComponentID is specified more than once\n");
  503. goto InvalidOption;
  504. }
  505. else
  506. {
  507. *pszComponentID = Options[i + 1];
  508. }
  509. }
  510. else if (_wcsicmp(Options[i], L"-msmid") == 0 )
  511. {
  512. if (*pszMsmID != NULL)
  513. {
  514. ReportError("msmid is specified more than once\n");
  515. goto InvalidOption;
  516. } else
  517. {
  518. *pszMsmID = Options[i + 1];
  519. }
  520. }
  521. else
  522. goto InvalidOption;
  523. i++; // skip the option
  524. i++; // skip the value of the option
  525. }
  526. hr = S_OK;
  527. goto Exit;
  528. InvalidOption:
  529. PrintUsage();
  530. hr = E_INVALIDARG;
  531. Exit:
  532. return hr;
  533. }
  534. HRESULT InitializeAsmInfoW(PCWSTR pszManifestFile, PCWSTR pszComponent)
  535. {
  536. HRESULT hr = S_OK;
  537. WCHAR tmp[MAX_PATH];
  538. UINT iRet;
  539. LPOLESTR tmpstr = NULL;
  540. PWSTR p = NULL;
  541. PARAMETER_CHECK_NTC(pszManifestFile != NULL);
  542. // initialize the global structure of current assembly info
  543. ZeroOutCurrentAssemblyInfo();
  544. //
  545. // set manifest, catalog and AssemblyPath,
  546. //
  547. // the manifest does not exist
  548. if (::GetFileAttributesW(pszManifestFile) == DWORD (-1))
  549. {
  550. ReportError("the manifest file, %S, does not exist, try with manifest file's fullpath!\n", pszManifestFile);
  551. SETFAIL_AND_EXIT;
  552. }
  553. iRet = ::GetFullPathNameW(pszManifestFile, NUMBER_OF(tmp), tmp, NULL);
  554. if ((iRet == 0 ) || (iRet > NUMBER_OF(tmp)))
  555. {
  556. ReportError("Get the fullpath of manifest file, %S, failed with LastError=%d!\n", pszManifestFile, ::GetLastError());
  557. SET_HRERR_AND_EXIT(::GetLastError());
  558. }
  559. IFFALSE_EXIT(curAsmInfo.m_sbAssemblyPath.Win32Assign(tmp, wcslen(tmp)));
  560. IFFALSE_EXIT(curAsmInfo.m_sbAssemblyPath.Win32GetLastPathElement(curAsmInfo.m_sbManifestFileName));
  561. IFFALSE_EXIT(curAsmInfo.m_sbAssemblyPath.Win32RemoveLastPathElement());
  562. IFFALSE_EXIT(curAsmInfo.m_sbAssemblyPath.Win32EnsureTrailingPathSeparator()); // Path with a trailing slash is always ready to use
  563. curAsmInfo.m_CchAssemblyPath = curAsmInfo.m_sbAssemblyPath.GetCchAsDWORD();
  564. curAsmInfo.m_CchManifestFileName = curAsmInfo.m_sbManifestFileName.GetCchAsDWORD();
  565. IFFALSE_EXIT(curAsmInfo.m_sbCatalogFileName.Win32Assign(curAsmInfo.m_sbManifestFileName));
  566. IFFALSE_EXIT(curAsmInfo.m_sbCatalogFileName.Win32ChangePathExtension(CATALOG_FILE_EXT, NUMBER_OF(CATALOG_FILE_EXT) -1, eAddIfNoExtension));
  567. IFFALSE_EXIT(curAsmInfo.m_sbAssemblyPath.Win32Append(curAsmInfo.m_sbCatalogFileName));
  568. if (::GetFileAttributesW(curAsmInfo.m_sbAssemblyPath) == DWORD (-1))
  569. {
  570. ReportError("The catalog file, %S, does not exist!", (PCWSTR)curAsmInfo.m_sbAssemblyPath);
  571. SETFAIL_AND_EXIT;
  572. }
  573. curAsmInfo.m_CchCatalogFileName = curAsmInfo.m_sbCatalogFileName.GetCchAsDWORD();
  574. //
  575. // reset
  576. //
  577. curAsmInfo.m_sbAssemblyPath.Left(curAsmInfo.m_CchAssemblyPath);
  578. curAsmInfo.m_sbManifestFileName.Left(curAsmInfo.m_CchManifestFileName);
  579. //
  580. // set componentID
  581. //
  582. if (pszComponent == NULL)
  583. {
  584. GUID tmpguid;
  585. IFFAILED_EXIT(::CoCreateGuid(&tmpguid));
  586. IFFAILED_EXIT(StringFromCLSID(tmpguid, &tmpstr));
  587. IFFALSE_EXIT(curAsmInfo.m_sbComponentID.Win32Assign(tmpstr, wcslen(tmpstr)));
  588. }
  589. else
  590. {
  591. IFFALSE_EXIT(curAsmInfo.m_sbComponentID.Win32Assign(pszComponent, wcslen(pszComponent)));
  592. }
  593. MsmToUpper(curAsmInfo.m_sbComponentID);
  594. Exit:
  595. CoTaskMemFree(tmpstr);
  596. return hr;
  597. }
  598. HRESULT InitializeAsmInfoA(const string & strManifestFile, const string & strComponent)
  599. {
  600. WCHAR wstrManifestFile[MAX_PATH];
  601. WCHAR wstrComponentID[64];
  602. HRESULT hr = S_OK;
  603. PARAMETER_CHECK_NTC(!strManifestFile.empty());
  604. if (0 == MultiByteToWideChar(CP_ACP, 0, strManifestFile.c_str(), strManifestFile.length(), wstrManifestFile, NUMBER_OF(wstrManifestFile)))
  605. {
  606. ReportError("convert %s to wstr failed!", strManifestFile.c_str());
  607. SETFAIL_AND_EXIT;
  608. }
  609. wstrManifestFile[strManifestFile.length()] = L'\0';
  610. if (!strComponent.empty())
  611. {
  612. if (0 == MultiByteToWideChar(CP_ACP, 0, strComponent.c_str(), strComponent.length(), wstrComponentID, NUMBER_OF(wstrComponentID)))
  613. {
  614. ReportError("convert %s to wstr failed!", strComponent.c_str());
  615. SETFAIL_AND_EXIT;
  616. }
  617. wstrComponentID[strComponent.length()] = L'\0';
  618. }
  619. IFFAILED_EXIT(InitializeAsmInfoW(wstrManifestFile, strComponent.empty() ? NULL : wstrComponentID));
  620. Exit:
  621. return hr;
  622. }
  623. void CleanupMsm()
  624. {
  625. if ( g_MsmInfo.m_hfci != NULL)
  626. {
  627. FCIDestroy(g_MsmInfo.m_hfci);
  628. g_MsmInfo.m_hfci = NULL;
  629. }
  630. if ( g_MsmInfo.m_hdb!= NULL){
  631. MsiDatabaseCommit(g_MsmInfo.m_hdb);
  632. MsiCloseHandle(g_MsmInfo.m_hdb);
  633. g_MsmInfo.m_hdb = NULL;
  634. }
  635. return;
  636. }
  637. HRESULT FinalizedMsm()
  638. {
  639. HRESULT hr = S_OK;
  640. IFFAILED_EXIT(CloseCabinet());
  641. IFFAILED_EXIT(InsertCabinetIntoMsm());
  642. Exit:
  643. DeleteFileW(g_MsmInfo.m_sbCabinet);
  644. CleanupMsm();
  645. return hr;
  646. }
  647. HRESULT CreateMsmForSingleManifest(PCWSTR pszManifestFile, PCWSTR pszComponent)
  648. {
  649. HRESULT hr = S_OK;
  650. PARAMETER_CHECK_NTC(pszManifestFile != NULL);
  651. IFFAILED_EXIT(InitializeAsmInfoW(pszManifestFile, pszComponent));
  652. IFFAILED_EXIT(PutAssemblyIntoMergeModule(MSMGEN_CREATE_MSM_ALWAYS));
  653. IFFAILED_EXIT(FinalizedMsm());
  654. Exit:
  655. return hr;
  656. }
  657. #include <fstream>
  658. #if defined(_WIN64)
  659. #pragma warning(disable: 4244)
  660. #endif
  661. #include <strstream>
  662. #if defined(_WIN64)
  663. #pragma warning(default: 4244)
  664. #endif
  665. void MsmTrimString(string & str)
  666. {
  667. if (!str.empty())
  668. {
  669. string::size_type x = str.find_first_not_of(' ');
  670. if (x != 0)
  671. str.erase(0, x);
  672. if (!str.empty())
  673. {
  674. x = str.find_last_not_of(' ');
  675. if (x != str.length() - 1)
  676. str.erase(x + 1, str.length() - 1 - x);
  677. }
  678. }
  679. return;
  680. }
  681. HRESULT CreateMsmForManifestList(PCWSTR pwszManListFile)
  682. {
  683. HRESULT hr = S_OK;
  684. char pszManListFile[MAX_PATH];
  685. int iBufSize;
  686. string strline;
  687. string strManifestFilename;
  688. string strComponentID;
  689. DWORD numLine = 0;
  690. ifstream manlist;
  691. PARAMETER_CHECK_NTC(pwszManListFile != NULL);
  692. iBufSize = WideCharToMultiByte(CP_ACP, 0, pwszManListFile, wcslen(pwszManListFile), NULL, 0, NULL, NULL);
  693. if (iBufSize > NUMBER_OF(pszManListFile))
  694. {
  695. ReportError("the manlist filename, %S, is longer than MAX_PATH\n", pwszManListFile);
  696. SETFAIL_AND_EXIT;
  697. }
  698. if (0 == WideCharToMultiByte(CP_ACP, 0, pwszManListFile, wcslen(pwszManListFile), pszManListFile, NUMBER_OF(pszManListFile), NULL, NULL))
  699. {
  700. ReportError("the manlist filename, %S, failed to convert to ansi string\n", pwszManListFile);
  701. SETFAIL_AND_EXIT;
  702. }
  703. pszManListFile[wcslen(pwszManListFile)] = '\0';
  704. manlist.open(pszManListFile);
  705. if (manlist.fail())
  706. {
  707. ReportError("the manlist, %S, now as %s, can not be opened\n", pwszManListFile, pszManListFile);
  708. SETFAIL_AND_EXIT;
  709. }
  710. for(; !manlist.eof(); )
  711. {
  712. getline(manlist, strline);
  713. if (strline.empty())
  714. break;
  715. numLine ++;
  716. // extract manifest filename[required] and componentID[optional] and its default value could be empty or "default"
  717. istrstream iline(strline.c_str());
  718. getline(iline, strManifestFilename, ',');
  719. getline(iline, strComponentID);
  720. MsmTrimString(strManifestFilename);
  721. MsmTrimString(strComponentID);
  722. if (strManifestFilename.empty() == TRUE)
  723. {
  724. ReportError("no manifest is specified on line %d in manlist file %S \n", numLine, pwszManListFile);
  725. SETFAIL_AND_EXIT;
  726. }
  727. IFFAILED_EXIT(InitializeAsmInfoA(strManifestFilename, strComponentID));
  728. if (numLine == 1)
  729. {
  730. IFFAILED_EXIT(PutAssemblyIntoMergeModule(MSMGEN_CREATE_MSM_ALWAYS));
  731. }
  732. else
  733. {
  734. IFFAILED_EXIT(PutAssemblyIntoMergeModule(MSMGEN_ADD_ASSEMBLY_INTO_EXIST_MSM));
  735. }
  736. }
  737. IFFAILED_EXIT(FinalizedMsm());
  738. hr = S_OK;
  739. Exit:
  740. return hr;
  741. }
  742. class ManGroupKey{
  743. public:
  744. string strTag;
  745. string strMsmID;
  746. string strMsmFile;
  747. string strTemplateFile;
  748. string strManifest;
  749. };
  750. class ManGroupValue{
  751. public:
  752. string strComponentID;
  753. };
  754. #include <functional>
  755. bool less<ManGroupKey>::operator()(const ManGroupKey& x, const ManGroupKey& y) const
  756. {
  757. if (x.strTag != y.strTag)
  758. return (x.strTag < y.strTag);
  759. if (x.strMsmID != y.strMsmID)
  760. return (x.strMsmID < y.strMsmID);
  761. if (x.strMsmFile != y.strMsmFile)
  762. return (x.strMsmFile < y.strMsmFile);
  763. if (x.strTemplateFile != y.strTemplateFile)
  764. return (x.strTemplateFile < y.strTemplateFile);
  765. return (x.strManifest < y.strManifest);
  766. }
  767. #include <map>
  768. #include <utility>
  769. HRESULT CreateMsmForManifestGroup(PCWSTR pwszMangroupFile)
  770. {
  771. HRESULT hr = S_OK;
  772. ifstream mangroup;
  773. char pszMangroupFile[MAX_PATH];
  774. ManGroupKey mgKey;
  775. ManGroupValue mgValue;
  776. map<ManGroupKey, ManGroupValue> mapManGroup;
  777. map<ManGroupKey, ManGroupValue>::iterator m1_pIter;
  778. typedef pair <ManGroupKey, ManGroupValue> Mangroup_Entry;
  779. int iBufSize;
  780. DWORD numLine;
  781. string strline;
  782. bool fCurrentInAGroup;
  783. bool fStartFromSratch;
  784. string strCurrentMsmid;
  785. string strCurrentMsmFile;
  786. string strCurrentMsmTemplate;
  787. PARAMETER_CHECK_NTC(pwszMangroupFile != NULL);
  788. iBufSize = WideCharToMultiByte(CP_ACP, 0, pwszMangroupFile, wcslen(pwszMangroupFile), NULL, 0, NULL, NULL);
  789. if (iBufSize > NUMBER_OF(pszMangroupFile))
  790. {
  791. ReportError("the manlist filename, %S, is longer than MAX_PATH\n", pwszMangroupFile);
  792. SETFAIL_AND_EXIT;
  793. }
  794. if (0 == WideCharToMultiByte(CP_ACP, 0, pwszMangroupFile, wcslen(pwszMangroupFile), pszMangroupFile, NUMBER_OF(pszMangroupFile), NULL, NULL))
  795. {
  796. ReportError("the manlist filename, %S, failed to convert to ansi string\n", pwszMangroupFile);
  797. SETFAIL_AND_EXIT;
  798. }
  799. pszMangroupFile[wcslen(pwszMangroupFile)] = '\0';
  800. mangroup.open(pszMangroupFile);
  801. if (mangroup.fail())
  802. {
  803. ReportError("the mangroupfile, %S, now as %s, can not be opened\n", pwszMangroupFile, pszMangroupFile);
  804. SETFAIL_AND_EXIT;
  805. }
  806. numLine = 0;
  807. //
  808. // firstly read the file into a map which is sorted during insert
  809. //
  810. for(; !mangroup.eof(); )
  811. {
  812. getline(mangroup, strline);
  813. if (strline.empty())
  814. continue;
  815. istrstream iline(strline.c_str());
  816. if (iline.str() == NULL)
  817. break;
  818. numLine ++;
  819. // clean the key strings
  820. mgKey.strTag.erase();
  821. mgKey.strMsmID.erase();
  822. mgKey.strManifest.erase();
  823. mgKey.strMsmFile.erase();
  824. mgKey.strTemplateFile.erase();
  825. mgValue.strComponentID.erase();
  826. getline(iline, mgKey.strTag, ',');
  827. getline(iline, mgKey.strMsmID, ',');
  828. getline(iline, mgKey.strMsmFile, ',');
  829. getline(iline, mgKey.strManifest, ',');
  830. getline(iline, mgValue.strComponentID, ',');
  831. getline(iline, mgKey.strTemplateFile, ',');
  832. MsmTrimString(mgKey.strTag);
  833. MsmTrimString(mgKey.strMsmID);
  834. MsmTrimString(mgKey.strManifest);
  835. MsmTrimString(mgKey.strMsmFile);
  836. MsmTrimString(mgValue.strComponentID);
  837. MsmTrimString(mgKey.strTemplateFile);
  838. if (mgKey.strTag.empty())
  839. {
  840. ReportError("error on line %d in mangroup file %S, also is %s: Tag or MsmID is empty\n", numLine, pwszMangroupFile, pszMangroupFile);
  841. SETFAIL_AND_EXIT;
  842. }
  843. if (mgKey.strManifest.empty())
  844. {
  845. ReportError("error on line %d in mangroup file %S, also is %s: manifest file is empty\n", numLine, pwszMangroupFile, pszMangroupFile);
  846. SETFAIL_AND_EXIT;
  847. }
  848. if ((mgKey.strTag.compare("0") != 0) && (mgKey.strTag.compare("1") != 0))
  849. {
  850. ReportError("error on line %d in mangroup file %S, also is %s: tag must be 0 or 1\n", numLine, pwszMangroupFile, pszMangroupFile);
  851. SETFAIL_AND_EXIT;
  852. }
  853. if (mgKey.strTag.compare("1") == 0)
  854. {
  855. //
  856. // in this case, msmid and msmfile must be specified
  857. //
  858. if ((mgKey.strMsmFile.empty()) || (mgKey.strMsmID.empty()))
  859. {
  860. ReportError("if the first column is set to be \"1\", output msm file and msmid must be specified in the mangroup file!\n");
  861. SETFAIL_AND_EXIT;
  862. }
  863. }
  864. mapManGroup.insert(Mangroup_Entry(mgKey, mgValue));
  865. }
  866. fCurrentInAGroup = false;
  867. fStartFromSratch = true;
  868. for ( m1_pIter = mapManGroup.begin( ); m1_pIter != mapManGroup.end( ); m1_pIter++ )
  869. {
  870. mgKey = m1_pIter->first;
  871. mgValue = m1_pIter->second;
  872. if (mgKey.strTag.compare("1") == 0)
  873. {
  874. if (fCurrentInAGroup == false)
  875. {
  876. fStartFromSratch = true;
  877. fCurrentInAGroup = true;
  878. strCurrentMsmid = mgKey.strMsmID;
  879. strCurrentMsmFile = mgKey.strMsmFile;
  880. strCurrentMsmTemplate = mgKey.strTemplateFile;
  881. }else
  882. {
  883. if (strCurrentMsmid != mgKey.strMsmID)
  884. {
  885. IFFAILED_EXIT(FinalizedMsm());
  886. fStartFromSratch = true;
  887. fCurrentInAGroup = true;
  888. strCurrentMsmid = mgKey.strMsmID;
  889. strCurrentMsmFile = mgKey.strMsmFile;
  890. strCurrentMsmTemplate = mgKey.strTemplateFile;
  891. } else
  892. {
  893. // they must share the same msmID and msmfile
  894. if (!mgKey.strMsmFile.empty())
  895. {
  896. if (mgKey.strMsmFile != strCurrentMsmFile)
  897. {
  898. ReportError("must share the same msm output file\n");
  899. SETFAIL_AND_EXIT;
  900. }
  901. }
  902. if (!mgKey.strTemplateFile.empty())
  903. {
  904. if (mgKey.strTemplateFile != strCurrentMsmTemplate)
  905. {
  906. ReportError("must use the same msm templatefile\n");
  907. SETFAIL_AND_EXIT;
  908. }
  909. }
  910. }
  911. }
  912. } else if (mgKey.strTag == "0")
  913. {
  914. if (fCurrentInAGroup == true)
  915. {
  916. // close current manifest group
  917. IFFAILED_EXIT(FinalizedMsm());
  918. }
  919. fStartFromSratch = true;
  920. fCurrentInAGroup = false;
  921. }
  922. else
  923. {
  924. // impossible case
  925. ReportError("tag is neither 0 nor 1\n");
  926. SETFAIL_AND_EXIT;
  927. }
  928. if (fStartFromSratch)
  929. {
  930. IFFAILED_EXIT(InitializeMsmA(mgKey.strManifest, mgKey.strMsmFile, mgKey.strMsmID, mgKey.strTemplateFile));
  931. IFFAILED_EXIT(InitializeAsmInfoA(mgKey.strManifest, mgValue.strComponentID));
  932. IFFAILED_EXIT(PutAssemblyIntoMergeModule(MSMGEN_CREATE_MSM_ALWAYS));
  933. }
  934. else
  935. {
  936. ASSERT_NTC(fCurrentInAGroup == true);
  937. if (fCurrentInAGroup)
  938. {
  939. IFFAILED_EXIT(InitializeAsmInfoA(mgKey.strManifest, mgValue.strComponentID));
  940. IFFAILED_EXIT(PutAssemblyIntoMergeModule(MSMGEN_ADD_ASSEMBLY_INTO_EXIST_MSM));
  941. }
  942. }
  943. // for single generation
  944. if (fCurrentInAGroup == false)
  945. {
  946. ASSERT_NTC(fStartFromSratch == true);
  947. IFFAILED_EXIT(FinalizedMsm());
  948. }
  949. fStartFromSratch = false;
  950. }
  951. if (fCurrentInAGroup == true)
  952. IFFAILED_EXIT(FinalizedMsm());
  953. Exit:
  954. return hr;
  955. }
  956. extern "C" int __cdecl wmain(int argc, wchar_t** argv)
  957. {
  958. HRESULT hr = S_OK;
  959. PWSTR pszComponentID = NULL, pszMsmFile = NULL, pszMsmID = NULL, pszTemplateFile = NULL;
  960. DWORD dwGenFlag;
  961. if ((argc < 3) || ((argc % 2) != 1))
  962. {
  963. PrintUsage();
  964. hr = E_INVALIDARG;
  965. goto Exit;
  966. }
  967. if (!FusionpInitializeHeap(NULL)){
  968. hr = HRESULT_FROM_WIN32(::GetLastError());
  969. goto Exit;
  970. }
  971. CoInitialize(NULL);
  972. //
  973. // the first parameter must be "manfile" or "manlist" or "mangroup"
  974. //
  975. if (_wcsicmp(argv[1], L"manfile") == 0)
  976. {
  977. dwGenFlag = MSMGEN_FROM_MANFILE;
  978. }
  979. else if (_wcsicmp(argv[1], L"manlist") == 0)
  980. {
  981. dwGenFlag = MSMGEN_FROM_MANLIST;
  982. }
  983. else if (_wcsicmp(argv[1], L"mangroup") == 0)
  984. {
  985. dwGenFlag = dwGenFlag = MSMGEN_FROM_MANGROUP;
  986. if ((argc != 3) && (argc != 5))
  987. {
  988. goto InvalidParam;
  989. }
  990. if (argc == 5)
  991. {
  992. // it must try to specify a template
  993. if (_wcsicmp(argv[3], L"-template") != 0)
  994. {
  995. goto InvalidParam;
  996. }else
  997. {
  998. IFFALSE_EXIT(g_sbTemplateFile.Win32Assign(argv[4], wcslen(argv[4])));
  999. }
  1000. }
  1001. }
  1002. else
  1003. {
  1004. goto InvalidParam;
  1005. }
  1006. //check the existence of the input file
  1007. if ( GetFileAttributesW(argv[2]) == DWORD (-1))
  1008. {
  1009. ReportError("man file does not exist!\n");
  1010. goto InvalidParam;
  1011. }
  1012. else
  1013. {
  1014. if (dwGenFlag == MSMGEN_FROM_MANFILE)
  1015. {
  1016. CStringBuffer manfile;
  1017. CSmallStringBuffer ext;
  1018. IFFALSE_EXIT(manfile.Win32Assign(argv[2], wcslen(argv[2])));
  1019. IFFALSE_EXIT(manfile.Win32GetPathExtension(ext));
  1020. if (ext.Cch() == 0)
  1021. {
  1022. ReportError("Manifest file must has ext as .man or .manifest\n");
  1023. goto InvalidParam;
  1024. }
  1025. }
  1026. }
  1027. if ((dwGenFlag == MSMGEN_FROM_MANFILE) || (dwGenFlag == MSMGEN_FROM_MANLIST))
  1028. {
  1029. //
  1030. // parse and validate parameters
  1031. //
  1032. IFFAILED_EXIT(GetInfoMsmgenCommandLineParameters(dwGenFlag, argv+3, argc-3, &pszComponentID, &pszMsmFile, &pszMsmID, &pszTemplateFile));
  1033. }
  1034. switch(dwGenFlag)
  1035. {
  1036. case MSMGEN_FROM_MANFILE:
  1037. IFFAILED_EXIT(InitializeMsmW(argv[2], pszMsmFile, pszMsmID, pszTemplateFile));
  1038. IFFAILED_EXIT(CreateMsmForSingleManifest(argv[2], pszComponentID));
  1039. break;
  1040. case MSMGEN_FROM_MANLIST:
  1041. if (pszComponentID != NULL)
  1042. {
  1043. ReportError("componentID should not be specified with manlist\n");
  1044. goto InvalidParam;
  1045. }
  1046. IFFAILED_EXIT(InitializeMsmW(argv[2], pszMsmFile, pszMsmID, pszTemplateFile));
  1047. IFFAILED_EXIT(CreateMsmForManifestList(argv[2]));
  1048. break;
  1049. case MSMGEN_FROM_MANGROUP:
  1050. IFFAILED_EXIT(CreateMsmForManifestGroup(argv[2]));
  1051. break;
  1052. }
  1053. hr = S_OK;
  1054. goto Exit;
  1055. InvalidParam:
  1056. PrintUsage();
  1057. hr = E_INVALIDARG;
  1058. Exit:
  1059. CoUninitialize();
  1060. CleanupMsm();
  1061. if (hr == S_OK)
  1062. printf("msm is generated successfully!");
  1063. else
  1064. printf("msm is failed to be generated!");
  1065. return (hr == S_OK) ? 0 : 1;
  1066. }