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.

285 lines
8.2 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. common.cpp
  5. Abstract:
  6. Common Function calls for msm generation
  7. Author:
  8. Xiaoyu Wu(xiaoyuw) 01-Aug-2001
  9. --*/
  10. #include "msmgen.h"
  11. #include "msidefs.h"
  12. #include "objbase.h"
  13. #include "fusionhandle.h"
  14. #include "coguid.h"
  15. inline BOOL IsDotOrDotDot(PCWSTR str)
  16. {
  17. return ((str[0] == L'.') && ((str[1] == L'\0') || ((str[1] == L'.') && (str[2] == L'\0'))));
  18. }
  19. //
  20. // simple function, check the ext of the filename
  21. //
  22. BOOL IsIDTFile(PCWSTR pwzStr)
  23. {
  24. PWSTR p = wcsrchr(pwzStr, L'.');
  25. if ( p )
  26. {
  27. if ( _wcsicmp(p, IDT_EXT) == 0) // idt files
  28. return TRUE;
  29. }
  30. return FALSE;
  31. }
  32. //
  33. //Function:
  34. //
  35. // get moduleID from the msm file, if not present, generate a new one and write related entried into the Database
  36. //
  37. HRESULT SetModuleID()
  38. {
  39. HRESULT hr = S_OK;
  40. WCHAR tmp[MAX_PATH];
  41. LPOLESTR tmpstr = NULL;
  42. DWORD cch = NUMBER_OF(tmp);
  43. UINT datatype;
  44. PMSIHANDLE hSummaryInfo = NULL;
  45. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiGetSummaryInformation(g_MsmInfo.m_hdb, NULL, 3, &hSummaryInfo));
  46. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiSummaryInfoGetPropertyW(hSummaryInfo, PID_REVNUMBER, &datatype, 0,0, tmp, &cch));
  47. //
  48. // because msm has existed before, it should has a module ID, otherwise, it should generate a new one
  49. //
  50. if (cch == 0)
  51. {
  52. if (IsEqualGUID(g_MsmInfo.m_guidModuleID, GUID_NULL)) //otherwise, user has input a guid
  53. {
  54. IFFAILED_EXIT(::CoCreateGuid(&g_MsmInfo.m_guidModuleID));
  55. }
  56. IFFAILED_EXIT(StringFromCLSID(g_MsmInfo.m_guidModuleID, &tmpstr));
  57. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiSummaryInfoSetProperty(hSummaryInfo, PID_REVNUMBER, VT_LPSTR, 0,0, tmpstr));
  58. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiSummaryInfoSetProperty(hSummaryInfo, PID_PAGECOUNT, VT_I4, 150, 0, 0));
  59. }
  60. else
  61. {
  62. //
  63. // get ModuleID from msm and save it into the global structure
  64. //
  65. IFFAILED_EXIT(CLSIDFromString(LPOLESTR(tmp), &g_MsmInfo.m_guidModuleID));
  66. }
  67. IFFAILED_EXIT(GetMsiGUIDStrFromGUID(MSIGUIDSTR_WITH_PREPEND_DOT, g_MsmInfo.m_guidModuleID, g_MsmInfo.m_sbModuleGuidStr));
  68. Exit:
  69. MsiSummaryInfoPersist(hSummaryInfo);
  70. CoTaskMemFree(tmpstr);
  71. return hr;
  72. }
  73. //
  74. // Purpose:
  75. // make sure the tables we want to use is avaiable, if not, import the tables
  76. // Input Param:
  77. // Fully qulified msm filename
  78. //
  79. HRESULT OpenMsmFileForMsmGen(PCWSTR msmfile)
  80. {
  81. HRESULT hr = S_OK;
  82. BOOL fUsingExistedMsm = FALSE;
  83. if (g_MsmInfo.m_hdb == NULL)
  84. {
  85. if (g_MsmInfo.m_enumGenMode == MSMGEN_OPR_NEW)
  86. {
  87. ASSERT_NTC(g_MsmInfo.m_sbMsmTemplateFile.IsEmpty() == FALSE);
  88. IFFALSE_EXIT(CopyFileW(g_MsmInfo.m_sbMsmTemplateFile, msmfile, FALSE));
  89. IFFALSE_EXIT(SetFileAttributesW(msmfile, FILE_ATTRIBUTE_NORMAL));
  90. } else // get it from the msm file, which must has a moduleID
  91. {
  92. //
  93. // make sure that the file exist
  94. //
  95. if (GetFileAttributesW(msmfile) == (DWORD)-1)
  96. SET_HRERR_AND_EXIT(ERROR_INVALID_PARAMETER);
  97. }
  98. //
  99. // open database for revise
  100. //
  101. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiOpenDatabaseW(msmfile, (LPCWSTR)(MSIDBOPEN_DIRECT), &g_MsmInfo.m_hdb));
  102. }
  103. Exit:
  104. return hr;
  105. }
  106. HRESULT ImportTableIfNonPresent(MSIHANDLE * pdbHandle, PCWSTR sbMsmTablePath, PCWSTR idt)
  107. {
  108. CSmallStringBuffer sbTableName;
  109. HRESULT hr = S_OK;
  110. IFFAILED_EXIT(sbTableName.Win32Assign(idt, wcslen(idt)));
  111. IFFALSE_EXIT(sbTableName.Win32RemoveLastPathElement());
  112. //
  113. // check whether the table exist in the Database
  114. //
  115. MSICONDITION err = MsiDatabaseIsTablePersistent(g_MsmInfo.m_hdb, sbTableName);
  116. if (( err == MSICONDITION_ERROR) || (err == MSICONDITION_FALSE))
  117. {
  118. SETFAIL_AND_EXIT;
  119. }
  120. else if (err == MSICONDITION_NONE) // non-exist
  121. {
  122. //import the table
  123. IFFAILED_EXIT(MsiDatabaseImportW(*pdbHandle, sbMsmTablePath, idt));
  124. }
  125. Exit:
  126. return hr;
  127. }
  128. //
  129. // Fucntion:
  130. // - make sure the msm has all tables msmgen needed
  131. //
  132. HRESULT PrepareMsm()
  133. {
  134. if (g_MsmInfo.m_enumGenMode == MSMGEN_OPR_NEW)
  135. return S_OK;
  136. else
  137. {
  138. HRESULT hr = S_OK;
  139. PMSIHANDLE phdb = NULL;
  140. CStringBuffer sb;
  141. IFFALSE_EXIT(sb.Win32Assign(g_MsmInfo.m_sbMsmTemplateFile));
  142. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiOpenDatabaseW(sb, (LPCWSTR)MSIDBOPEN_READONLY, &phdb));
  143. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiDatabaseMergeW(g_MsmInfo.m_hdb, phdb, NULL));
  144. Exit:
  145. return hr;
  146. }
  147. }
  148. //
  149. // make msi-specified guid string ready : uppercase and replace "-" with "_"
  150. //
  151. HRESULT GetMsiGUIDStrFromGUID(DWORD dwFlags, GUID & guid, CSmallStringBuffer & str)
  152. {
  153. HRESULT hr = S_OK;
  154. LPOLESTR tmpstr = NULL;
  155. WCHAR tmpbuf[MAX_PATH];
  156. IFFAILED_EXIT(StringFromCLSID(guid, &tmpstr));
  157. wcscpy(tmpbuf, tmpstr);
  158. for (DWORD i=0; i < wcslen(tmpbuf); i++)
  159. {
  160. if (tmpbuf[i] == L'-')
  161. tmpbuf[i] = L'_';
  162. else
  163. tmpbuf[i]= towupper(tmpbuf[i]);
  164. }
  165. if (dwFlags & MSIGUIDSTR_WITH_PREPEND_DOT)
  166. {
  167. tmpbuf[0] = L'.';
  168. IFFALSE_EXIT(str.Win32Assign(tmpbuf, wcslen(tmpbuf) - 1 )); // has prepend "."
  169. }else
  170. IFFALSE_EXIT(str.Win32Assign(tmpbuf + 1 , wcslen(tmpbuf) - 2 )); // get rid of "{" and "}"
  171. Exit:
  172. return hr;
  173. }
  174. //
  175. // this function has to be called after the assembly name is known because we need query ComponentTable for MSMGEN_OPR_REGEN
  176. // use the input one, other get it from the componentTables
  177. //
  178. // the input keyPath could be NULL for policy assembly or assembly-without-data files
  179. //
  180. HRESULT SetComponentId(PCWSTR componentIdentifier, PCWSTR keyPath)
  181. {
  182. HRESULT hr = S_OK;
  183. BOOL fExist = FALSE;
  184. CStringBuffer str;
  185. LPOLESTR tmpstr = NULL;
  186. //
  187. // prepare component ID if not input-specified
  188. //
  189. if ((g_MsmInfo.m_enumGenMode == MSMGEN_OPR_ADD) || (g_MsmInfo.m_enumGenMode == MSMGEN_OPR_NEW))
  190. {
  191. if (curAsmInfo.m_sbComponentID.IsEmpty())
  192. {
  193. goto generate_new_componentID_and_insert;
  194. }
  195. else
  196. {
  197. goto insert_into_table;
  198. }
  199. }
  200. else if (g_MsmInfo.m_enumGenMode == MSMGEN_OPR_REGEN)
  201. {
  202. MSIHANDLE * hRecord = NULL;
  203. IFFAILED_EXIT(ExecuteQuerySQL(L"Component", L"Component", componentIdentifier, fExist, NULL));
  204. if (fExist == FALSE)
  205. {
  206. if (curAsmInfo.m_sbComponentID.IsEmpty())
  207. {
  208. // SET_HRERR_AND_EXIT(ERROR_INTERNAL_ERROR);
  209. goto generate_new_componentID_and_insert;
  210. }
  211. else
  212. {
  213. goto insert_into_table;
  214. }
  215. }
  216. else
  217. {
  218. if (! curAsmInfo.m_sbComponentID.IsEmpty() )
  219. {
  220. // change the componentID, using the user-input one
  221. IFFAILED_EXIT(ExecuteUpdateSQL(L"Component", L"Component", componentIdentifier,
  222. L"ComponentId", curAsmInfo.m_sbComponentID));
  223. }
  224. hr = S_OK;
  225. goto Exit;
  226. }
  227. }
  228. generate_new_componentID_and_insert:
  229. GUID tmpguid;
  230. IFFAILED_EXIT(::CoCreateGuid(&tmpguid));
  231. IFFAILED_EXIT(StringFromCLSID(tmpguid, &tmpstr));
  232. IFFALSE_EXIT(curAsmInfo.m_sbComponentID.Win32Assign(tmpstr, wcslen(tmpstr)));
  233. insert_into_table:
  234. IFFALSE_EXIT(str.Win32Assign(SYSTEM_FOLDER, NUMBER_OF(SYSTEM_FOLDER)-1));
  235. IFFALSE_EXIT(str.Win32Append(g_MsmInfo.m_sbModuleGuidStr));
  236. IFFAILED_EXIT(ExecuteInsertTableSQL(
  237. OPT_COMPONENT,
  238. NUMBER_OF_PARAM_TO_INSERT_TABLE_COMPONENT,
  239. MAKE_PCWSTR(curAsmInfo.m_sbComponentIdentifier),
  240. MAKE_PCWSTR(curAsmInfo.m_sbComponentID),
  241. MAKE_PCWSTR(str),
  242. MAKE_PCWSTR(keyPath)));
  243. Exit:
  244. CoTaskMemFree(tmpstr);
  245. return hr;
  246. }