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.

463 lines
15 KiB

  1. #include "stdinc.h"
  2. #include "macros.h"
  3. #include <msi.h>
  4. #include <msiquery.h>
  5. #include "common.h"
  6. HRESULT MSI_GetInstallerState(const MSIHANDLE & hInstall, enum CA_MIGRATION_MSI_INSTALL_MODE &fmode)
  7. {
  8. WCHAR szbuf[MAX_PATH];
  9. DWORD cchbuf = NUMBER_OF(szbuf);
  10. HRESULT hr = S_OK;
  11. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiGetPropertyW(hInstall, L"REMOVE", szbuf, &cchbuf));
  12. if (cchbuf != 0) // remove mode
  13. fmode = eRemoveProduct;
  14. else
  15. fmode = eInstallProduct;
  16. Exit:
  17. return hr;
  18. }
  19. VOID ResetCallbackInfo(CA_ENM_ASSEMBLY_CALLBACK_INFO &info)
  20. {
  21. info.pszComponentID = NULL;
  22. info.pszAssemblyUniqueDir = NULL;
  23. info.pszDestFolderID = NULL;
  24. info.pszManifestFileID = NULL;
  25. info.pszFileName = NULL;
  26. info.pszFileID = NULL;
  27. return;
  28. }
  29. //
  30. // basically, this func first lookup MsiAssembly Table,
  31. //
  32. HRESULT MSI_EnumWinFuseAssembly(DWORD dwFlags, const MSIHANDLE & hInstall, PCA_ENUM_FUSION_WIN32_ASSEMBLY_CALLBACK pfnCallback)
  33. {
  34. HRESULT hr = S_OK;
  35. WCHAR bufSQL[CA_MAX_BUF];
  36. WCHAR szManifestFileID[256];
  37. WCHAR szComponentID[128];
  38. UINT iRet;
  39. PMSIHANDLE hView = NULL;
  40. PMSIHANDLE hRecord = NULL;
  41. DWORD cchManifestFileID, cchComponentID;
  42. BOOL fFusionWin32Component;
  43. BOOL fExist = FALSE;
  44. CA_ENM_ASSEMBLY_CALLBACK_INFO info;
  45. MSIHANDLE hdb = NULL;
  46. PARAMETER_CHECK_NTC((dwFlags & ~(ENUM_ASSEMBLY_FLAG_CHECK_ASSEMBLY_ONLY |
  47. ENUM_ASSEMBLY_FLAG_CHECK_POLICY_ONLY)) == 0);
  48. PARAMETER_CHECK_NTC(hInstall != NULL);
  49. PARAMETER_CHECK_NTC(pfnCallback != NULL);
  50. if (dwFlags == 0)
  51. dwFlags = (ENUM_ASSEMBLY_FLAG_CHECK_ASSEMBLY_ONLY | ENUM_ASSEMBLY_FLAG_CHECK_POLICY_ONLY);
  52. hdb = MsiGetActiveDatabase(hInstall);
  53. INTERNAL_ERROR_CHECK_NTC(hdb != 0);
  54. IFFAILED_EXIT(MSI_IsTableExist(hdb, L"MsiAssembly", fExist));
  55. if ( fExist == FALSE)
  56. goto Exit;
  57. //
  58. // initialize info structure
  59. //
  60. ZeroMemory(&info, sizeof(info));
  61. IFFAILED_EXIT(MSI_IsTableExist(hdb, WIN32_ASSEMBLY_MIGRATE_TABLE, fExist));
  62. if (!fExist)
  63. info.dwFlags = CA_ENM_ASSEMBLY_CALLBACK_INFO_FLAG_IGNORE_MIGRATE_DENY_CHECK;
  64. info.hInstall = hInstall;
  65. info.hdb = hdb;
  66. //
  67. // Query Fusion Win32 Assembly, exclude private assembly
  68. //
  69. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewW(hdb, ca_sqlQuery[CA_SQL_QUERY_MSIASSEMBLY], &hView));
  70. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(hView, 0));
  71. for (;;)
  72. {
  73. //
  74. // reset info structure for component-related fields
  75. // except handles ( hInstall and hdb) and dwflags
  76. //
  77. ResetCallbackInfo(info);
  78. //
  79. // for each entry in MsiAssembly Table
  80. //
  81. iRet = MsiViewFetch(hView, &hRecord);
  82. if (iRet == ERROR_NO_MORE_ITEMS)
  83. break;
  84. if (iRet != ERROR_SUCCESS )
  85. SET_HRERR_AND_EXIT(iRet);
  86. iRet = MsiRecordGetInteger(hRecord, 1);
  87. if ( iRet != MSI_FUSION_WIN32_ASSEMBLY)
  88. continue;
  89. //
  90. // get manifest-filename ID
  91. //
  92. cchManifestFileID = NUMBER_OF(szManifestFileID);
  93. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiRecordGetString(hRecord, 2, szManifestFileID, &cchManifestFileID));
  94. //
  95. // get componentID
  96. //
  97. cchComponentID = NUMBER_OF(szComponentID);
  98. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiRecordGetString(hRecord, 3, szComponentID, &cchComponentID));
  99. MsiCloseHandle(hRecord);
  100. //
  101. // check whether it is policy by searching MsiAssemblyName::type = "win32" or "win32-policy"
  102. //
  103. if (dwFlags != (ENUM_ASSEMBLY_FLAG_CHECK_ASSEMBLY_ONLY | ENUM_ASSEMBLY_FLAG_CHECK_POLICY_ONLY)) // otherwise, no check is needed
  104. {
  105. PMSIHANDLE local_hView = NULL;
  106. PMSIHANDLE local_hRecord = NULL;
  107. WCHAR bufType[64];
  108. DWORD cchType = NUMBER_OF(bufType);
  109. swprintf(bufSQL, ca_sqlQuery[CA_SQL_QUERY_MSIASSEMBLYNAME], szComponentID);
  110. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewW(hdb, bufSQL, &local_hView));
  111. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(local_hView, 0));
  112. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewFetch(local_hView, &local_hRecord));
  113. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiRecordGetString(local_hRecord, 1, bufType, &cchType));
  114. fFusionWin32Component = FALSE;
  115. if (dwFlags & ENUM_ASSEMBLY_FLAG_CHECK_ASSEMBLY_ONLY)
  116. {
  117. if (_wcsicmp(bufType, CA_FUSION_WIN32_ASSEMBLY_TYPE) == 0)
  118. fFusionWin32Component = TRUE;
  119. }
  120. if (dwFlags & ENUM_ASSEMBLY_FLAG_CHECK_POLICY_ONLY)
  121. {
  122. if (_wcsicmp(bufType, CA_FUSION_WIN32_POLICY_TYPE) == 0)
  123. fFusionWin32Component = TRUE;
  124. }
  125. if (fFusionWin32Component == FALSE)
  126. continue;
  127. }
  128. //
  129. // OK, we got ComponentID of a fusion-win32 component now; callback would have a show
  130. //
  131. ASSERT_NTC(szComponentID != NULL);
  132. ASSERT_NTC(szManifestFileID != NULL);
  133. info.pszComponentID = szComponentID;
  134. info.pszManifestFileID = szManifestFileID;
  135. IFFAILED_EXIT(pfnCallback(&info));
  136. }
  137. Exit:
  138. if(hdb != NULL)
  139. MsiCloseHandle(hdb);
  140. return hr;
  141. }
  142. HRESULT MSI_GetSourceFileFullPathName(DWORD dwFlags, const MSIHANDLE & hInstall, const MSIHANDLE & hdb, PCWSTR szComponentDirectory, PCWSTR pszFile, CStringBuffer &sbFileName, PCWSTR pszComponent)
  143. {
  144. HRESULT hr = S_OK;
  145. WCHAR szFileNameInTable[CA_MAX_BUF];
  146. DWORD cchFileNameInTable = NUMBER_OF(szFileNameInTable);
  147. PWSTR pszFileNameInTable = NULL;
  148. PMSIHANDLE hView = NULL;
  149. PMSIHANDLE hRecord = NULL;
  150. WCHAR szDirectory[MAX_PATH];
  151. DWORD cchDirectory = NUMBER_OF(szDirectory);
  152. PWSTR pszComponentDirectory = NULL;
  153. PARAMETER_CHECK_NTC((dwFlags == CA_FILEFULLPATHNAME_FILENAME_IN_FILE_TABLE) || (dwFlags == CA_FILEFULLPATHNAME_FILEID_IN_FILE_TABLE));
  154. PARAMETER_CHECK_NTC(hInstall != NULL);
  155. PARAMETER_CHECK_NTC(pszFile != NULL);
  156. PARAMETER_CHECK_NTC((szComponentDirectory != NULL) || ((hInstall != NULL) && (pszComponent != NULL)));
  157. PARAMETER_CHECK_NTC((dwFlags != CA_FILEFULLPATHNAME_FILEID_IN_FILE_TABLE) || (pszComponent != NULL));
  158. if ( dwFlags == CA_FILEFULLPATHNAME_FILEID_IN_FILE_TABLE)
  159. {
  160. WCHAR sqlbuf[CA_MAX_BUF];
  161. swprintf(sqlbuf, ca_sqlQuery[CA_SQL_QUERY_FILENAME_USING_FILEID], pszFile, pszComponent);
  162. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewW(hdb, sqlbuf, &hView));
  163. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(hView, 0));
  164. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiViewFetch(hView, &hRecord)); // this call should succeed otherwise fail
  165. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiRecordGetString(hRecord, 1, szFileNameInTable, &cchFileNameInTable));
  166. pszFileNameInTable = szFileNameInTable;
  167. }
  168. else
  169. pszFileNameInTable = const_cast<PWSTR>(pszFile);
  170. if (szComponentDirectory == NULL)
  171. {
  172. IFFAILED_EXIT(MSI_GetComponentSourceDirectory(hInstall, hdb, pszComponent, szDirectory, cchDirectory));
  173. pszComponentDirectory = szDirectory;
  174. }
  175. else
  176. pszComponentDirectory = const_cast<PWSTR>(szComponentDirectory);
  177. IFFALSE_EXIT(sbFileName.Win32Assign(pszComponentDirectory, wcslen(pszComponentDirectory)));
  178. IFFALSE_EXIT(sbFileName.Win32EnsureTrailingPathSeparator());
  179. PWSTR p = wcschr(pszFileNameInTable, L'|');
  180. if ( p != NULL)
  181. {
  182. p++; // skip '|'
  183. IFFALSE_EXIT(sbFileName.Win32Append(p, wcslen(p)));
  184. }else
  185. {
  186. WCHAR szLongPathName[MAX_PATH];
  187. CStringBuffer FullPathShortFileName;
  188. WCHAR szShortPathName[MAX_PATH];
  189. DWORD ret = 0;
  190. //
  191. // get short name of the directory
  192. //
  193. ret = GetShortPathNameW(sbFileName, szShortPathName, NUMBER_OF(szShortPathName));
  194. if (( ret == 0) || (ret > NUMBER_OF(szShortPathName)))
  195. {
  196. SET_HRERR_AND_EXIT(::GetLastError());
  197. }
  198. IFFALSE_EXIT(FullPathShortFileName.Win32Assign(szShortPathName, wcslen(szShortPathName)));
  199. IFFALSE_EXIT(FullPathShortFileName.Win32Append(pszFileNameInTable, wcslen(pszFileNameInTable)));
  200. ret = GetLongPathNameW(FullPathShortFileName, szLongPathName, NUMBER_OF(szLongPathName));
  201. if (( ret == 0) || (ret > NUMBER_OF(szLongPathName)))
  202. {
  203. SET_HRERR_AND_EXIT(::GetLastError());
  204. }
  205. IFFALSE_EXIT(sbFileName.Win32Assign(szLongPathName, wcslen(szLongPathName)));
  206. }
  207. Exit:
  208. return hr;
  209. }
  210. HRESULT MSI_GetComponentSourceDirectory(const MSIHANDLE & hInstall, const MSIHANDLE & hdb, PCWSTR pszComponentID, PWSTR szDirectory, DWORD cchDirectory)
  211. {
  212. HRESULT hr = S_OK;
  213. WCHAR sqlBuf[CA_MAX_BUF];
  214. PMSIHANDLE hView = NULL;
  215. PMSIHANDLE hRecord = NULL;
  216. WCHAR szDirectoryID[128];
  217. DWORD cchDirectoryID = NUMBER_OF(szDirectoryID);
  218. PARAMETER_CHECK_NTC(hInstall != NULL);
  219. PARAMETER_CHECK_NTC((pszComponentID != NULL) && (szDirectory!= NULL) && (cchDirectory != 0));
  220. swprintf(sqlBuf, ca_sqlQuery[CA_SQL_QUERY_COMPONENT], pszComponentID);
  221. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewW(hdb, sqlBuf, &hView));
  222. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(hView, 0));
  223. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiViewFetch(hView, &hRecord)); // this call should succeed otherwise fail
  224. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiRecordGetString(hRecord, 1, szDirectoryID, &cchDirectoryID));
  225. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiGetSourcePath(hInstall, szDirectoryID, szDirectory, &cchDirectory));
  226. Exit:
  227. return hr;
  228. }
  229. HRESULT MSI_EnumComponentFiles(CA_ENM_ASSEMBLY_CALLBACK_INFO * info, PCA_ENUM_COMPONENT_FILES_CALLBACK pfnCallback)
  230. {
  231. HRESULT hr = S_OK;
  232. WCHAR bufFileName[CA_MAX_BUF];
  233. WCHAR bufFileID[CA_MAX_BUF];
  234. WCHAR sqlbuf[CA_MAX_BUF];
  235. DWORD cchbuf;
  236. PMSIHANDLE hView = NULL;
  237. PMSIHANDLE hRecord = NULL;
  238. UINT iRet;
  239. PARAMETER_CHECK_NTC((info != NULL) && (info->pszComponentID != (PCWSTR)NULL) && (info->hInstall != NULL));
  240. PARAMETER_CHECK_NTC(pfnCallback != NULL);
  241. swprintf(sqlbuf, ca_sqlQuery[CA_SQL_QUERY_FILETABLE_USING_COMPONENTID], info->pszComponentID);
  242. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewW(info->hdb, sqlbuf, &hView));
  243. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(hView, 0));
  244. for (;;)
  245. {
  246. //
  247. // for each entry in MsiAssembly Table
  248. //
  249. iRet = MsiViewFetch(hView, &hRecord);
  250. if (iRet == ERROR_NO_MORE_ITEMS)
  251. break;
  252. if (iRet != ERROR_SUCCESS )
  253. SET_HRERR_AND_EXIT(iRet);
  254. cchbuf = NUMBER_OF(bufFileID);
  255. bufFileID[0] = L'\0';
  256. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiRecordGetStringW(hRecord, 1, bufFileID, &cchbuf));
  257. cchbuf = NUMBER_OF(bufFileName);
  258. bufFileName[0] = L'\0';
  259. IF_NOTSUCCESS_SET_HRERR_EXIT(MsiRecordGetStringW(hRecord, 2, bufFileName, &cchbuf));
  260. info->pszFileName = bufFileName;
  261. info->pszFileID = bufFileID;
  262. IFFAILED_EXIT(pfnCallback(info));
  263. }
  264. Exit:
  265. return hr;
  266. }
  267. HRESULT MSI_IsTableExist(const MSIHANDLE & hdb, PCWSTR pszTableName, BOOL & fExist)
  268. {
  269. HRESULT hr = S_OK;
  270. WCHAR sqlbuf[CA_MAX_BUF];
  271. PMSIHANDLE hView = NULL;
  272. PMSIHANDLE hRecord = NULL;
  273. DWORD iRet;
  274. PARAMETER_CHECK_NTC((hdb != NULL) && (pszTableName != NULL));
  275. fExist = FALSE;
  276. swprintf(sqlbuf, L"SELECT * FROM `_Tables` WHERE `Name`='%s'", pszTableName);
  277. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewW(hdb, sqlbuf, &hView));
  278. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(hView, 0));
  279. iRet = MsiViewFetch(hView, &hRecord);
  280. if (iRet == ERROR_NO_MORE_ITEMS)
  281. {
  282. goto Exit;
  283. }
  284. else
  285. if (iRet != ERROR_SUCCESS)
  286. {
  287. SET_HRERR_AND_EXIT(iRet);
  288. }
  289. fExist = TRUE;
  290. Exit:
  291. return hr;
  292. }
  293. HRESULT Msi_CreateTableIfNotExist(const MSIHANDLE & hdb, PCWSTR pwszTableName, PCWSTR pwszTableSchema, BOOL & fExistAlready)
  294. {
  295. HRESULT hr = S_OK;
  296. PMSIHANDLE hView = NULL;
  297. PARAMETER_CHECK_NTC((pwszTableSchema != NULL) && (pwszTableName != NULL));
  298. fExistAlready = FALSE;
  299. IFFAILED_EXIT(MSI_IsTableExist(hdb, pwszTableName, fExistAlready));
  300. if (fExistAlready == TRUE)
  301. goto Exit;
  302. //
  303. // create the table
  304. //
  305. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiDatabaseOpenViewW(hdb, pwszTableSchema, &hView));
  306. IF_NOTSUCCESS_SET_HRERR_EXIT(::MsiViewExecute(hView, 0));
  307. Exit:
  308. return hr;
  309. }
  310. typedef enum _FUSION_MSI_OS_VERSION
  311. {
  312. E_OS_UNKNOWN,
  313. E_WIN95,
  314. E_WIN_ME,
  315. E_WIN_NT,
  316. E_WIN98,
  317. E_WIN2K,
  318. E_WHISTLER,
  319. E_WIN32_OTHERS
  320. }FUSION_MSI_OS_VERSION;
  321. typedef enum _FUSION_MSI_OS_TYPE
  322. {
  323. E_PERSONAL,
  324. E_PROFESSIONAL,
  325. E_DATA_CENTER,
  326. E_STD_SERVER,
  327. E_ADV_SERVER,
  328. E_WORKSTATION,
  329. E_SERVER
  330. }FUSION_MSI_OS_TYPE;
  331. HRESULT GetOSVersion(FUSION_MSI_OS_VERSION & osv)
  332. {
  333. HRESULT hr = S_OK;
  334. OSVERSIONINFO osvi;
  335. BOOL bOsVersionInfoEx;
  336. osv = E_OS_UNKNOWN;
  337. if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
  338. {
  339. // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
  340. osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  341. if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
  342. {
  343. hr = HRESULT_FROM_WIN32(::GetLastError());
  344. goto Exit;
  345. }
  346. }
  347. switch (osvi.dwPlatformId)
  348. {
  349. case VER_PLATFORM_WIN32_NT:
  350. if ( osvi.dwMajorVersion <= 4 )
  351. osv = E_WIN_NT;
  352. else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
  353. osv = E_WIN2K;
  354. else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
  355. osv = E_WHISTLER;
  356. case VER_PLATFORM_WIN32_WINDOWS:
  357. if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
  358. osv = E_WIN95;
  359. else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
  360. osv = E_WIN98;
  361. else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
  362. osv = E_WIN_ME;
  363. break;
  364. case VER_PLATFORM_WIN32s:
  365. osv = E_WIN32_OTHERS;
  366. break;
  367. }
  368. Exit:
  369. return hr;
  370. }
  371. BOOL IsDownlevel()
  372. {
  373. FUSION_MSI_OS_VERSION osv = E_OS_UNKNOWN;
  374. if (SUCCEEDED(GetOSVersion(osv)))
  375. {
  376. return ((osv == E_WIN2K) || (osv == E_WIN98));
  377. }
  378. return FALSE;
  379. }