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.

832 lines
28 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. db.cpp
  5. Abstract:
  6. Database calls for msm generation
  7. Author:
  8. Xiaoyu Wu(xiaoyuw) 01-Aug-2001
  9. --*/
  10. #include "string.h"
  11. #include "msmgen.h"
  12. #include "msidefs.h"
  13. #include "Msiquery.h"
  14. #include "objbase.h"
  15. #include "coguid.h"
  16. #define NUM_OF_ALLOWED_ATTRIBUTE_ASSEMBLYIDENTITY 6
  17. #define NUM_OF_ALLOWED_ATTRIBUTE_COMCLASS 5
  18. #define NUM_OF_ALLOWED_ATTRIBUTE_TYPELIB 3
  19. #define POLICY_TYPE_PREFIX L"win32-policy"
  20. #define POLICY_TYPE_PREFIX NUMBER_OF(POLICY_TYPE_PREFIX) - 1
  21. static PWSTR s_InsertTableSQL[] =
  22. {
  23. L"INSERT INTO Directory (Directory, Directory_Parent, DefaultDir) VALUES (?, ?, ?)",
  24. L"INSERT INTO Component (Component, ComponentId, Directory_, KeyPath, Attributes, Condition) VALUES (?, ?, ?, ?, 0, '')",
  25. L"INSERT INTO File (File, Component_, FileName, Sequence, FileSize, Version, Language, Attributes) VALUES (?, ?, ?, ?, '0', '1.0.0.0', '0', 0)",
  26. L"INSERT INTO MsiAssembly (Component_, Feature_, File_Manifest, File_Application, Attributes) VALUES (?, ?, ?, '', 1)",
  27. L"INSERT INTO MsiAssemblyName (Component_, Name, Value) VALUES (?, ?, ?)",
  28. L"INSERT INTO ModuleSignature (ModuleID, Version, Language) VALUES (?, ?, 0)",
  29. L"INSERT INTO ModuleComponents (Component, ModuleID, Language) VALUES (?, ?, 0)",
  30. L"INSERT INTO Property (Property, Value) VALUES (?, ?)",
  31. L"INSERT INTO ProgId (ProgId, Class_, Description, ProgId_Parent, Icon_, IconIndex) VALUES (?, ?, ?, NULL, NULL, NULL)",
  32. L"INSERT INTO Class (CLSID, Component_, ProgId_Default, Description, Feature_, Context, AppId_, FileTypeMask, Icon_, IconIndex, DefInprocHandler, Argument, Attributes)"
  33. L"VALUES (?, ?, ?, ?, ?, 'InprocServer32', NULL, NULL, NULL, NULL, NULL, NULL, 0)",
  34. L"INSERT INTO TypeLib (LibID, Component_, Version, Feature_, Language, Description, Directory_, Cost)"
  35. L"VALUES (?, ?, ?, ?, 0, NULL, NULL, 0)"
  36. };
  37. HRESULT ExecuteDeleteFromSQL(PCWSTR szTablename, PCWSTR szId, PCWSTR szValue)
  38. {
  39. HRESULT hr = S_OK;
  40. WCHAR pwszSQL[MAX_PATH];
  41. PMSIHANDLE hView = NULL;
  42. swprintf(pwszSQL, L"DELETE FROM `%s` WHERE `%s`='%s'", szTablename, szId, szValue);
  43. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewW(g_MsmInfo.m_hdb, pwszSQL, &hView));
  44. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(hView, NULL));
  45. Exit:
  46. return hr;
  47. }
  48. DWORD g_FileSequenceNumber = 0;
  49. HRESULT ExecuteDropTableSQL(PCWSTR pszTableName)
  50. {
  51. WCHAR pwszSQL[MAX_PATH];
  52. HRESULT hr = S_OK;
  53. PMSIHANDLE hView = NULL;
  54. MSICONDITION con;
  55. con = MsiDatabaseIsTablePersistent(g_MsmInfo.m_hdb, pszTableName);
  56. if (con == MSICONDITION_NONE)
  57. {
  58. hr = S_OK; // the table does not exist in DB, so do not need to drop the table at all
  59. goto Exit;
  60. }
  61. else if (con != MSICONDITION_TRUE)
  62. SETFAIL_AND_EXIT;
  63. //
  64. // drop the table
  65. //
  66. swprintf(pwszSQL, L"DROP TABLE `%s`", pszTableName);
  67. //
  68. // ignore the error for drop table because this table maybe non-exist at all
  69. //
  70. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewW(g_MsmInfo.m_hdb, pwszSQL, &hView));
  71. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(hView, NULL));
  72. Exit:
  73. return hr;
  74. }
  75. HRESULT ExecuteInsertTableSQL(DWORD tableIndex, UINT cRecords, ...)
  76. {
  77. PMSIHANDLE hView;
  78. PMSIHANDLE hRecord = NULL;
  79. PCWSTR pwszRecord = NULL;
  80. va_list ap;
  81. HRESULT hr = S_OK;
  82. PWSTR pwszSQL = NULL;
  83. pwszSQL = s_InsertTableSQL[tableIndex];
  84. //
  85. // create records
  86. //
  87. switch (tableIndex){
  88. case OPT_FILE:
  89. hRecord = ::MsiCreateRecord(cRecords + 1);
  90. break;
  91. case OPT_DIRECTORY:
  92. case OPT_COMPONENT:
  93. case OPT_MSIASSEMBLY:
  94. case OPT_MSIASSEMBLYNAME:
  95. case OPT_MODULESIGNATURE:
  96. case OPT_MODULECOMPONENTS:
  97. case OPT_PROPERTY:
  98. case OPT_PROGID:
  99. case OPT_CLASS:
  100. case OPT_TYPELIB:
  101. hRecord = ::MsiCreateRecord(cRecords);
  102. break;
  103. default:
  104. SETFAIL_AND_EXIT;
  105. }
  106. if (hRecord == NULL)
  107. SETFAIL_AND_EXIT;
  108. //
  109. // get parameters
  110. //
  111. va_start(ap, cRecords);
  112. for (DWORD i=0; i<cRecords; i++)
  113. {
  114. pwszRecord = va_arg(ap, PCWSTR);
  115. if ((tableIndex == OPT_TYPELIB) && (i == 2)) // set version for typelib
  116. {
  117. UINT x = _wtoi(pwszRecord);
  118. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiRecordSetInteger(hRecord, i+1, x));
  119. }
  120. else
  121. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiRecordSetStringW(hRecord, i+1, pwszRecord));
  122. }
  123. //
  124. // for fileTable, add a sequence number here
  125. //
  126. if (tableIndex == OPT_FILE)
  127. {
  128. g_FileSequenceNumber ++;
  129. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiRecordSetInteger(hRecord, cRecords + 1 , g_FileSequenceNumber));
  130. }
  131. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewW(g_MsmInfo.m_hdb, pwszSQL, &hView));
  132. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(hView, hRecord));
  133. Exit:
  134. va_end(ap);
  135. return hr;
  136. }
  137. //
  138. // check a table with a name-value pair of its identifier
  139. //
  140. HRESULT ExecuteQuerySQL(PCWSTR szTableName, PCWSTR szKeyName, PCWSTR szKeyValue, BOOL & fExist, MSIHANDLE * hOutRecord)
  141. {
  142. WCHAR pwszSQL[MAX_PATH];
  143. HRESULT hr = S_OK;
  144. PMSIHANDLE hView = NULL;
  145. MSIHANDLE hRecord;
  146. MSIHANDLE * phRecord = hOutRecord;
  147. if (phRecord == NULL)
  148. phRecord = &hRecord;
  149. fExist = FALSE;
  150. swprintf(pwszSQL, L"SELECT * FROM `%s` WHERE `%s`='%s'", szTableName, szKeyName, szKeyValue);
  151. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewW(g_MsmInfo.m_hdb, pwszSQL, &hView));
  152. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(hView, NULL));
  153. UINT err = ::MsiViewFetch(hView, phRecord);
  154. if ((err == ERROR_NO_MORE_ITEMS) || ((err == ERROR_SUCCESS) && (phRecord == NULL)))
  155. fExist = FALSE;
  156. else if (err != ERROR_SUCCESS)
  157. SET_HRERR_AND_EXIT(err);
  158. else
  159. fExist = TRUE;
  160. Exit:
  161. if (phRecord == &hRecord)
  162. MsiCloseHandle(hRecord);
  163. return hr;
  164. }
  165. HRESULT ExecuteUpdateSQL(PCWSTR szTableName, PCWSTR KeyName, PCWSTR KeyValue, PCWSTR ColumnName, PCWSTR NewValue)
  166. {
  167. WCHAR pwszSQL[MAX_PATH];
  168. HRESULT hr = S_OK;
  169. PMSIHANDLE hView = NULL;
  170. MSIHANDLE * hRecord = NULL;
  171. BOOL fExist = FALSE;
  172. swprintf(pwszSQL, L"UPDATE '%s' SET `%s` = '%s' WHERE '%s'='%s'",
  173. szTableName, ColumnName, NewValue, KeyName, KeyValue);
  174. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewW(g_MsmInfo.m_hdb, pwszSQL, &hView));
  175. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(hView, NULL));
  176. Exit:
  177. return hr;
  178. }
  179. HRESULT GetShortLongFileNamePair(PCWSTR fullpath, SIZE_T cch, CStringBuffer & namepair)
  180. {
  181. WCHAR shortname[MAX_PATH];
  182. HRESULT hr = S_OK;
  183. PWSTR p = NULL;
  184. DWORD ret = GetShortPathNameW(
  185. fullpath,
  186. shortname,
  187. NUMBER_OF(shortname));
  188. if ( ret == 0 )
  189. {
  190. hr = HRESULT_FROM_WIN32(::GetLastError());
  191. goto Exit;
  192. }
  193. if (ret > NUMBER_OF(shortname))
  194. {
  195. hr = ERROR_INSUFFICIENT_BUFFER;
  196. goto Exit;
  197. }
  198. p = wcsrchr(shortname, L'\\');
  199. p ++ ;
  200. IFFALSE_EXIT(namepair.Win32Assign(p, wcslen(p)));
  201. IFFALSE_EXIT(namepair.Win32Append(L"|", 1));
  202. p = wcsrchr(fullpath, L'\\');
  203. p++;
  204. IFFALSE_EXIT(namepair.Win32Append(p, wcslen(p)));
  205. Exit:
  206. return hr;
  207. }
  208. //
  209. // Function:
  210. // - add manifest and catalog into the cabinet
  211. // - add manifest and catalog into FileTable
  212. //
  213. // because this function used ComponentIdentifier, it has to wait until ComponentIdentifier is set
  214. // and it is set to be the name of the assembly
  215. //
  216. HRESULT SetManifestAndCatalog(CStringBuffer & strSystemFolder)
  217. {
  218. HRESULT hr = S_OK;
  219. CStringBuffer sbBakFileName;
  220. CStringBuffer sbNamePair;
  221. CurrentAssemblyRealign;
  222. //
  223. // add manifest into FileTable and Cabinet
  224. //
  225. IFFALSE_EXIT(sbBakFileName.Win32Assign(curAsmInfo.m_sbManifestFileName));
  226. IFFALSE_EXIT(curAsmInfo.m_sbManifestFileName.Win32Append(g_MsmInfo.m_sbModuleGuidStr));
  227. curAsmInfo.m_sbAssemblyPath.Left(curAsmInfo.m_CchAssemblyPath);
  228. IFFALSE_EXIT(curAsmInfo.m_sbAssemblyPath.Win32Append(sbBakFileName));
  229. IFFAILED_EXIT(GetShortLongFileNamePair(curAsmInfo.m_sbAssemblyPath, curAsmInfo.m_sbAssemblyPath.Cch(), sbNamePair));
  230. IFFAILED_EXIT(ExecuteInsertTableSQL(
  231. OPT_FILE,
  232. NUMBER_OF_PARAM_TO_INSERT_TABLE_FILE,
  233. MAKE_PCWSTR(curAsmInfo.m_sbManifestFileName), // sfp.manifest.123434545
  234. MAKE_PCWSTR(curAsmInfo.m_sbComponentIdentifier),
  235. MAKE_PCWSTR(sbNamePair))); // sfp.manifest
  236. // add manifest to the cabinet
  237. IFFAILED_EXIT(AddFileToCabinetW( curAsmInfo.m_sbAssemblyPath, // fullpath : c:\tests\sfp\sfp.manifest
  238. curAsmInfo.m_sbAssemblyPath.Cch(),
  239. curAsmInfo.m_sbManifestFileName, // identifier in FILE : sfp.manifest.1234234234234234
  240. curAsmInfo.m_sbManifestFileName.Cch()));
  241. //
  242. // add catalog into FileTable and Cabinet
  243. //
  244. IFFALSE_EXIT(sbBakFileName.Win32ChangePathExtension(CATALOG_FILE_EXT, NUMBER_OF(CATALOG_FILE_EXT) -1, eAddIfNoExtension));
  245. IFFALSE_EXIT(curAsmInfo.m_sbCatalogFileName.Win32Append(g_MsmInfo.m_sbModuleGuidStr));
  246. curAsmInfo.m_sbAssemblyPath.Left(curAsmInfo.m_CchAssemblyPath);
  247. IFFALSE_EXIT(curAsmInfo.m_sbAssemblyPath.Win32Append(sbBakFileName));
  248. IFFAILED_EXIT(GetShortLongFileNamePair(curAsmInfo.m_sbAssemblyPath, curAsmInfo.m_sbAssemblyPath.Cch(), sbNamePair));
  249. IFFAILED_EXIT(ExecuteInsertTableSQL(
  250. OPT_FILE,
  251. NUMBER_OF_PARAM_TO_INSERT_TABLE_FILE,
  252. MAKE_PCWSTR(curAsmInfo.m_sbCatalogFileName), // sfp.cat.123434345345
  253. MAKE_PCWSTR(curAsmInfo.m_sbComponentIdentifier),
  254. MAKE_PCWSTR(sbNamePair))); // sfp.cat
  255. // add catalog to the cabinet
  256. IFFAILED_EXIT(AddFileToCabinetW(curAsmInfo.m_sbAssemblyPath, // fullpath : c:\tests\sfp\sfp.cat
  257. curAsmInfo.m_sbAssemblyPath.Cch(),
  258. curAsmInfo.m_sbCatalogFileName, //
  259. curAsmInfo.m_sbCatalogFileName.Cch()));
  260. // set directory table
  261. IFFALSE_EXIT(strSystemFolder.Win32Assign(SYSTEM_FOLDER, NUMBER_OF(SYSTEM_FOLDER)-1));
  262. IFFALSE_EXIT(strSystemFolder.Win32Append(g_MsmInfo.m_sbModuleGuidStr));
  263. // insert into Directory Table
  264. IFFAILED_EXIT(ExecuteInsertTableSQL(
  265. OPT_DIRECTORY,
  266. NUMBER_OF_PARAM_TO_INSERT_TABLE_DIRECTORY,
  267. MAKE_PCWSTR(strSystemFolder),
  268. MAKE_PCWSTR(L"TARGETDIR"),
  269. MAKE_PCWSTR(L".:System32")));
  270. Exit:
  271. return hr;
  272. }
  273. HRESULT PropagateXMLDOMNode(IXMLDOMNode* node, ELEMENT_ALLOWED_ATTRIBUTE rgAllowedAttribute[], DWORD num)
  274. {
  275. HRESULT hr = S_OK;
  276. IXMLDOMNamedNodeMap* pattrs = NULL;
  277. IXMLDOMNode* pChild = NULL;
  278. CStringBuffer tmp;
  279. DWORD j;
  280. CurrentAssemblyRealign;
  281. for ( j = 0 ; j < num; j++)
  282. rgAllowedAttribute[j].m_fValued = FALSE;
  283. //
  284. // write MSIAssemblyName table
  285. //
  286. if (SUCCEEDED(node->get_attributes(&pattrs)) && pattrs != NULL)
  287. {
  288. pattrs->nextNode(&pChild);
  289. while (pChild)
  290. {
  291. BSTR name;
  292. pChild->get_nodeName(&name);
  293. for ( j = 0; j < num; j++)
  294. {
  295. if((rgAllowedAttribute[j].m_fValued == FALSE) && (wcscmp(rgAllowedAttribute[j].m_name, name) == 0))
  296. {
  297. VARIANT value;
  298. pChild->get_nodeValue(&value);
  299. if (value.vt != VT_BSTR)
  300. {
  301. hr = E_FAIL;
  302. break;
  303. }
  304. if ( ! rgAllowedAttribute[j].m_value->Win32Assign(V_BSTR(&value), wcslen(V_BSTR(&value))))
  305. hr = HRESULT_FROM_WIN32(::GetLastError());
  306. VariantClear(&value);
  307. if ( !SUCCEEDED(hr))
  308. break;
  309. hr = S_OK;
  310. if (rgAllowedAttribute[j].m_callbackFunc != NULL)
  311. hr = rgAllowedAttribute[j].m_callbackFunc(
  312. rgAllowedAttribute[j].m_name,
  313. *(rgAllowedAttribute[j].m_value));
  314. if ( !SUCCEEDED(hr))
  315. break;
  316. rgAllowedAttribute[j].m_fValued = TRUE;
  317. }
  318. }
  319. //
  320. // cleaning work
  321. //
  322. SysFreeString(name);
  323. pChild->Release();
  324. pChild = NULL;
  325. if (!SUCCEEDED(hr))
  326. {
  327. pattrs->Release();
  328. pattrs = NULL;
  329. goto Exit;
  330. }
  331. pattrs->nextNode(&pChild);
  332. }
  333. pattrs->Release();
  334. pattrs = NULL;
  335. }
  336. Exit:
  337. SAFE_RELEASE_COMPOINTER(pattrs);
  338. SAFE_RELEASE_COMPOINTER(pChild);
  339. return hr;
  340. }
  341. HRESULT MSM_PARSER_DOM_NODE_file(IXMLDOMNode* node)
  342. {
  343. IXMLDOMNamedNodeMap* pattrs = NULL;
  344. IXMLDOMNode* pChild = NULL;
  345. BOOL fFoundFileName = FALSE;
  346. HRESULT hr = S_OK;
  347. CStringBuffer tmpStr;
  348. CStringBuffer ShortLongPair;
  349. DWORD CchFullpathFilename;
  350. CurrentAssemblyRealign;
  351. IFFALSE_EXIT(tmpStr.Win32Assign(curAsmInfo.m_sbAssemblyPath));
  352. //
  353. // get the filename from node
  354. //
  355. if (SUCCEEDED(node->get_attributes(&pattrs)) && pattrs != NULL)
  356. {
  357. pattrs->nextNode(&pChild);
  358. while (pChild)
  359. {
  360. BSTR name = NULL;
  361. pChild->get_nodeName(&name);
  362. if (wcscmp(name, L"name") == 0)
  363. {
  364. VARIANT value;
  365. pChild->get_nodeValue(&value);
  366. if (value.vt != VT_BSTR)
  367. {
  368. VariantClear(&value);
  369. hr = E_FAIL;
  370. break;
  371. }
  372. if ( !curAsmInfo.m_sbAssemblyPath.Win32Append(V_BSTR(&value), wcslen(V_BSTR(&value))))
  373. hr = HRESULT_FROM_WIN32(::GetLastError());
  374. VariantClear(&value);
  375. fFoundFileName = TRUE;
  376. }
  377. ::SysFreeString(name);
  378. pChild->Release();
  379. pChild = NULL;
  380. if (!SUCCEEDED(hr)){
  381. pattrs->Release();
  382. pattrs = NULL;
  383. goto Exit;
  384. }
  385. if ( fFoundFileName )
  386. break;
  387. pattrs->nextNode(&pChild);
  388. }
  389. if (pattrs)
  390. {
  391. pattrs->Release();
  392. pattrs = NULL;
  393. }
  394. }
  395. if ( !fFoundFileName)
  396. SETFAIL_AND_EXIT;
  397. CchFullpathFilename = curAsmInfo.m_sbAssemblyPath.GetCchAsDWORD();
  398. //
  399. // get fully qualified filename
  400. //
  401. IFFAILED_EXIT(GetShortLongFileNamePair(curAsmInfo.m_sbAssemblyPath, curAsmInfo.m_sbAssemblyPath.Cch(), ShortLongPair));
  402. //
  403. // check the existence of the file
  404. //
  405. if ( GetFileAttributesW(curAsmInfo.m_sbAssemblyPath) == DWORD(-1))
  406. {
  407. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  408. goto Exit;
  409. }
  410. //
  411. // get FileIdentifier for this file
  412. //
  413. IFFALSE_EXIT(curAsmInfo.m_sbAssemblyPath.Win32Append(g_MsmInfo.m_sbModuleGuidStr));
  414. //
  415. // add the file to FileTable
  416. //
  417. IFFAILED_EXIT(ExecuteInsertTableSQL(
  418. OPT_FILE,
  419. NUMBER_OF_PARAM_TO_INSERT_TABLE_FILE,
  420. MAKE_PCWSTR(curAsmInfo.m_sbAssemblyPath + curAsmInfo.m_CchAssemblyPath), // a.dll.12223423423423412343
  421. MAKE_PCWSTR(curAsmInfo.m_sbComponentIdentifier),
  422. MAKE_PCWSTR(ShortLongPair))); // a.dll | a.dll
  423. //
  424. // add this file to the cabinet
  425. //
  426. IFFAILED_EXIT(AddFileToCabinetW(
  427. curAsmInfo.m_sbAssemblyPath, CchFullpathFilename,
  428. curAsmInfo.m_sbAssemblyPath + curAsmInfo.m_CchAssemblyPath, curAsmInfo.m_sbAssemblyPath.Cch() - curAsmInfo.m_CchAssemblyPath));
  429. //
  430. // set Component Table with ComponentID, componentIdentifier, keypath:
  431. //
  432. if (curAsmInfo.m_fComponentTableSet == FALSE)
  433. {
  434. CStringBuffer str;
  435. IFFALSE_EXIT(str.Win32Assign(SYSTEM_FOLDER, NUMBER_OF(SYSTEM_FOLDER)-1));
  436. IFFALSE_EXIT(str.Win32Append(g_MsmInfo.m_sbModuleGuidStr));
  437. IFFAILED_EXIT(ExecuteInsertTableSQL(
  438. OPT_COMPONENT,
  439. NUMBER_OF_PARAM_TO_INSERT_TABLE_COMPONENT,
  440. MAKE_PCWSTR(curAsmInfo.m_sbComponentIdentifier),
  441. MAKE_PCWSTR(curAsmInfo.m_sbComponentID),
  442. MAKE_PCWSTR(str),
  443. MAKE_PCWSTR(curAsmInfo.m_sbAssemblyPath + curAsmInfo.m_CchAssemblyPath)));
  444. curAsmInfo.m_fComponentTableSet = TRUE;
  445. }
  446. Exit:
  447. if (pattrs)
  448. pattrs->Release();
  449. if(pChild)
  450. pChild->Release();
  451. return hr;
  452. }
  453. BOOL IsValidAttributes(const ELEMENT_ALLOWED_ATTRIBUTE attribs[], DWORD num)
  454. {
  455. for (DWORD i=0; i< num; i++)
  456. {
  457. if (attribs[i].m_fRequired && ! attribs[i].m_fValued)
  458. {
  459. ::SetLastError(ERROR_INVALID_DATA);
  460. return FALSE;
  461. }
  462. }
  463. return TRUE;
  464. }
  465. HRESULT GetPrimAssemblyName(PCWSTR pwszAssemblyName, PWSTR pwszPrimAssemblyName, DWORD & cch)
  466. {
  467. HRESULT hr = S_OK;
  468. DWORD i = 0, num = wcslen(pwszAssemblyName);
  469. if (cch < num)
  470. {
  471. cch = num;
  472. SET_HRERR_AND_EXIT(ERROR_INSUFFICIENT_BUFFER);
  473. }
  474. wcscpy(pwszPrimAssemblyName, pwszAssemblyName);
  475. while ( i < num)
  476. {
  477. if (pwszPrimAssemblyName[i] == L'-')
  478. {
  479. pwszPrimAssemblyName[i] = L'_';
  480. }
  481. i++;
  482. }
  483. Exit:
  484. return hr;
  485. }
  486. HRESULT MSM_PARSER_DOM_NODE_assemblyIdentity(IXMLDOMNode* node)
  487. {
  488. CStringBuffer strSystemFolder;
  489. //
  490. // we only are interested in the assemblyIdentity of the component, that is,
  491. // <assemblyIdentity .... /> at the head of manifest, ignore <assemblyIdentity ..../> of
  492. // dependency
  493. //
  494. if (curAsmInfo.m_sbComponentIdentifier.IsEmpty() == FALSE)
  495. {
  496. return S_OK;
  497. }
  498. HRESULT hr = S_OK;
  499. BOOL fExist;
  500. static CSmallStringBuffer rg_StringBuffer[NUM_OF_ALLOWED_ATTRIBUTE_ASSEMBLYIDENTITY];
  501. static ELEMENT_ALLOWED_ATTRIBUTE rg_assemblyIdentity_AllowedAttributes[NUM_OF_ALLOWED_ATTRIBUTE_ASSEMBLYIDENTITY] =
  502. {
  503. {L"name", TRUE, NULL, FALSE, &rg_StringBuffer[0]},
  504. {L"language", FALSE, NULL, FALSE, &rg_StringBuffer[1]},
  505. {L"version", TRUE, NULL, FALSE, &rg_StringBuffer[2]},
  506. {L"processorArchitecture", TRUE, NULL, FALSE, &rg_StringBuffer[3]},
  507. {L"publicKeyToken", FALSE, NULL, FALSE, &rg_StringBuffer[4]},
  508. {L"type", TRUE, NULL, FALSE, &rg_StringBuffer[5]}
  509. };
  510. CStringBuffer tmp;
  511. WCHAR tmpbuf[MAX_PATH];
  512. DWORD num = NUMBER_OF(tmpbuf);
  513. CurrentAssemblyRealign;
  514. IFFAILED_EXIT(PropagateXMLDOMNode(node, rg_assemblyIdentity_AllowedAttributes, NUM_OF_ALLOWED_ATTRIBUTE_ASSEMBLYIDENTITY));
  515. IFFALSE_EXIT(IsValidAttributes(rg_assemblyIdentity_AllowedAttributes, NUM_OF_ALLOWED_ATTRIBUTE_ASSEMBLYIDENTITY));
  516. IFFAILED_EXIT(GetPrimAssemblyName(*rg_assemblyIdentity_AllowedAttributes[MSMGEN_ASSEMBLYIDENTTIY_ATTRIBUTE_NAME].m_value, tmpbuf, num));
  517. //
  518. // set componentIdentifier and add entries to table which depends on componentIdentifier
  519. //
  520. IFFALSE_EXIT(curAsmInfo.m_sbComponentIdentifier.Win32Assign(tmpbuf, wcslen(tmpbuf)));
  521. IFFALSE_EXIT(curAsmInfo.m_sbComponentIdentifier.Win32Append(g_MsmInfo.m_sbModuleGuidStr));
  522. //
  523. // insert manifest & catalog into File Table, cabinet,
  524. //
  525. IFFAILED_EXIT(SetManifestAndCatalog(strSystemFolder));
  526. //
  527. // write component table if it is a policy
  528. //
  529. ASSERT_NTC(curAsmInfo.m_fComponentTableSet == FALSE);
  530. if (0 == _wcsnicmp(*(rg_assemblyIdentity_AllowedAttributes[5].m_value),
  531. POLICY_TYPE_PREFIX,
  532. POLICY_TYPE_PREFIX_CCH))
  533. {
  534. IFFAILED_EXIT(ExecuteInsertTableSQL(
  535. OPT_COMPONENT,
  536. NUMBER_OF_PARAM_TO_INSERT_TABLE_COMPONENT,
  537. MAKE_PCWSTR(curAsmInfo.m_sbComponentIdentifier),
  538. MAKE_PCWSTR(curAsmInfo.m_sbComponentID),
  539. MAKE_PCWSTR(strSystemFolder),
  540. MAKE_PCWSTR(NULL)));
  541. curAsmInfo.m_fComponentTableSet = TRUE;
  542. }
  543. //
  544. // write MsiAssemblyName table
  545. //
  546. for (DWORD i = 0; i < NUMBER_OF(rg_assemblyIdentity_AllowedAttributes); i++)
  547. {
  548. if (rg_assemblyIdentity_AllowedAttributes[i].m_fValued)
  549. {
  550. IFFAILED_EXIT(ExecuteInsertTableSQL(OPT_MSIASSEMBLYNAME,
  551. NUMBER_OF_PARAM_TO_INSERT_TABLE_MSIASSEMBLYNAME,
  552. MAKE_PCWSTR(curAsmInfo.m_sbComponentIdentifier),
  553. MAKE_PCWSTR(rg_assemblyIdentity_AllowedAttributes[i].m_name),
  554. MAKE_PCWSTR(*rg_assemblyIdentity_AllowedAttributes[i].m_value)));
  555. }
  556. }
  557. //
  558. // write MsiAssebly Table
  559. //
  560. curAsmInfo.m_sbManifestFileName.Left(curAsmInfo.m_CchManifestFileName);
  561. IFFALSE_EXIT(curAsmInfo.m_sbManifestFileName.Win32Append(g_MsmInfo.m_sbModuleGuidStr));
  562. IFFAILED_EXIT(ExecuteInsertTableSQL(
  563. OPT_MSIASSEMBLY,
  564. NUMBER_OF_PARAM_TO_INSERT_TABLE_MSIASSEMBLY,
  565. MAKE_PCWSTR(curAsmInfo.m_sbComponentIdentifier),
  566. MAKE_PCWSTR(GUID_NULL_IN_STRING),
  567. MAKE_PCWSTR(curAsmInfo.m_sbManifestFileName))); // sfp.manifest.12343454534534534
  568. //
  569. // write ModuleComponent table using version
  570. //
  571. IFFAILED_EXIT(ExecuteQuerySQL(L"ModuleComponents", L"Component", curAsmInfo.m_sbComponentIdentifier, fExist, NULL));
  572. if ( fExist == FALSE)
  573. {
  574. IFFAILED_EXIT(ExecuteInsertTableSQL(OPT_MODULECOMPONENTS,
  575. NUMBER_OF_PARAM_TO_INSERT_TABLE_MODULECOMPONENTS,
  576. MAKE_PCWSTR(curAsmInfo.m_sbComponentIdentifier),
  577. MAKE_PCWSTR(g_MsmInfo.m_sbModuleIdentifier)));
  578. }else
  579. {
  580. // updateRecord
  581. }
  582. Exit:
  583. return hr;
  584. }
  585. void MsmToUpper(CBaseStringBuffer & sb)
  586. {
  587. CStringBufferAccessor sba;
  588. sba.Attach(&sb);
  589. PWSTR str = sba.GetBufferPtr();
  590. for ( int i = 0; i < sb.Cch(); i++)
  591. {
  592. if ((str[i] >= L'a') && (str[i] <= L'z'))
  593. str[i] = (WCHAR)(str[i] + L'A' - L'a');
  594. }
  595. sba.Detach();
  596. return;
  597. }
  598. HRESULT MSM_PARSER_DOM_NODE_comClass(IXMLDOMNode* node)
  599. {
  600. HRESULT hr = S_OK;
  601. // About this array :
  602. // 0, 2 would be stored in class table
  603. // 1 would be stored in progid table
  604. // 3 would be ignored and Typelib Table would be created when "<typelib />" is encounter
  605. // 4 would be ignored
  606. //
  607. static CSmallStringBuffer rg_StringBuffer[NUM_OF_ALLOWED_ATTRIBUTE_COMCLASS];
  608. static ELEMENT_ALLOWED_ATTRIBUTE rg_comClass_AllowedAttributes[NUM_OF_ALLOWED_ATTRIBUTE_COMCLASS] = {
  609. {L"clsid", TRUE, NULL, FALSE, &rg_StringBuffer[0]},
  610. {L"description", FALSE, NULL, FALSE, &rg_StringBuffer[1]},
  611. {L"progid", FALSE, NULL, FALSE, &rg_StringBuffer[2]},
  612. {L"tlbid", FALSE, NULL, FALSE, &rg_StringBuffer[3]},
  613. {L"threadingModel", FALSE, NULL, FALSE, &rg_StringBuffer[4]}
  614. };
  615. CurrentAssemblyRealign;
  616. IFFAILED_EXIT(PropagateXMLDOMNode(node, rg_comClass_AllowedAttributes, NUM_OF_ALLOWED_ATTRIBUTE_COMCLASS));
  617. IFFALSE_EXIT(IsValidAttributes(rg_comClass_AllowedAttributes, NUM_OF_ALLOWED_ATTRIBUTE_COMCLASS));
  618. // convert GUIDID to msi-required guid : all upper-case in the guid string
  619. MsmToUpper(*rg_comClass_AllowedAttributes[MSMGEN_COMCLASS_ATTRIBUTE_CLSID].m_value);
  620. //
  621. // if the progId is not NULL, Insert an entry to ProgID Table
  622. //
  623. if (rg_comClass_AllowedAttributes[MSMGEN_COMCLASS_ATTRIBUTE_PROGID].m_fValued)
  624. {
  625. IFFAILED_EXIT(ExecuteInsertTableSQL(
  626. OPT_PROGID,
  627. NUMBER_OF_PARAM_TO_INSERT_TABLE_PROGID,
  628. MAKE_PCWSTR(*rg_comClass_AllowedAttributes[MSMGEN_COMCLASS_ATTRIBUTE_PROGID].m_value),
  629. MAKE_PCWSTR(*rg_comClass_AllowedAttributes[MSMGEN_COMCLASS_ATTRIBUTE_CLSID].m_value),
  630. MAKE_PCWSTR(*rg_comClass_AllowedAttributes[MSMGEN_COMCLASS_ATTRIBUTE_DESCRIPTION].m_value)));
  631. }
  632. //
  633. // insert one entry to ClassTable
  634. //
  635. IFFAILED_EXIT(ExecuteInsertTableSQL(
  636. OPT_CLASS,
  637. NUMBER_OF_PARAM_TO_INSERT_TABLE_CLASS,
  638. MAKE_PCWSTR(*rg_comClass_AllowedAttributes[MSMGEN_COMCLASS_ATTRIBUTE_CLSID].m_value),
  639. MAKE_PCWSTR(curAsmInfo.m_sbComponentIdentifier),
  640. MAKE_PCWSTR(*rg_comClass_AllowedAttributes[MSMGEN_COMCLASS_ATTRIBUTE_PROGID].m_value),
  641. MAKE_PCWSTR(*rg_comClass_AllowedAttributes[MSMGEN_COMCLASS_ATTRIBUTE_DESCRIPTION].m_value),
  642. MAKE_PCWSTR(GUID_NULL_IN_STRING)));
  643. Exit:
  644. return hr;
  645. }
  646. HRESULT MSM_PARSER_DOM_NODE_typelib(IXMLDOMNode* node)
  647. {
  648. HRESULT hr = S_OK;
  649. //
  650. // all of three attributes are required for "<typelib .... />" element
  651. //
  652. static CSmallStringBuffer rg_StringBuffer[NUM_OF_ALLOWED_ATTRIBUTE_TYPELIB];
  653. static ELEMENT_ALLOWED_ATTRIBUTE rg_typelib_AllowedAttributes[NUM_OF_ALLOWED_ATTRIBUTE_TYPELIB] = {
  654. {L"tlbid", TRUE, NULL, FALSE, &rg_StringBuffer[0]},
  655. {L"version", TRUE, NULL, FALSE, &rg_StringBuffer[1]},
  656. {L"helpdir", TRUE, NULL, FALSE, &rg_StringBuffer[2]}
  657. };
  658. CurrentAssemblyRealign;
  659. IFFAILED_EXIT(PropagateXMLDOMNode(node, rg_typelib_AllowedAttributes, NUM_OF_ALLOWED_ATTRIBUTE_TYPELIB));
  660. IFFALSE_EXIT(IsValidAttributes(rg_typelib_AllowedAttributes, NUM_OF_ALLOWED_ATTRIBUTE_TYPELIB));
  661. MsmToUpper(*rg_typelib_AllowedAttributes[MSMGEN_TYPELIB_ATTRIBUTE_TLBID].m_value);
  662. //
  663. // insert one entry to class table
  664. //
  665. IFFAILED_EXIT(ExecuteInsertTableSQL(
  666. OPT_TYPELIB,
  667. NUMBER_OF_PARAM_TO_INSERT_TABLE_TYPELIB,
  668. MAKE_PCWSTR(*rg_typelib_AllowedAttributes[MSMGEN_TYPELIB_ATTRIBUTE_TLBID].m_value),
  669. MAKE_PCWSTR(curAsmInfo.m_sbComponentIdentifier),
  670. MAKE_PCWSTR(*rg_typelib_AllowedAttributes[MSMGEN_TYPELIB_ATTRIBUTE_VERSION].m_value),
  671. MAKE_PCWSTR(GUID_NULL_IN_STRING)));
  672. Exit:
  673. return hr;
  674. }
  675. HRESULT InsertCabinetIntoMsm()
  676. {
  677. HRESULT hr = S_OK;
  678. PMSIHANDLE hView = NULL;
  679. PMSIHANDLE hRec = NULL;
  680. CurrentAssemblyRealign;
  681. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewA(g_MsmInfo.m_hdb, "INSERT INTO `_Streams` (`Name`, `Data`) VALUES (?, ?)", &hView));
  682. hRec = ::MsiCreateRecord(2);
  683. if (NULL == hRec)
  684. SETFAIL_AND_EXIT;
  685. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiRecordSetStringW(hRec, 1, MERGEMODULE_CABINET_FILENAME));
  686. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiRecordSetStreamW(hRec, 2, g_MsmInfo.m_sbCabinet));
  687. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(hView, hRec));
  688. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewClose(hView));
  689. Exit:
  690. return hr;
  691. }