WindowsXP-SP1/admin/pchealth/core/mpc_common/utils_hglobal.cpp
2020-09-30 16:53:49 +02:00

353 lines
6.5 KiB
C++

/******************************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
Utils_HGLOBAL.cpp
Abstract:
This file contains the implementation of various utility functions.
Revision History:
Davide Massarenti (Dmassare) 04/17/99
created
******************************************************************************/
#include "stdafx.h"
////////////////////////////////////////////////////////////////////////////////
MPC::CComHGLOBAL::CComHGLOBAL()
{
m_hg = NULL; // HGLOBAL m_hg;
m_ptr = NULL; // mutable LPVOID m_ptr;
m_dwLock = 0; // mutable DWORD m_dwLock;
}
MPC::CComHGLOBAL::~CComHGLOBAL()
{
Release();
}
MPC::CComHGLOBAL::CComHGLOBAL( /*[in]*/ const CComHGLOBAL& chg )
{
m_hg = NULL; // HGLOBAL m_hg;
m_ptr = NULL; // mutable LPVOID m_ptr;
m_dwLock = 0; // mutable DWORD m_dwLock;
*this = chg;
}
MPC::CComHGLOBAL& MPC::CComHGLOBAL::operator=( /*[in]*/ const CComHGLOBAL& chg )
{
return *this = chg.m_hg;
}
MPC::CComHGLOBAL& MPC::CComHGLOBAL::operator=( /*[in]*/ HGLOBAL hg )
{
(void)Copy( hg );
return *this;
}
void MPC::CComHGLOBAL::Attach( /*[in]*/ HGLOBAL hg )
{
Release();
m_hg = hg;
}
HGLOBAL MPC::CComHGLOBAL::Detach()
{
HGLOBAL hg;
while(m_ptr) Unlock();
hg = m_hg; m_hg = NULL;
return hg;
}
////////////////////
HRESULT MPC::CComHGLOBAL::New( /*[in]*/ UINT uFlags, /*[in]*/ DWORD dwSize )
{
__MPC_FUNC_ENTRY( COMMONID, "MPC::CComHGLOBAL::New" );
HRESULT hr;
Release();
if(dwSize)
{
__MPC_EXIT_IF_ALLOC_FAILS(hr, m_hg, ::GlobalAlloc( uFlags, dwSize ));
}
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr);
}
void MPC::CComHGLOBAL::Release()
{
Unlock();
if(m_hg)
{
::GlobalFree( m_hg );
m_hg = NULL;
}
}
LPVOID MPC::CComHGLOBAL::Lock() const
{
if(m_ptr == NULL)
{
if(m_hg) m_ptr = ::GlobalLock( m_hg );
}
m_dwLock++;
return m_ptr;
}
void MPC::CComHGLOBAL::Unlock() const
{
if(m_ptr)
{
if(--m_dwLock == 0)
{
::GlobalUnlock( m_hg );
m_ptr = NULL;
}
}
}
////////////////////
HGLOBAL MPC::CComHGLOBAL::Get () const { return m_hg; }
HGLOBAL MPC::CComHGLOBAL::GetRef () { Unlock(); return m_hg; }
HGLOBAL MPC::CComHGLOBAL::GetPointer() { Unlock(); return &m_hg; }
DWORD MPC::CComHGLOBAL::Size() const { return m_hg ? ::GlobalSize( m_hg ) : 0; }
////////////////////
HRESULT MPC::CComHGLOBAL::Copy( /*[in]*/ HGLOBAL hg, /*[in]*/ DWORD dwMaxSize )
{
__MPC_FUNC_ENTRY( COMMONID, "MPC::CComHGLOBAL::Copy" );
HRESULT hr;
Release();
if(hg)
{
DWORD dwSize = ::GlobalSize( hg );
LPVOID pIn;
LPVOID pOut;
if(dwMaxSize != 0xFFFFFFFF &&
dwMaxSize < dwSize )
{
dwSize = dwMaxSize;
}
__MPC_EXIT_IF_ALLOC_FAILS(hr, m_hg, ::GlobalAlloc( GMEM_SHARE | GMEM_MOVEABLE, dwSize ));
if((pIn = ::GlobalLock( hg )))
{
if((pOut = ::GlobalLock( m_hg )))
{
::CopyMemory( pOut, pIn, dwSize );
::GlobalUnlock( m_hg );
}
::GlobalUnlock( hg );
}
}
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr);
}
//////////////////////////////////////////////////
HRESULT MPC::CComHGLOBAL::CopyFromStream( /*[in ]*/ IStream* val )
{
__MPC_FUNC_ENTRY( COMMONID, "MPC::CComHGLOBAL::FromStream" );
HRESULT hr;
CComPtr<IStream> tmp;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_NOTNULL(val);
__MPC_PARAMCHECK_END();
__MPC_EXIT_IF_METHOD_FAILS(hr, New( GMEM_SHARE | GMEM_MOVEABLE, 0 ));
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CreateStreamOnHGlobal( m_hg, FALSE, &tmp ));
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::BaseStream::TransferData( val, tmp ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr);
}
HRESULT MPC::CComHGLOBAL::CopyToStream( /*[out]*/ IStream* val )
{
__MPC_FUNC_ENTRY( COMMONID, "MPC::CComHGLOBAL::ToStream" );
HRESULT hr;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_NOTNULL(val);
__MPC_PARAMCHECK_END();
if(m_hg)
{
LARGE_INTEGER li;
DWORD dwWritten = 0;
DWORD dwSize = ::GlobalSize( m_hg );
LPVOID ptr;
if((ptr = ::GlobalLock( m_hg )))
{
hr = val->Write( ptr, dwSize, &dwWritten );
::GlobalUnlock( m_hg );
}
else
{
hr = E_FAIL;
}
if(FAILED(hr)) __MPC_FUNC_LEAVE;
if(dwWritten != dwSize)
{
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_HANDLE_DISK_FULL );
}
}
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr);
}
HRESULT MPC::CComHGLOBAL::CloneAsStream( /*[out]*/ IStream* *pVal )
{
__MPC_FUNC_ENTRY( COMMONID, "MPC::CComHGLOBAL::CloneAsStream" );
HRESULT hr;
CComHGLOBAL tmp;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_POINTER_AND_SET(pVal,NULL);
__MPC_PARAMCHECK_END();
__MPC_EXIT_IF_METHOD_FAILS(hr, tmp.Copy( m_hg ));
__MPC_EXIT_IF_METHOD_FAILS(hr, tmp.DetachAsStream( pVal ));
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr);
}
HRESULT MPC::CComHGLOBAL::DetachAsStream( /*[out]*/ IStream* *pVal )
{
__MPC_FUNC_ENTRY( COMMONID, "MPC::CComHGLOBAL::DetachAsStream" );
HRESULT hr;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_POINTER_AND_SET(pVal,NULL);
__MPC_PARAMCHECK_END();
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CreateStreamOnHGlobal( m_hg, TRUE, pVal ));
(void)Detach();
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr);
}
HRESULT MPC::CComHGLOBAL::GetAsStream( /*[out]*/ IStream* *pVal, /*[in]*/ bool fClone )
{
__MPC_FUNC_ENTRY( COMMONID, "MPC::CComHGLOBAL::GetAsStream" );
HRESULT hr;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_POINTER_AND_SET(pVal,NULL);
__MPC_PARAMCHECK_END();
if(fClone)
{
CComHGLOBAL h = *this;
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CreateStreamOnHGlobal( h.Get(), TRUE, pVal ));
(void)h.Detach(); // Detach AFTER the stream has been created, to avoid leaks...
}
else
{
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CreateStreamOnHGlobal( m_hg, FALSE, pVal ));
if(!m_hg)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, ::GetHGlobalFromStream( *pVal, &m_hg ));
}
}
hr = S_OK;
__MPC_FUNC_CLEANUP;
__MPC_FUNC_EXIT(hr);
}
HRESULT MPC::CComHGLOBAL::NewStream( /*[out]*/ IStream* *pVal )
{
Release();
return GetAsStream( pVal, /*fClone*/false );
}