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.
 
 
 
 
 
 

637 lines
11 KiB

////////////////////////////////////////////////////////////////////////////////////
//
// 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;
}