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.

636 lines
11 KiB

  1. ////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved
  4. //
  5. // All rights reserved.
  6. //
  7. // Module Name:
  8. //
  9. // MSIDataLock.cpp
  10. //
  11. // Abstract:
  12. //
  13. // definitions of lock for msi handles
  14. //
  15. ////////////////////////////////////////////////////////////////////////////////////
  16. #include "precomp.h"
  17. #include "MSIDataLock.h"
  18. ////////////////////////////////////////////////////////////////////////////////////
  19. // extern variables
  20. ////////////////////////////////////////////////////////////////////////////////////
  21. extern CRITICAL_SECTION g_msi_prov_cs;
  22. MSIHANDLE MSIDataLockBase::m_hProduct = NULL;
  23. MSIHANDLE MSIDataLockBase::m_hDatabase = NULL;
  24. HANDLE MSIDataLockBase::m_hOwn = NULL;
  25. LPWSTR MSIDataLockBase::m_wszProduct = NULL;
  26. DWORD MSIDataLockBase::m_ThreadID = 0L;
  27. LONG MSIDataLockBase::m_lRefProduct = 0L;
  28. LONG MSIDataLockBase::m_lRefDatabase = 0L;
  29. BOOL MSIDataLockBase::m_bProductOwn = FALSE;
  30. BOOL MSIDataLockBase::m_bDatabaseOwn = FALSE;
  31. LONG MSIDataLockBase::m_lRef = 0L;
  32. ////////////////////////////////////////////////////////////////////////////////////
  33. // IMPLEMENTATION
  34. ////////////////////////////////////////////////////////////////////////////////////
  35. MSIDataLockBase::MSIDataLockBase ()
  36. {
  37. Initialize ();
  38. }
  39. MSIDataLockBase::~MSIDataLockBase ()
  40. {
  41. Uninitialize ();
  42. }
  43. BOOL MSIDataLockBase::Initialize ()
  44. {
  45. BOOL bResult = TRUE;
  46. ::EnterCriticalSection ( &g_msi_prov_cs );
  47. if ( ! m_hOwn && ( m_hOwn = ::CreateEvent ( NULL, TRUE, TRUE, NULL ) ) == NULL )
  48. {
  49. bResult = FALSE;
  50. }
  51. if ( bResult )
  52. {
  53. m_lRef++;
  54. }
  55. ::LeaveCriticalSection ( &g_msi_prov_cs );
  56. return bResult;
  57. }
  58. void MSIDataLockBase::Uninitialize ()
  59. {
  60. ::EnterCriticalSection ( &g_msi_prov_cs );
  61. if ( m_lRef && ( --m_lRef == 0 ) )
  62. {
  63. if ( m_hOwn )
  64. {
  65. ::CloseHandle ( m_hOwn );
  66. m_hOwn = NULL;
  67. }
  68. }
  69. ::LeaveCriticalSection ( &g_msi_prov_cs );
  70. return;
  71. }
  72. BOOL MSIDataLockBase::Lock ( void )
  73. {
  74. BOOL bResult = FALSE;
  75. BOOL bWork = TRUE;
  76. BOOL bSect = TRUE;
  77. while ( bWork )
  78. {
  79. ::EnterCriticalSection ( &g_msi_prov_cs );
  80. // we have obtained critsec now
  81. bSect = TRUE;
  82. // are handles already allocated ?
  83. if ( m_hProduct != NULL || m_hDatabase != NULL )
  84. {
  85. if ( ::GetCurrentThreadId () != m_ThreadID )
  86. {
  87. DWORD dwWaitResult = 0L;
  88. // we have left crit sec
  89. ::LeaveCriticalSection ( &g_msi_prov_cs );
  90. bSect = FALSE;
  91. // wait till resource gets free again
  92. dwWaitResult = ::WaitForSingleObject ( m_hOwn, INFINITE );
  93. if ( dwWaitResult == WAIT_OBJECT_0 )
  94. {
  95. bWork = TRUE;
  96. bResult = FALSE;
  97. }
  98. else
  99. {
  100. bWork = FALSE;
  101. bResult = FALSE;
  102. }
  103. }
  104. else
  105. {
  106. bWork = FALSE;
  107. bResult = TRUE;
  108. }
  109. }
  110. else
  111. {
  112. m_ThreadID = ::GetCurrentThreadId ( );
  113. bWork = FALSE;
  114. bResult = TRUE;
  115. }
  116. }
  117. if ( bSect && ! bResult )
  118. {
  119. ::LeaveCriticalSection ( &g_msi_prov_cs );
  120. }
  121. return bResult;
  122. }
  123. void MSIDataLockBase::Unlock ( void )
  124. {
  125. try
  126. {
  127. if ( !m_bProductOwn && !m_bDatabaseOwn )
  128. {
  129. m_ThreadID = 0;
  130. ::SetEvent ( m_hOwn );
  131. }
  132. }
  133. catch (...)
  134. {
  135. ::LeaveCriticalSection ( &g_msi_prov_cs );
  136. throw ;
  137. }
  138. ::LeaveCriticalSection ( &g_msi_prov_cs );
  139. }
  140. HRESULT MSIDataLock::OpenProductAlloc ( LPCWSTR wszProduct )
  141. {
  142. HRESULT hRes = S_OK;
  143. try
  144. {
  145. if ( ( m_wszProduct = new WCHAR [ lstrlenW ( wszProduct ) + 1 ] ) == NULL )
  146. {
  147. throw CHeap_Exception ( CHeap_Exception::E_ALLOCATION_ERROR );
  148. }
  149. lstrcpyW ( m_wszProduct, wszProduct );
  150. }
  151. catch ( ... )
  152. {
  153. if ( m_wszProduct )
  154. {
  155. delete [] m_wszProduct;
  156. m_wszProduct = NULL;
  157. }
  158. throw;
  159. }
  160. return hRes;
  161. }
  162. HRESULT MSIDataLock::OpenProductInternal ( LPCWSTR wszProduct )
  163. {
  164. HRESULT hRes = E_FAIL;
  165. UINT uiStatus = ERROR_SUCCESS;
  166. BOOL bAlloc = FALSE;
  167. try
  168. {
  169. if ( ( uiStatus = g_fpMsiOpenProductW ( wszProduct, &m_hProduct ) ) != ERROR_SUCCESS )
  170. {
  171. if ( uiStatus == static_cast < UINT > ( E_OUTOFMEMORY ) )
  172. {
  173. throw CHeap_Exception ( CHeap_Exception::E_ALLOCATION_ERROR );
  174. }
  175. }
  176. }
  177. catch ( ... )
  178. {
  179. if ( m_hProduct )
  180. {
  181. g_fpMsiCloseHandle ( m_hProduct );
  182. m_hProduct = NULL;
  183. }
  184. throw;
  185. }
  186. if ( uiStatus != ERROR_SUCCESS )
  187. {
  188. //and if that didn't work, yet another way
  189. WCHAR * wcBuf = NULL;
  190. DWORD dwBufsize = BUFF_SIZE;
  191. if ( ( wcBuf = new WCHAR [ BUFF_SIZE ] ) == NULL )
  192. {
  193. throw CHeap_Exception ( CHeap_Exception::E_ALLOCATION_ERROR );
  194. }
  195. try
  196. {
  197. if ( ( uiStatus = g_fpMsiGetProductInfoW ( wszProduct, INSTALLPROPERTY_LOCALPACKAGE, wcBuf, &dwBufsize ) ) == ERROR_SUCCESS )
  198. {
  199. if ( dwBufsize > 0 )
  200. {
  201. uiStatus = g_fpMsiOpenPackageW ( wcBuf, &m_hProduct );
  202. }
  203. }
  204. }
  205. catch ( ... )
  206. {
  207. delete [] wcBuf;
  208. throw ;
  209. }
  210. delete [] wcBuf;
  211. if ( uiStatus == ERROR_SUCCESS && m_hProduct )
  212. {
  213. bAlloc = TRUE;
  214. }
  215. }
  216. else
  217. {
  218. if ( m_hProduct )
  219. {
  220. bAlloc = TRUE;
  221. }
  222. }
  223. if ( bAlloc )
  224. {
  225. try
  226. {
  227. hRes = OpenProductAlloc ( wszProduct );
  228. }
  229. catch ( ... )
  230. {
  231. if ( m_hProduct )
  232. {
  233. g_fpMsiCloseHandle ( m_hProduct );
  234. m_hProduct = NULL;
  235. }
  236. throw;
  237. }
  238. }
  239. return hRes;
  240. }
  241. HRESULT MSIDataLock::OpenProduct ( LPCWSTR wszProduct )
  242. {
  243. HRESULT hRes = E_FAIL;
  244. if ( ! wszProduct )
  245. {
  246. hRes = E_INVALIDARG;
  247. }
  248. else
  249. {
  250. if ( Lock ( ) )
  251. {
  252. try
  253. {
  254. if ( ! m_hProduct && ! m_wszProduct )
  255. {
  256. hRes = OpenProductInternal ( wszProduct );
  257. if FAILED ( hRes )
  258. {
  259. if ( m_wszProduct )
  260. {
  261. delete [] m_wszProduct;
  262. m_wszProduct = NULL;
  263. }
  264. if ( m_hProduct )
  265. {
  266. g_fpMsiCloseHandle ( m_hProduct );
  267. m_hProduct = NULL;
  268. }
  269. }
  270. }
  271. else
  272. {
  273. if ( m_hProduct && m_wszProduct && lstrcmpW ( wszProduct, m_wszProduct ) == 0 )
  274. {
  275. hRes = S_OK;
  276. }
  277. }
  278. if SUCCEEDED ( hRes )
  279. {
  280. if ( m_lRefProduct == 0 )
  281. {
  282. m_bProductOwn = TRUE;
  283. ::ResetEvent ( m_hOwn );
  284. }
  285. m_lRefProduct++;
  286. }
  287. }
  288. catch ( ... )
  289. {
  290. Unlock ( );
  291. throw;
  292. }
  293. Unlock ( );
  294. }
  295. }
  296. return hRes;
  297. }
  298. HRESULT MSIDataLock::OpenDatabase ( )
  299. {
  300. HRESULT hRes = E_FAIL;
  301. if ( Lock ( ) )
  302. {
  303. try
  304. {
  305. if ( m_hProduct )
  306. {
  307. if ( ! m_hDatabase )
  308. {
  309. m_hDatabase = g_fpMsiGetActiveDatabase ( m_hProduct );
  310. if ( m_hDatabase != NULL )
  311. {
  312. hRes = S_OK;
  313. }
  314. }
  315. else
  316. {
  317. MSIHANDLE hDatabase = NULL;
  318. hDatabase = g_fpMsiGetActiveDatabase ( m_hProduct );
  319. if ( hDatabase != NULL )
  320. {
  321. if ( hDatabase == m_hDatabase )
  322. {
  323. g_fpMsiCloseHandle ( hDatabase );
  324. hDatabase = NULL;
  325. hRes = S_OK;
  326. }
  327. }
  328. }
  329. if SUCCEEDED ( hRes )
  330. {
  331. if ( m_lRefDatabase == 0 )
  332. {
  333. m_bDatabaseOwn = TRUE;
  334. ::ResetEvent ( m_hOwn );
  335. }
  336. m_lRefDatabase++;
  337. }
  338. }
  339. }
  340. catch ( ... )
  341. {
  342. Unlock ( );
  343. throw;
  344. }
  345. Unlock ( );
  346. }
  347. return hRes;
  348. }
  349. HRESULT MSIDataLock::OpenDatabase ( LPCWSTR wszProduct )
  350. {
  351. HRESULT hRes = E_FAIL;
  352. if ( Lock ( ) )
  353. {
  354. try
  355. {
  356. if SUCCEEDED ( hRes = OpenProduct ( wszProduct ) )
  357. {
  358. hRes = OpenDatabase ();
  359. if FAILED ( hRes )
  360. {
  361. // we have to close product
  362. CloseProduct ();
  363. }
  364. }
  365. }
  366. catch ( ... )
  367. {
  368. Unlock ( );
  369. throw;
  370. }
  371. Unlock ( );
  372. }
  373. return hRes;
  374. }
  375. HRESULT MSIDataLock::CloseProduct ()
  376. {
  377. HRESULT hRes = S_FALSE;
  378. if ( Lock ( ) )
  379. {
  380. try
  381. {
  382. if ( m_hProduct && m_lRefProduct && ( --m_lRefProduct == 0 ) )
  383. {
  384. delete [] m_wszProduct;
  385. m_wszProduct = NULL;
  386. g_fpMsiCloseHandle ( m_hProduct );
  387. m_hProduct = NULL;
  388. m_bProductOwn = FALSE;
  389. hRes = S_OK;
  390. }
  391. }
  392. catch ( ... )
  393. {
  394. Unlock ( );
  395. throw;
  396. }
  397. Unlock ( );
  398. }
  399. return hRes;
  400. }
  401. HRESULT MSIDataLock::CloseDatabase ( )
  402. {
  403. HRESULT hRes = E_FAIL;
  404. if ( Lock ( ) )
  405. {
  406. try
  407. {
  408. if ( m_hDatabase && m_lRefDatabase && ( --m_lRefDatabase == 0 ) )
  409. {
  410. g_fpMsiCloseHandle ( m_hDatabase );
  411. m_hDatabase = NULL;
  412. m_bDatabaseOwn = FALSE;
  413. hRes = S_OK;
  414. }
  415. }
  416. catch ( ... )
  417. {
  418. Unlock ( );
  419. throw;
  420. }
  421. Unlock ( );
  422. }
  423. return hRes;
  424. }
  425. HRESULT MSIDataLock::Query ( MSIHANDLE* pView, LPCWSTR wszQuery, LPCWSTR wszTable )
  426. {
  427. HRESULT hRes = S_OK;
  428. UINT uiStatus= ERROR_SUCCESS;
  429. if ( ! pView )
  430. {
  431. hRes = E_POINTER;
  432. }
  433. else
  434. {
  435. ( * pView ) = NULL;
  436. if ( ! wszQuery )
  437. {
  438. hRes = E_INVALIDARG;
  439. }
  440. else
  441. {
  442. if ( Lock ( ) )
  443. {
  444. if ( m_hDatabase )
  445. {
  446. try
  447. {
  448. if ( wszTable )
  449. {
  450. if ( g_fpMsiDatabaseIsTablePersistentW ( m_hDatabase, wszTable ) != MSICONDITION_TRUE )
  451. {
  452. hRes = E_FAIL;
  453. }
  454. }
  455. if SUCCEEDED ( hRes )
  456. {
  457. if ( ( uiStatus = g_fpMsiDatabaseOpenViewW ( m_hDatabase, wszQuery, pView ) ) == ERROR_SUCCESS )
  458. {
  459. if ( g_fpMsiViewExecute ( *pView, 0 ) != ERROR_SUCCESS )
  460. {
  461. if ( *pView )
  462. {
  463. g_fpMsiCloseHandle ( *pView );
  464. ( * pView ) = NULL;
  465. }
  466. hRes = E_FAIL;
  467. }
  468. }
  469. else
  470. {
  471. if ( uiStatus == static_cast < UINT > ( E_OUTOFMEMORY ) )
  472. {
  473. throw CHeap_Exception ( CHeap_Exception::E_ALLOCATION_ERROR );
  474. }
  475. // what is the failure here ?
  476. hRes = HRESULT_FROM_WIN32 ( uiStatus );
  477. }
  478. }
  479. }
  480. catch ( ... )
  481. {
  482. Unlock ( );
  483. throw;
  484. }
  485. }
  486. else
  487. {
  488. hRes = E_UNEXPECTED;
  489. }
  490. Unlock ( );
  491. }
  492. }
  493. }
  494. return hRes;
  495. }
  496. bool MSIDataLock::GetView ( MSIHANDLE *phView,
  497. WCHAR *wcPackage,
  498. WCHAR *wcQuery,
  499. WCHAR *wcTable,
  500. BOOL bCloseProduct,
  501. BOOL bCloseDatabase
  502. )
  503. {
  504. bool bResult = false;
  505. if ( wcPackage )
  506. {
  507. if ( Lock () )
  508. {
  509. try
  510. {
  511. if SUCCEEDED ( OpenDatabase ( wcPackage ) )
  512. {
  513. if ( phView && wcQuery )
  514. {
  515. if SUCCEEDED ( Query ( phView, wcQuery, wcTable ) )
  516. {
  517. bResult = true;
  518. }
  519. }
  520. else
  521. {
  522. bResult = true;
  523. }
  524. if ( bCloseDatabase )
  525. {
  526. CloseDatabase ();
  527. }
  528. }
  529. if ( bCloseProduct )
  530. {
  531. CloseProduct ();
  532. }
  533. }
  534. catch ( ... )
  535. {
  536. CloseProduct ();
  537. CloseDatabase ();
  538. Unlock ();
  539. throw;
  540. }
  541. Unlock ();
  542. }
  543. }
  544. return bResult;
  545. }