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.
652 lines
16 KiB
652 lines
16 KiB
#include "stdafx.h"
|
|
#include "resource.h"
|
|
#include "imgutil.h"
|
|
#include "cdithtbl.h"
|
|
#include "dithers.h"
|
|
#include "cdith8.h"
|
|
#include "align.h"
|
|
#include "cddsurf.h"
|
|
//#include <icapexp.h>
|
|
|
|
void CopyColorsFromPaletteEntries(RGBQUAD *prgb, const PALETTEENTRY *ppe, UINT uCount);
|
|
|
|
CDitherTable* CDitherToRGB8::s_apTableCache[MAX_DITHERTABLE_CACHE_SIZE];
|
|
ULONG CDitherToRGB8::s_nCacheSize;
|
|
CRITICAL_SECTION CDitherToRGB8::s_csCache;
|
|
|
|
void CDitherToRGB8::InitTableCache()
|
|
{
|
|
ULONG iTable;
|
|
|
|
InitializeCriticalSection( &s_csCache );
|
|
|
|
s_nCacheSize = 0;
|
|
for( iTable = 0; iTable < MAX_DITHERTABLE_CACHE_SIZE; iTable++ )
|
|
{
|
|
s_apTableCache[iTable] = NULL;
|
|
}
|
|
}
|
|
|
|
void CDitherToRGB8::CleanupTableCache()
|
|
{
|
|
ULONG iTable;
|
|
|
|
EnterCriticalSection( &s_csCache );
|
|
for( iTable = 0; iTable < s_nCacheSize; iTable++ )
|
|
{
|
|
_ASSERTE( s_apTableCache[iTable]->m_nRefCount == 0 );
|
|
delete s_apTableCache[iTable];
|
|
s_apTableCache[iTable] = NULL;
|
|
}
|
|
s_nCacheSize = 0;
|
|
LeaveCriticalSection( &s_csCache );
|
|
|
|
DeleteCriticalSection( &s_csCache );
|
|
}
|
|
|
|
CDitherToRGB8::CDitherToRGB8() :
|
|
m_dwEvents( 0 ),
|
|
m_iScanLine( 0 ),
|
|
m_bProgressiveDither( FALSE ),
|
|
m_pErrBuf( NULL ),
|
|
m_pErrBuf1( NULL ),
|
|
m_pErrBuf2( NULL ),
|
|
m_pTable( NULL ),
|
|
m_pbBits( NULL ),
|
|
m_hbmDestDib( NULL )
|
|
{
|
|
}
|
|
|
|
CDitherToRGB8::~CDitherToRGB8()
|
|
{
|
|
if (m_pTable)
|
|
m_pTable->m_nRefCount--;
|
|
|
|
if (m_hbmDestDib)
|
|
DeleteObject(m_hbmDestDib);
|
|
}
|
|
|
|
STDMETHODIMP CDitherToRGB8::GetSurface( LONG nWidth, LONG nHeight,
|
|
REFGUID bfid, ULONG nPasses, DWORD dwHints, IUnknown** ppSurface )
|
|
{
|
|
HRESULT hResult;
|
|
CComPtr< IUnknown > pDestSurface;
|
|
|
|
if (ppSurface != NULL)
|
|
*ppSurface = NULL;
|
|
|
|
if ((nWidth <= 0) || (nHeight <= 0))
|
|
return E_INVALIDARG;
|
|
|
|
if (ppSurface == NULL)
|
|
return E_POINTER;
|
|
|
|
if (IsEqualGUID(bfid, BFID_RGB_24))
|
|
{
|
|
m_eSrcFormat = RGB24;
|
|
m_nBitsPerPixel = 24;
|
|
}
|
|
else if (IsEqualGUID(bfid, BFID_INDEXED_RGB_8))
|
|
{
|
|
m_eSrcFormat = RGB8;
|
|
m_nBitsPerPixel = 8;
|
|
}
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
m_nWidth = nWidth;
|
|
m_nHeight = nHeight;
|
|
|
|
if ((dwHints & IMGDECODE_HINT_TOPDOWN) &&
|
|
(dwHints & IMGDECODE_HINT_FULLWIDTH) &&
|
|
(m_dwEvents & IMGDECODE_EVENT_PROGRESS))
|
|
m_bProgressiveDither = TRUE;
|
|
else
|
|
m_bProgressiveDither = FALSE;
|
|
|
|
m_pErrBuf = new ERRBUF[(m_nWidth+2)*2];
|
|
if (m_pErrBuf == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
m_pErrBuf1 = &m_pErrBuf[1];
|
|
m_pErrBuf2 = &m_pErrBuf[m_nWidth+3];
|
|
|
|
memset(m_pErrBuf, 0, sizeof( ERRBUF )*(m_nWidth+2)*2);
|
|
|
|
hResult = m_pEventSink->GetSurface(m_nWidth, m_nHeight, BFID_INDEXED_RGB_8,
|
|
nPasses, dwHints, &pDestSurface);
|
|
if (FAILED(hResult))
|
|
return( hResult );
|
|
|
|
hResult = pDestSurface->QueryInterface(IID_IDirectDrawSurface,
|
|
(void **)&m_pDestSurface);
|
|
if (FAILED(hResult))
|
|
return hResult;
|
|
|
|
m_hbmDestDib = ImgCreateDib(m_nWidth, -LONG(m_nHeight), FALSE, m_nBitsPerPixel, 0, NULL,
|
|
&m_pbBits, (int *)&m_nPitch);
|
|
if (m_hbmDestDib == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
hResult = CreateDDrawSurfaceOnDIB(m_hbmDestDib, &m_pSurface);
|
|
if (FAILED(hResult))
|
|
return hResult;
|
|
|
|
*ppSurface = (IUnknown *)m_pSurface;
|
|
(*ppSurface)->AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CDitherToRGB8::OnBeginDecode( DWORD* pdwEvents, ULONG* pnFormats,
|
|
GUID** ppFormats )
|
|
{
|
|
HRESULT hResult;
|
|
GUID* pFormats;
|
|
ULONG nFormats;
|
|
ULONG iFormat;
|
|
BOOL bFound;
|
|
|
|
if( pdwEvents != NULL )
|
|
{
|
|
*pdwEvents = 0;
|
|
}
|
|
if( pnFormats != NULL )
|
|
{
|
|
*pnFormats = 0;
|
|
}
|
|
if( ppFormats != NULL )
|
|
{
|
|
*pnFormats = NULL;
|
|
}
|
|
if( pdwEvents == NULL )
|
|
{
|
|
return( E_POINTER );
|
|
}
|
|
if( pnFormats == NULL )
|
|
{
|
|
return( E_POINTER );
|
|
}
|
|
if( ppFormats == NULL )
|
|
{
|
|
return( E_POINTER );
|
|
}
|
|
|
|
hResult = m_pEventSink->OnBeginDecode( &m_dwEvents, &nFormats, &pFormats );
|
|
if( FAILED( hResult ) )
|
|
{
|
|
return( hResult );
|
|
}
|
|
|
|
bFound = FALSE;
|
|
for( iFormat = 0; (iFormat < nFormats) && !bFound; iFormat++ )
|
|
{
|
|
if( IsEqualGUID( pFormats[iFormat], BFID_INDEXED_RGB_8 ) )
|
|
{
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
CoTaskMemFree( pFormats );
|
|
if( !bFound )
|
|
{
|
|
return( E_FAIL );
|
|
}
|
|
|
|
*ppFormats = (GUID*)CoTaskMemAlloc( 3*sizeof( GUID ) );
|
|
if( *ppFormats == NULL )
|
|
{
|
|
return( E_OUTOFMEMORY );
|
|
}
|
|
*pnFormats = 3;
|
|
(*ppFormats)[0] = BFID_GRAY_8;
|
|
(*ppFormats)[1] = BFID_RGB_24;
|
|
(*ppFormats)[2] = BFID_INDEXED_RGB_8;
|
|
|
|
*pdwEvents = m_dwEvents|IMGDECODE_EVENT_BITSCOMPLETE|
|
|
IMGDECODE_EVENT_PALETTE;
|
|
|
|
return( S_OK );
|
|
}
|
|
|
|
STDMETHODIMP CDitherToRGB8::OnBitsComplete()
|
|
{
|
|
HRESULT hResult;
|
|
|
|
hResult = DitherFull();
|
|
if( FAILED( hResult ) )
|
|
{
|
|
return( hResult );
|
|
}
|
|
|
|
if( m_dwEvents & IMGDECODE_EVENT_BITSCOMPLETE )
|
|
{
|
|
hResult = m_pEventSink->OnBitsComplete();
|
|
if( FAILED( hResult ) )
|
|
{
|
|
return( hResult );
|
|
}
|
|
}
|
|
|
|
return( S_OK );
|
|
}
|
|
|
|
STDMETHODIMP CDitherToRGB8::OnDecodeComplete( HRESULT hrStatus )
|
|
{
|
|
HRESULT hResult;
|
|
|
|
delete m_pErrBuf;
|
|
m_pErrBuf = NULL;
|
|
m_pErrBuf1 = NULL;
|
|
m_pErrBuf2 = NULL;
|
|
|
|
// Propagate the transparency information if necessary
|
|
|
|
if (m_pSurface && m_pDestSurface)
|
|
{
|
|
DDCOLORKEY ddKey;
|
|
|
|
if (SUCCEEDED(m_pSurface->GetColorKey(DDCKEY_SRCBLT, &ddKey)))
|
|
m_pDestSurface->SetColorKey(DDCKEY_SRCBLT, &ddKey);
|
|
}
|
|
|
|
if( m_pSurface != NULL )
|
|
{
|
|
m_pSurface.Release();
|
|
}
|
|
if( m_pDestSurface != NULL )
|
|
{
|
|
m_pDestSurface.Release();
|
|
}
|
|
|
|
hResult = m_pEventSink->OnDecodeComplete( hrStatus );
|
|
m_pEventSink.Release();
|
|
if( FAILED( hResult ) )
|
|
{
|
|
return( hResult );
|
|
}
|
|
|
|
return( S_OK );
|
|
}
|
|
|
|
STDMETHODIMP CDitherToRGB8::OnPalette()
|
|
{
|
|
HRESULT hResult;
|
|
CComPtr< IDirectDrawPalette > pPalette;
|
|
PALETTEENTRY ape[256];
|
|
|
|
if (m_eSrcFormat == RGB8)
|
|
{
|
|
hResult = m_pSurface->GetPalette(&pPalette);
|
|
if (FAILED(hResult))
|
|
return hResult;
|
|
|
|
hResult = pPalette->GetEntries(0, 0, 256, ape);
|
|
if (FAILED(hResult))
|
|
return hResult;
|
|
|
|
CopyColorsFromPaletteEntries(m_argbSrcColors, ape, 256);
|
|
}
|
|
|
|
if (m_dwEvents & IMGDECODE_EVENT_PALETTE)
|
|
{
|
|
hResult = m_pEventSink->OnPalette();
|
|
if (FAILED(hResult))
|
|
{
|
|
return hResult;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CDitherToRGB8::OnProgress( RECT* pBounds, BOOL bComplete )
|
|
{
|
|
HRESULT hResult;
|
|
|
|
if( pBounds == NULL )
|
|
{
|
|
return( E_INVALIDARG );
|
|
}
|
|
|
|
if( m_bProgressiveDither && bComplete )
|
|
{
|
|
hResult = DitherBand( pBounds );
|
|
if( FAILED( hResult ) )
|
|
{
|
|
return( hResult );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hResult = ConvertBlock( pBounds );
|
|
if( FAILED( hResult ) )
|
|
{
|
|
return( hResult );
|
|
}
|
|
}
|
|
|
|
if( m_dwEvents & IMGDECODE_EVENT_PROGRESS )
|
|
{
|
|
hResult = m_pEventSink->OnProgress( pBounds, bComplete );
|
|
if( FAILED( hResult ) )
|
|
{
|
|
return( hResult );
|
|
}
|
|
}
|
|
|
|
return( S_OK );
|
|
}
|
|
|
|
STDMETHODIMP CDitherToRGB8::SetDestColorTable( ULONG nColors,
|
|
const RGBQUAD* prgbColors )
|
|
{
|
|
ULONG iTable;
|
|
HRESULT hResult;
|
|
|
|
if( (nColors == 0) || (nColors > 256) )
|
|
{
|
|
return( E_INVALIDARG );
|
|
}
|
|
if( prgbColors == NULL )
|
|
{
|
|
return( E_INVALIDARG );
|
|
}
|
|
|
|
EnterCriticalSection( &s_csCache );
|
|
|
|
if( m_pTable != NULL )
|
|
{
|
|
// Release whatever table we've got already
|
|
m_pTable->m_nRefCount--;
|
|
m_pTable = NULL;
|
|
}
|
|
|
|
// See if we can find the requested table in the cache
|
|
for( iTable = 0; (iTable < s_nCacheSize) && (m_pTable == NULL); iTable++ )
|
|
{
|
|
if( s_apTableCache[iTable]->Match( nColors, prgbColors ) )
|
|
{
|
|
m_pTable = s_apTableCache[iTable];
|
|
m_pTable->m_nRefCount++;
|
|
}
|
|
}
|
|
|
|
if( m_pTable == NULL )
|
|
{
|
|
if( s_nCacheSize < MAX_DITHERTABLE_CACHE_SIZE )
|
|
{
|
|
m_pTable = new CDitherTable;
|
|
if( m_pTable == NULL )
|
|
{
|
|
LeaveCriticalSection( &s_csCache );
|
|
return( E_OUTOFMEMORY );
|
|
}
|
|
hResult = m_pTable->SetColors( nColors, prgbColors );
|
|
if( FAILED( hResult ) )
|
|
{
|
|
LeaveCriticalSection( &s_csCache );
|
|
m_pTable = NULL;
|
|
return( hResult );
|
|
}
|
|
|
|
// Add a new cache entry
|
|
m_pTable->m_nRefCount++;
|
|
s_apTableCache[s_nCacheSize] = m_pTable;
|
|
s_nCacheSize++;
|
|
}
|
|
else
|
|
{
|
|
// Find a cache entry to replace.
|
|
for( iTable = 0; (iTable < s_nCacheSize) && (m_pTable == NULL);
|
|
iTable++ )
|
|
{
|
|
if( s_apTableCache[iTable]->m_nRefCount == 0 )
|
|
{
|
|
m_pTable = s_apTableCache[iTable];
|
|
hResult = m_pTable->SetColors( nColors, prgbColors );
|
|
if( FAILED( hResult ) )
|
|
{
|
|
LeaveCriticalSection( &s_csCache );
|
|
m_pTable = NULL;
|
|
return( hResult );
|
|
}
|
|
m_pTable->m_nRefCount++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_ASSERTE( m_pTable != NULL );
|
|
|
|
LeaveCriticalSection( &s_csCache );
|
|
|
|
return( S_OK );
|
|
}
|
|
|
|
STDMETHODIMP CDitherToRGB8::SetEventSink( IImageDecodeEventSink* pEventSink )
|
|
{
|
|
if( pEventSink == NULL )
|
|
{
|
|
return( E_INVALIDARG );
|
|
}
|
|
|
|
m_pEventSink = pEventSink;
|
|
|
|
return( S_OK );
|
|
}
|
|
|
|
HRESULT CDitherToRGB8::ConvertBlock( RECT* pBounds )
|
|
{
|
|
HRESULT hResult;
|
|
void* pSrcBits;
|
|
void* pDestBits;
|
|
LONG nSrcPitch;
|
|
LONG nDestPitch;
|
|
DDSURFACEDESC ddsd;
|
|
|
|
_ASSERTE( pBounds->left == 0 );
|
|
_ASSERTE( pBounds->right == LONG( m_nWidth ) );
|
|
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
hResult = m_pSurface->Lock(pBounds, &ddsd, 0, 0);
|
|
if (FAILED(hResult))
|
|
return hResult;
|
|
|
|
pSrcBits = ddsd.lpSurface;
|
|
nSrcPitch = ddsd.lPitch;
|
|
|
|
hResult = m_pDestSurface->Lock(pBounds, &ddsd, 0, 0);
|
|
if (FAILED(hResult))
|
|
{
|
|
m_pSurface->Unlock(pSrcBits);
|
|
return hResult;
|
|
}
|
|
|
|
pDestBits = ddsd.lpSurface;
|
|
nDestPitch = ddsd.lPitch;
|
|
|
|
switch( m_eSrcFormat )
|
|
{
|
|
case RGB24:
|
|
Convert24to8(LPBYTE(pDestBits), LPBYTE(pSrcBits), nDestPitch,
|
|
nSrcPitch, m_pTable->m_abInverseMap, pBounds->left,
|
|
pBounds->right-pBounds->left, pBounds->top,
|
|
pBounds->bottom-pBounds->top );
|
|
break;
|
|
|
|
case RGB8:
|
|
Convert8to8( LPBYTE( pDestBits ), LPBYTE( pSrcBits ), nDestPitch,
|
|
nSrcPitch, m_argbSrcColors, m_pTable->m_abInverseMap, pBounds->left,
|
|
pBounds->right-pBounds->left, pBounds->top,
|
|
pBounds->bottom-pBounds->top );
|
|
break;
|
|
|
|
default:
|
|
return E_FAIL;
|
|
break;
|
|
}
|
|
|
|
m_pDestSurface->Unlock(pDestBits);
|
|
m_pSurface->Unlock(pSrcBits);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CDitherToRGB8::DitherBand( RECT* pBounds )
|
|
{
|
|
HRESULT hResult;
|
|
void* pSrcBits;
|
|
void* pDestBits;
|
|
LONG nSrcPitch;
|
|
LONG nDestPitch;
|
|
LONG lDestTrans = -1;
|
|
LONG lSrcTrans = -1;
|
|
DDSURFACEDESC ddsd;
|
|
DDCOLORKEY ddColorKey;
|
|
|
|
_ASSERTE( pBounds->left == 0 );
|
|
_ASSERTE( pBounds->right == LONG( m_nWidth ) );
|
|
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
hResult = m_pSurface->Lock(pBounds, &ddsd, 0, 0);
|
|
if (FAILED(hResult))
|
|
return hResult;
|
|
|
|
pSrcBits = ddsd.lpSurface;
|
|
nSrcPitch = ddsd.lPitch;
|
|
|
|
hResult = m_pDestSurface->Lock(pBounds, &ddsd, 0, 0);
|
|
if (FAILED(hResult))
|
|
{
|
|
m_pSurface->Unlock(pSrcBits);
|
|
return hResult;
|
|
}
|
|
|
|
pDestBits = ddsd.lpSurface;
|
|
nDestPitch = ddsd.lPitch;
|
|
|
|
switch (m_eSrcFormat)
|
|
{
|
|
case RGB24:
|
|
Dith24to8(LPBYTE(pDestBits), LPBYTE(pSrcBits), nDestPitch,
|
|
nSrcPitch, m_pTable->m_argbColors, m_pTable->m_abInverseMap,
|
|
m_pErrBuf1, m_pErrBuf2, pBounds->left, pBounds->right-pBounds->left,
|
|
pBounds->top, pBounds->bottom-pBounds->top);
|
|
break;
|
|
|
|
case RGB8:
|
|
if (SUCCEEDED(m_pSurface->GetColorKey(DDCKEY_SRCBLT, &ddColorKey)))
|
|
lSrcTrans = ddColorKey.dwColorSpaceLowValue;
|
|
|
|
if (SUCCEEDED(m_pDestSurface->GetColorKey(DDCKEY_SRCBLT, &ddColorKey)))
|
|
lDestTrans = ddColorKey.dwColorSpaceLowValue;
|
|
|
|
// preserve the transparent index if necessary
|
|
if (lSrcTrans >= 0 && lDestTrans == -1)
|
|
{
|
|
lDestTrans = lSrcTrans;
|
|
}
|
|
|
|
if (lSrcTrans == -1 || lDestTrans == -1)
|
|
{
|
|
Dith8to8(LPBYTE(pDestBits), LPBYTE(pSrcBits), nDestPitch, nSrcPitch,
|
|
m_argbSrcColors, m_pTable->m_argbColors, m_pTable->m_abInverseMap,
|
|
m_pErrBuf1, m_pErrBuf2, pBounds->left, pBounds->right-pBounds->left,
|
|
pBounds->top, pBounds->bottom-pBounds->top);
|
|
}
|
|
else
|
|
{
|
|
Dith8to8t(LPBYTE(pDestBits), LPBYTE(pSrcBits), nDestPitch, nSrcPitch,
|
|
m_argbSrcColors, m_pTable->m_argbColors, m_pTable->m_abInverseMap,
|
|
m_pErrBuf1, m_pErrBuf2, pBounds->left, pBounds->right-pBounds->left,
|
|
pBounds->top, pBounds->bottom-pBounds->top, (BYTE)lDestTrans, (BYTE)lSrcTrans);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return E_FAIL;
|
|
}
|
|
|
|
m_pDestSurface->Unlock(pDestBits);
|
|
m_pSurface->Unlock(pSrcBits);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CDitherToRGB8::DitherFull()
|
|
{
|
|
HRESULT hResult;
|
|
RECT rect;
|
|
|
|
rect.left = 0;
|
|
rect.top = 0;
|
|
rect.right = m_nWidth;
|
|
rect.bottom = m_nHeight;
|
|
|
|
hResult = DitherBand(&rect);
|
|
if (FAILED(hResult))
|
|
return hResult;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT DitherTo8( BYTE * pDestBits, LONG nDestPitch,
|
|
BYTE * pSrcBits, LONG nSrcPitch, REFGUID bfidSrc,
|
|
RGBQUAD * prgbDestColors, RGBQUAD * prgbSrcColors,
|
|
BYTE * pbDestInvMap,
|
|
LONG x, LONG y, LONG cx, LONG cy,
|
|
LONG lDestTrans, LONG lSrcTrans)
|
|
{
|
|
ERRBUF* m_pErrBuf;
|
|
ERRBUF* m_pErrBuf1;
|
|
ERRBUF* m_pErrBuf2;
|
|
|
|
// StartCAPAll();
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
m_pErrBuf = new ERRBUF[(cx+2)*2];
|
|
if (m_pErrBuf == NULL)
|
|
{
|
|
return( E_OUTOFMEMORY );
|
|
}
|
|
|
|
m_pErrBuf1 = &m_pErrBuf[1];
|
|
m_pErrBuf2 = &m_pErrBuf[cx+3];
|
|
|
|
memset(m_pErrBuf, 0, sizeof( ERRBUF )*(cx+2)*2);
|
|
|
|
if (bfidSrc == BFID_RGB_24)
|
|
{
|
|
Dith24to8( pDestBits, pSrcBits, nDestPitch, nSrcPitch,
|
|
prgbDestColors, pbDestInvMap,
|
|
m_pErrBuf1, m_pErrBuf2, x, cx, y, cy );
|
|
}
|
|
else if (bfidSrc == BFID_RGB_8)
|
|
{
|
|
if (lDestTrans == -1 || lSrcTrans == -1)
|
|
{
|
|
Dith8to8( pDestBits, pSrcBits, nDestPitch, nSrcPitch,
|
|
prgbSrcColors, prgbDestColors, pbDestInvMap,
|
|
m_pErrBuf1, m_pErrBuf2, x, cx, y, cy );
|
|
}
|
|
else
|
|
{
|
|
Dith8to8t( pDestBits, pSrcBits, nDestPitch, nSrcPitch,
|
|
prgbSrcColors, prgbDestColors, pbDestInvMap,
|
|
m_pErrBuf1, m_pErrBuf2, x, cx, y, cy, (BYTE)lDestTrans, (BYTE)lSrcTrans );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
delete m_pErrBuf;
|
|
|
|
// StopCAPAll();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|