|
|
////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved
//
// All rights reserved.
//
// Module Name:
//
// MSIDataLock.cpp
//
// Abstract:
//
// definitions of lock for msi handles
//
////////////////////////////////////////////////////////////////////////////////////
#include "precomp.h"
#include "MSIDataLock.h"
////////////////////////////////////////////////////////////////////////////////////
// extern variables
////////////////////////////////////////////////////////////////////////////////////
extern CRITICAL_SECTION g_msi_prov_cs;
MSIHANDLE MSIDataLockBase::m_hProduct = NULL; MSIHANDLE MSIDataLockBase::m_hDatabase = NULL; HANDLE MSIDataLockBase::m_hOwn = NULL; LPWSTR MSIDataLockBase::m_wszProduct = NULL; DWORD MSIDataLockBase::m_ThreadID = 0L; LONG MSIDataLockBase::m_lRefProduct = 0L; LONG MSIDataLockBase::m_lRefDatabase = 0L; BOOL MSIDataLockBase::m_bProductOwn = FALSE; BOOL MSIDataLockBase::m_bDatabaseOwn = FALSE; LONG MSIDataLockBase::m_lRef = 0L;
////////////////////////////////////////////////////////////////////////////////////
// IMPLEMENTATION
////////////////////////////////////////////////////////////////////////////////////
MSIDataLockBase::MSIDataLockBase () { Initialize (); }
MSIDataLockBase::~MSIDataLockBase () { Uninitialize (); }
BOOL MSIDataLockBase::Initialize () { BOOL bResult = TRUE;
::EnterCriticalSection ( &g_msi_prov_cs );
if ( ! m_hOwn && ( m_hOwn = ::CreateEvent ( NULL, TRUE, TRUE, NULL ) ) == NULL ) { bResult = FALSE; }
if ( bResult ) { m_lRef++; }
::LeaveCriticalSection ( &g_msi_prov_cs );
return bResult; }
void MSIDataLockBase::Uninitialize () { ::EnterCriticalSection ( &g_msi_prov_cs );
if ( m_lRef && ( --m_lRef == 0 ) ) { if ( m_hOwn ) { ::CloseHandle ( m_hOwn ); m_hOwn = NULL; } }
::LeaveCriticalSection ( &g_msi_prov_cs );
return; }
BOOL MSIDataLockBase::Lock ( void ) { BOOL bResult = FALSE; BOOL bWork = TRUE; BOOL bSect = TRUE;
while ( bWork ) { ::EnterCriticalSection ( &g_msi_prov_cs );
// we have obtained critsec now
bSect = TRUE;
// are handles already allocated ?
if ( m_hProduct != NULL || m_hDatabase != NULL ) { if ( ::GetCurrentThreadId () != m_ThreadID ) { DWORD dwWaitResult = 0L;
// we have left crit sec
::LeaveCriticalSection ( &g_msi_prov_cs ); bSect = FALSE;
// wait till resource gets free again
dwWaitResult = ::WaitForSingleObject ( m_hOwn, INFINITE );
if ( dwWaitResult == WAIT_OBJECT_0 ) { bWork = TRUE; bResult = FALSE; } else { bWork = FALSE; bResult = FALSE; } } else { bWork = FALSE; bResult = TRUE; } } else { m_ThreadID = ::GetCurrentThreadId ( );
bWork = FALSE; bResult = TRUE; } }
if ( bSect && ! bResult ) { ::LeaveCriticalSection ( &g_msi_prov_cs ); }
return bResult; }
void MSIDataLockBase::Unlock ( void ) { try { if ( !m_bProductOwn && !m_bDatabaseOwn ) { m_ThreadID = 0; ::SetEvent ( m_hOwn ); } } catch (...) { ::LeaveCriticalSection ( &g_msi_prov_cs ); throw ; }
::LeaveCriticalSection ( &g_msi_prov_cs ); }
HRESULT MSIDataLock::OpenProductAlloc ( LPCWSTR wszProduct ) { HRESULT hRes = S_OK;
try { if ( ( m_wszProduct = new WCHAR [ lstrlenW ( wszProduct ) + 1 ] ) == NULL ) { throw CHeap_Exception ( CHeap_Exception::E_ALLOCATION_ERROR ); }
lstrcpyW ( m_wszProduct, wszProduct ); } catch ( ... ) { if ( m_wszProduct ) { delete [] m_wszProduct; m_wszProduct = NULL; }
throw; }
return hRes; }
HRESULT MSIDataLock::OpenProductInternal ( LPCWSTR wszProduct ) { HRESULT hRes = E_FAIL; UINT uiStatus = ERROR_SUCCESS;
BOOL bAlloc = FALSE;
try { if ( ( uiStatus = g_fpMsiOpenProductW ( wszProduct, &m_hProduct ) ) != ERROR_SUCCESS ) { if ( uiStatus == static_cast < UINT > ( E_OUTOFMEMORY ) ) { throw CHeap_Exception ( CHeap_Exception::E_ALLOCATION_ERROR ); } } } catch ( ... ) { if ( m_hProduct ) { g_fpMsiCloseHandle ( m_hProduct ); m_hProduct = NULL; }
throw; }
if ( uiStatus != ERROR_SUCCESS ) { //and if that didn't work, yet another way
WCHAR * wcBuf = NULL; DWORD dwBufsize = BUFF_SIZE;
if ( ( wcBuf = new WCHAR [ BUFF_SIZE ] ) == NULL ) { throw CHeap_Exception ( CHeap_Exception::E_ALLOCATION_ERROR ); }
try { if ( ( uiStatus = g_fpMsiGetProductInfoW ( wszProduct, INSTALLPROPERTY_LOCALPACKAGE, wcBuf, &dwBufsize ) ) == ERROR_SUCCESS ) { if ( dwBufsize > 0 ) { uiStatus = g_fpMsiOpenPackageW ( wcBuf, &m_hProduct ); } } } catch ( ... ) { delete [] wcBuf; throw ; }
delete [] wcBuf;
if ( uiStatus == ERROR_SUCCESS && m_hProduct ) { bAlloc = TRUE; } } else { if ( m_hProduct ) { bAlloc = TRUE; } }
if ( bAlloc ) { try { hRes = OpenProductAlloc ( wszProduct ); } catch ( ... ) { if ( m_hProduct ) { g_fpMsiCloseHandle ( m_hProduct ); m_hProduct = NULL; }
throw; } }
return hRes; }
HRESULT MSIDataLock::OpenProduct ( LPCWSTR wszProduct ) { HRESULT hRes = E_FAIL;
if ( ! wszProduct ) { hRes = E_INVALIDARG; } else { if ( Lock ( ) ) { try { if ( ! m_hProduct && ! m_wszProduct ) { hRes = OpenProductInternal ( wszProduct );
if FAILED ( hRes ) { if ( m_wszProduct ) { delete [] m_wszProduct; m_wszProduct = NULL; }
if ( m_hProduct ) { g_fpMsiCloseHandle ( m_hProduct ); m_hProduct = NULL; } } } else { if ( m_hProduct && m_wszProduct && lstrcmpW ( wszProduct, m_wszProduct ) == 0 ) { hRes = S_OK; } }
if SUCCEEDED ( hRes ) { if ( m_lRefProduct == 0 ) { m_bProductOwn = TRUE; ::ResetEvent ( m_hOwn ); }
m_lRefProduct++; } } catch ( ... ) { Unlock ( ); throw; }
Unlock ( ); } }
return hRes; }
HRESULT MSIDataLock::OpenDatabase ( ) { HRESULT hRes = E_FAIL;
if ( Lock ( ) ) { try { if ( m_hProduct ) { if ( ! m_hDatabase ) { m_hDatabase = g_fpMsiGetActiveDatabase ( m_hProduct );
if ( m_hDatabase != NULL ) { hRes = S_OK; } } else { MSIHANDLE hDatabase = NULL; hDatabase = g_fpMsiGetActiveDatabase ( m_hProduct );
if ( hDatabase != NULL ) { if ( hDatabase == m_hDatabase ) { g_fpMsiCloseHandle ( hDatabase ); hDatabase = NULL;
hRes = S_OK; } } }
if SUCCEEDED ( hRes ) { if ( m_lRefDatabase == 0 ) { m_bDatabaseOwn = TRUE; ::ResetEvent ( m_hOwn ); }
m_lRefDatabase++; } } } catch ( ... ) { Unlock ( ); throw; }
Unlock ( ); }
return hRes; }
HRESULT MSIDataLock::OpenDatabase ( LPCWSTR wszProduct ) { HRESULT hRes = E_FAIL;
if ( Lock ( ) ) { try { if SUCCEEDED ( hRes = OpenProduct ( wszProduct ) ) { hRes = OpenDatabase ();
if FAILED ( hRes ) { // we have to close product
CloseProduct (); } } } catch ( ... ) { Unlock ( ); throw; }
Unlock ( ); }
return hRes; }
HRESULT MSIDataLock::CloseProduct () { HRESULT hRes = S_FALSE;
if ( Lock ( ) ) { try { if ( m_hProduct && m_lRefProduct && ( --m_lRefProduct == 0 ) ) { delete [] m_wszProduct; m_wszProduct = NULL;
g_fpMsiCloseHandle ( m_hProduct ); m_hProduct = NULL; m_bProductOwn = FALSE; hRes = S_OK; } } catch ( ... ) { Unlock ( ); throw; }
Unlock ( ); }
return hRes; }
HRESULT MSIDataLock::CloseDatabase ( ) { HRESULT hRes = E_FAIL;
if ( Lock ( ) ) { try { if ( m_hDatabase && m_lRefDatabase && ( --m_lRefDatabase == 0 ) ) { g_fpMsiCloseHandle ( m_hDatabase ); m_hDatabase = NULL; m_bDatabaseOwn = FALSE; hRes = S_OK; } } catch ( ... ) { Unlock ( ); throw; }
Unlock ( ); }
return hRes; }
HRESULT MSIDataLock::Query ( MSIHANDLE* pView, LPCWSTR wszQuery, LPCWSTR wszTable ) { HRESULT hRes = S_OK; UINT uiStatus= ERROR_SUCCESS;
if ( ! pView ) { hRes = E_POINTER; } else { ( * pView ) = NULL;
if ( ! wszQuery ) { hRes = E_INVALIDARG; } else { if ( Lock ( ) ) { if ( m_hDatabase ) { try { if ( wszTable ) { if ( g_fpMsiDatabaseIsTablePersistentW ( m_hDatabase, wszTable ) != MSICONDITION_TRUE ) { hRes = E_FAIL; } }
if SUCCEEDED ( hRes ) { if ( ( uiStatus = g_fpMsiDatabaseOpenViewW ( m_hDatabase, wszQuery, pView ) ) == ERROR_SUCCESS ) { if ( g_fpMsiViewExecute ( *pView, 0 ) != ERROR_SUCCESS ) { if ( *pView ) { g_fpMsiCloseHandle ( *pView ); ( * pView ) = NULL; }
hRes = E_FAIL; } } else { if ( uiStatus == static_cast < UINT > ( E_OUTOFMEMORY ) ) { throw CHeap_Exception ( CHeap_Exception::E_ALLOCATION_ERROR ); }
// what is the failure here ?
hRes = HRESULT_FROM_WIN32 ( uiStatus ); } } } catch ( ... ) { Unlock ( ); throw; } } else { hRes = E_UNEXPECTED; }
Unlock ( ); } } }
return hRes; }
bool MSIDataLock::GetView ( MSIHANDLE *phView, WCHAR *wcPackage, WCHAR *wcQuery, WCHAR *wcTable, BOOL bCloseProduct, BOOL bCloseDatabase ) { bool bResult = false;
if ( wcPackage ) { if ( Lock () ) { try { if SUCCEEDED ( OpenDatabase ( wcPackage ) ) { if ( phView && wcQuery ) { if SUCCEEDED ( Query ( phView, wcQuery, wcTable ) ) { bResult = true; } } else { bResult = true; }
if ( bCloseDatabase ) { CloseDatabase (); } }
if ( bCloseProduct ) { CloseProduct (); } } catch ( ... ) { CloseProduct (); CloseDatabase ();
Unlock ();
throw; }
Unlock (); } }
return bResult; }
|