[+] dia get type

[+] dia get location
[+] dia print to string

git-svn-id: https://pykd.svn.codeplex.com/svn@69841 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2011-09-18 16:50:42 +00:00 committed by Mikhail I. Izmestev
parent 479f2745f6
commit f241ea851b
5 changed files with 439 additions and 92 deletions

View File

@ -3,7 +3,6 @@
#include <dbgeng.h> #include <dbgeng.h>
#include <dia2.h> #include <dia2.h>
#include <cvconst.h>
#include "module.h" #include "module.h"
#include "diawrapper.h" #include "diawrapper.h"
@ -98,13 +97,19 @@ BOOST_PYTHON_MODULE( pykd )
"Retrieves the children of the symbol" ) "Retrieves the children of the symbol" )
.def( "size", &pyDia::Symbol::getSize, .def( "size", &pyDia::Symbol::getSize,
"Retrieves the number of bits or bytes of memory used by the object represented by this symbol" ) "Retrieves the number of bits or bytes of memory used by the object represented by this symbol" )
//.def( "getName", &pyDia::Symbol::getName, .def( "name", &pyDia::Symbol::getName,
// "Retrieves the name of the symbol" ) "Retrieves the name of the symbol" )
//.def( "getType", &pyDia::Symbol::getType, .def( "type", &pyDia::Symbol::getType,
// "Retrieves the symbol that represents the type for this symbol" ) "Retrieves the symbol that represents the type for this symbol" )
.def( "getSymTag", &pyDia::Symbol::getSymTag, .def( "rva", &pyDia::Symbol::getRva,
"Retrieves the relative virtual address (RVA) of the location")
.def( "symTag", &pyDia::Symbol::getSymTag,
"Retrieves the symbol type classifier: SymTagXxx" ) "Retrieves the symbol type classifier: SymTagXxx" )
//__str__ &pyDia::Symbol::print .def( "locType", &pyDia::Symbol::getLocType,
"Retrieves the location type of a data symbol: LocIsXxx" )
.def( "value", &pyDia::Symbol::getValue,
"Retrieves the value of a constant")
.def( "__str__", &pyDia::Symbol::print)
.def("__getattr__", &pyDia::Symbol::getChildByName) .def("__getattr__", &pyDia::Symbol::getChildByName)
.def("__len__", &pyDia::Symbol::getChildCount ) .def("__len__", &pyDia::Symbol::getChildCount )
.def("__getitem__", &pyDia::Symbol::getChildByIndex); .def("__getitem__", &pyDia::Symbol::getChildByIndex);
@ -156,6 +161,19 @@ BOOST_PYTHON_MODULE( pykd )
DEF_PY_CONST_ULONG(nsRegularExpression); DEF_PY_CONST_ULONG(nsRegularExpression);
DEF_PY_CONST_ULONG(nsCaseInRegularExpression); DEF_PY_CONST_ULONG(nsCaseInRegularExpression);
// location type
DEF_PY_CONST_ULONG(LocIsNull);
DEF_PY_CONST_ULONG(LocIsStatic);
DEF_PY_CONST_ULONG(LocIsTLS);
DEF_PY_CONST_ULONG(LocIsRegRel);
DEF_PY_CONST_ULONG(LocIsThisRel);
DEF_PY_CONST_ULONG(LocIsEnregistered);
DEF_PY_CONST_ULONG(LocIsBitField);
DEF_PY_CONST_ULONG(LocIsSlot);
DEF_PY_CONST_ULONG(LocIsIlRel);
DEF_PY_CONST_ULONG(LocInMetaData);
DEF_PY_CONST_ULONG(LocIsConstant);
// exception: // exception:
// base exception // base exception
python::class_<DbgException> dbgExceptionClass( "BaseException", python::class_<DbgException> dbgExceptionClass( "BaseException",

View File

@ -1,28 +1,77 @@
#include "stdafx.h" #include "stdafx.h"
#include <strstream>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include "diawrapper.h" #include "diawrapper.h"
#include "utils.h"
using namespace pykd;
namespace pyDia { namespace pyDia {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
PyObject *Exception::diaExceptTypeObject = NULL; PyObject *Exception::diaExceptTypeObject = NULL;
const std::string Exception::descPrefix("pyDia: "); const std::string Exception::descPrefix("pyDia: ");
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
const char *Symbol::symTagName[SymTagMax] = {
"Null",
"Exe",
"Compiland",
"CompilandDetails",
"CompilandEnv",
"Function",
"Block",
"Data",
"Annotation",
"Label",
"PublicSymbol",
"UDT",
"Enum",
"FunctionType",
"PointerType",
"ArrayType",
"BaseType",
"Typedef",
"BaseClass",
"Friend",
"FunctionArgType",
"FuncDebugStart",
"FuncDebugEnd",
"UsingNamespace",
"VTableShape",
"VTable",
"Custom",
"Thunk",
"CustomType",
"ManagedType",
"Dimension"
};
const char *Symbol::locTypeName[LocTypeMax] = {
"Null",
"Static",
"TLS",
"RegRel",
"ThisRel",
"Enregistered",
"BitField",
"Slot",
"IlRel",
"InMetaData",
"Constant"
};
////////////////////////////////////////////////////////////////////////////////
std::string Exception::makeFullDesc(const std::string &desc, HRESULT hres) std::string Exception::makeFullDesc(const std::string &desc, HRESULT hres)
{ {
std::strstream res; std::stringstream sstream;
res << descPrefix << desc << " failed" << std::endl; sstream << descPrefix << desc << " failed" << std::endl;
res << "Return value is 0x" << std::hex << hres; sstream << "Return value is 0x" << std::hex << hres;
PCHAR errMessage = NULL; PCHAR errMessage = NULL;
FormatMessageA( FormatMessageA(
@ -35,16 +84,16 @@ std::string Exception::makeFullDesc(const std::string &desc, HRESULT hres)
NULL); NULL);
if (errMessage) if (errMessage)
{ {
res << ":" << std::endl; sstream << ": " << std::endl;
res << errMessage; sstream << errMessage;
LocalFree(errMessage); LocalFree(errMessage);
} }
else else
{ {
res << std::endl; sstream << std::endl;
} }
return res.str(); return sstream.str();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -56,25 +105,6 @@ void Exception::exceptionTranslate( const Exception &e )
PyErr_SetObject( diaExceptTypeObject, pyExcept.ptr() ); PyErr_SetObject( diaExceptTypeObject, pyExcept.ptr() );
} }
////////////////////////////////////////////////////////////////////////////////
// Convert to OLESTR helper
////////////////////////////////////////////////////////////////////////////////
class toOleStr {
public:
toOleStr(const std::string &sz)
{
m_buf.resize( sz.size() + 1, L'\0' );
::MultiByteToWideChar( CP_ACP, 0, sz.c_str(), sz.size(), &m_buf[0], m_buf.size() );
}
operator const OLECHAR *() const {
return m_buf.empty() ? NULL : &m_buf[0];
}
private:
std::vector<OLECHAR> m_buf;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
python::list Symbol::findChildrenImpl( python::list Symbol::findChildrenImpl(
@ -85,19 +115,19 @@ python::list Symbol::findChildrenImpl(
{ {
throwIfNull(__FUNCTION__); throwIfNull(__FUNCTION__);
CComPtr< IDiaEnumSymbols > symbols; DiaEnumSymbolsPtr symbols;
HRESULT hres = HRESULT hres =
m_symbol->findChildren( m_symbol->findChildren(
static_cast<enum SymTagEnum>(symTag), static_cast<enum SymTagEnum>(symTag),
toOleStr(name), toWStr(name),
nameCmpFlags, nameCmpFlags,
&symbols); &symbols);
if (FAILED(hres)) if (S_OK != hres)
throw Exception("Get list of children", hres); throw Exception("Call IDiaSymbol::findChildren", hres);
python::list childList; python::list childList;
CComPtr< IDiaSymbol > child; DiaSymbolPtr child;
ULONG celt; ULONG celt;
while ( SUCCEEDED(symbols->Next(1, &child, &celt)) && (celt == 1) ) while ( SUCCEEDED(symbols->Next(1, &child, &celt)) && (celt == 1) )
childList.append( Symbol(child) ); childList.append( Symbol(child) );
@ -113,57 +143,162 @@ ULONGLONG Symbol::getSize()
ULONGLONG retValue; ULONGLONG retValue;
HRESULT hres = m_symbol->get_length(&retValue); HRESULT hres = m_symbol->get_length(&retValue);
if (FAILED(hres)) if (S_OK != hres)
throw Exception("Get length", hres); throw Exception("Call IDiaSymbol::get_length", hres);
return retValue; return retValue;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
std::string Symbol::getName()
{
throwIfNull(__FUNCTION__);
autoBstr bstrName;
HRESULT hres = m_symbol->get_name(&bstrName);
if (S_OK != hres)
throw Exception("Call IDiaSymbol::get_name", hres);
return bstrName.asStr();
}
////////////////////////////////////////////////////////////////////////////////
python::object Symbol::getType()
{
throwIfNull(__FUNCTION__);
DiaSymbolPtr _type;
HRESULT hres = m_symbol->get_type(&_type);
if (S_OK != hres)
throw Exception("Call IDiaSymbol::get_type", hres);
return python::object( Symbol(_type) );
}
////////////////////////////////////////////////////////////////////////////////
ULONG Symbol::getSymTag() ULONG Symbol::getSymTag()
{ {
throwIfNull(__FUNCTION__); throwIfNull(__FUNCTION__);
DWORD retValue; DWORD retValue;
HRESULT hres = m_symbol->get_symTag(&retValue); HRESULT hres = m_symbol->get_symTag(&retValue);
if (FAILED(hres)) if (S_OK != hres)
throw Exception("Get symbol type", hres); throw Exception("Call IDiaSymbol::get_symTag", hres);
return retValue; return retValue;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ULONG Symbol::getRva()
{
throwIfNull(__FUNCTION__);
DWORD retValue;
HRESULT hres = m_symbol->get_relativeVirtualAddress(&retValue);
if (S_OK != hres)
throw Exception("Call IDiaSymbol::get_relativeVirtualAddress", hres);
return retValue;
}
////////////////////////////////////////////////////////////////////////////////
ULONG Symbol::getLocType()
{
throwIfNull(__FUNCTION__);
DWORD retValue;
HRESULT hres = m_symbol->get_locationType(&retValue);
if (S_OK != hres)
throw Exception("Call IDiaSymbol::get_locationType", hres);
return retValue;
}
////////////////////////////////////////////////////////////////////////////////
python::object Symbol::getValue()
{
throwIfNull(__FUNCTION__);
VARIANT variant = { VT_EMPTY };
HRESULT hres = m_symbol->get_value(&variant);
if (S_OK != hres)
throw Exception("Call IDiaSymbol::get_value", hres);
switch (variant.vt)
{
case VT_I1:
case VT_UI1:
return python::object( static_cast<ULONG>(variant.bVal) );
case VT_BOOL:
return python::object( static_cast<bool>(!!variant.iVal) );
case VT_I2:
case VT_UI2:
return python::object( static_cast<ULONG>(variant.iVal) );
case VT_I4:
case VT_UI4:
case VT_INT:
case VT_UINT:
case VT_ERROR:
case VT_HRESULT:
return python::object( variant.lVal );
case VT_I8:
case VT_UI8:
return python::object( variant.llVal );
case VT_R4:
return python::object( variant.fltVal );
case VT_R8:
return python::object( variant.dblVal );
case VT_BSTR:
return python::object( autoBstr::asStr(variant.bstrVal).c_str() );
}
throw Exception("Unknown value type");
}
////////////////////////////////////////////////////////////////////////////////
python::object Symbol::getChildByName(const std::string &_name) python::object Symbol::getChildByName(const std::string &_name)
{ {
throwIfNull(__FUNCTION__); throwIfNull(__FUNCTION__);
CComPtr< IDiaEnumSymbols > symbols; DiaEnumSymbolsPtr symbols;
HRESULT hres = HRESULT hres =
m_symbol->findChildren( m_symbol->findChildren(
SymTagNull, SymTagNull,
toOleStr(_name), toWStr(_name),
nsCaseSensitive, nsCaseSensitive,
&symbols); &symbols);
if (FAILED(hres)) if (S_OK != hres)
throw Exception("Get child by name", hres); throw Exception("Call IDiaSymbol::findChildren", hres);
LONG count; LONG count;
hres = symbols->get_Count(&count); hres = symbols->get_Count(&count);
if (FAILED(hres)) if (S_OK != hres)
throw Exception("Get count of children", hres); throw Exception("Call IDiaEnumSymbols::get_Count", hres);
if (!count) if (!count)
throw Exception(_name + " not found as children"); throw Exception(_name + " not found");
if (count != 1) if (count != 1)
throw Exception(_name + " is not unique"); throw Exception(_name + " is not unique");
CComPtr< IDiaSymbol > child; DiaSymbolPtr child;
hres = symbols->Item(0, &child); hres = symbols->Item(0, &child);
if (FAILED(hres)) if (S_OK != hres)
throw Exception("Build child object", hres); throw Exception("Call IDiaEnumSymbols::Item", hres);
return python::object( Symbol(child) ); return python::object( Symbol(child) );
} }
@ -174,20 +309,20 @@ ULONG Symbol::getChildCount()
{ {
throwIfNull(__FUNCTION__); throwIfNull(__FUNCTION__);
CComPtr< IDiaEnumSymbols > symbols; DiaEnumSymbolsPtr symbols;
HRESULT hres = HRESULT hres =
m_symbol->findChildren( m_symbol->findChildren(
SymTagNull, SymTagNull,
NULL, NULL,
nsCaseSensitive, nsCaseSensitive,
&symbols); &symbols);
if (FAILED(hres)) if (S_OK != hres)
throw Exception("Get child count", hres); throw Exception("Call IDiaSymbol::findChildren", hres);
LONG count; LONG count;
hres = symbols->get_Count(&count); hres = symbols->get_Count(&count);
if (FAILED(hres)) if (S_OK != hres)
throw Exception("Get count of count", hres); throw Exception("Call IDiaEnumSymbols::get_Count", hres);
return count; return count;
} }
@ -198,38 +333,135 @@ python::object Symbol::getChildByIndex(ULONG _index)
{ {
throwIfNull(__FUNCTION__); throwIfNull(__FUNCTION__);
CComPtr< IDiaEnumSymbols > symbols; DiaEnumSymbolsPtr symbols;
HRESULT hres = HRESULT hres =
m_symbol->findChildren( m_symbol->findChildren(
SymTagNull, SymTagNull,
NULL, NULL,
nsCaseSensitive, nsCaseSensitive,
&symbols); &symbols);
if (FAILED(hres)) if (S_OK != hres)
throw Exception("Get child by index", hres); throw Exception("Call IDiaSymbol::findChildren", hres);
LONG count; LONG count;
hres = symbols->get_Count(&count); hres = symbols->get_Count(&count);
if (FAILED(hres)) if (S_OK != hres)
throw Exception("Get count of children", hres); throw Exception("Call IDiaEnumSymbols::get_Count", hres);
if (LONG(_index) >= count) if (LONG(_index) >= count)
throw Exception("Attempt to access non-existing element: index overflow"); throw Exception("Attempt to access non-existing element by index");
CComPtr< IDiaSymbol > child; DiaSymbolPtr child;
hres = symbols->Item(_index, &child); hres = symbols->Item(_index, &child);
if (FAILED(hres)) if (S_OK != hres)
throw Exception("Build child object", hres); throw Exception("Call IDiaEnumSymbols::Item", hres);
return python::object( Symbol(child) ); return python::object( Symbol(child) );
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
std::string Symbol::print()
{
std::stringstream sstream;
if (m_symbol)
{
DWORD dwValue;
autoBstr bstrValue;
VARIANT vtValue = { VT_EMPTY };
sstream << "symTag: ";
HRESULT hres = m_symbol->get_symTag(&dwValue);
if ((S_OK == hres) && dwValue < _countof(symTagName))
sstream << symTagName[dwValue];
else
sstream << "<unknown>";
sstream << ", ";
hres = m_symbol->get_name(&bstrValue);
if (S_OK == hres)
sstream << "\"" << bstrValue.asStr().c_str() << "\"";
else
sstream << "<no-name>";
bstrValue.free();
hres = m_symbol->get_locationType(&dwValue);
if ((S_OK == hres) && dwValue < _countof(locTypeName))
{
sstream << std::endl;
sstream << "Location: " << locTypeName[dwValue];
if (dwValue == LocIsStatic)
{
hres = m_symbol->get_relativeVirtualAddress(&dwValue);
if (S_OK == hres)
sstream << ", RVA: 0x" << std::hex << dwValue;
}
}
hres = m_symbol->get_value(&vtValue);
if (S_OK == hres)
{
switch (vtValue.vt)
{
case VT_I1:
case VT_UI1:
sstream << std::endl << "Value is ";
sstream << std::hex << "0x" << vtValue.bVal;
break;
case VT_BOOL:
sstream << std::endl << "Value is ";
sstream << vtValue.iVal ? "True" : "False";
break;
case VT_I2:
case VT_UI2:
sstream << std::endl << "Value is ";
sstream << std::hex << "0x" << vtValue.iVal;
break;
case VT_I4:
case VT_UI4:
case VT_INT:
case VT_UINT:
case VT_ERROR:
case VT_HRESULT:
sstream << std::endl << "Value is ";
sstream << std::hex << "0x" << vtValue.lVal;
break;
case VT_I8:
case VT_UI8:
sstream << std::endl << "Value is ";
sstream << std::hex << "0x" << vtValue.llVal;
break;
case VT_R4:
sstream << std::endl << "Value is ";
sstream << vtValue.fltVal;
break;
case VT_R8:
sstream << std::endl << "Value is ";
sstream << vtValue.dblVal;
break;
case VT_BSTR:
sstream << std::endl << "Value is ";
sstream << "\"" << autoBstr::asStr(vtValue.bstrVal).c_str() << "\"";
break;
}
}
}
return sstream.str();
}
////////////////////////////////////////////////////////////////////////////////
GlobalScope::GlobalScope( GlobalScope::GlobalScope(
__inout CComPtr< IDiaDataSource > &_scope, __inout DiaDataSourcePtr &_scope,
__inout CComPtr< IDiaSession > &_session, __inout DiaSessionPtr &_session,
__inout CComPtr< IDiaSymbol > &_globalScope __inout DiaSymbolPtr &_globalScope
) : Symbol(_globalScope) ) : Symbol(_globalScope)
, m_source( _scope.Detach() ) , m_source( _scope.Detach() )
, m_session( _session.Detach() ) , m_session( _session.Detach() )
@ -240,26 +472,26 @@ GlobalScope::GlobalScope(
python::object GlobalScope::openPdb(const std::string &filePath) python::object GlobalScope::openPdb(const std::string &filePath)
{ {
CComPtr< IDiaDataSource > _scope; DiaDataSourcePtr _scope;
HRESULT hres = HRESULT hres =
_scope.CoCreateInstance(__uuidof(DiaSource), NULL, CLSCTX_INPROC_SERVER); _scope.CoCreateInstance(__uuidof(DiaSource), NULL, CLSCTX_INPROC_SERVER);
if ( FAILED(hres) ) if ( S_OK != hres )
throw Exception("Create scope instance", hres); throw Exception("Call ::CoCreateInstance", hres);
hres = _scope->loadDataFromPdb( toOleStr(filePath) ); hres = _scope->loadDataFromPdb( toWStr(filePath) );
if ( FAILED(hres) ) if ( S_OK != hres )
throw Exception("Load pdb file", hres); throw Exception("Call IDiaDataSource::loadDataFromPdb", hres);
CComPtr< IDiaSession > _session; DiaSessionPtr _session;
hres = _scope->openSession(&_session); hres = _scope->openSession(&_session);
if ( FAILED(hres) ) if ( S_OK != hres )
throw Exception("Open session for querying symbols", hres); throw Exception("Call IDiaDataSource::openSession", hres);
CComPtr< IDiaSymbol > _globalScope; DiaSymbolPtr _globalScope;
hres = _session->get_globalScope(&_globalScope); hres = _session->get_globalScope(&_globalScope);
if ( FAILED(hres) ) if ( S_OK != hres )
throw Exception("Retrieves a reference to the global scope", hres); throw Exception("Call IDiaSymbol::get_globalScope", hres);
return python::object(GlobalScope(_scope, _session, _globalScope)); return python::object(GlobalScope(_scope, _session, _globalScope));
} }

View File

@ -1,9 +1,16 @@
#pragma once #pragma once
#include <cvconst.h>
#include "dbgexcept.h" #include "dbgexcept.h"
namespace pyDia { namespace pyDia {
typedef CComPtr< IDiaSymbol > DiaSymbolPtr;
typedef CComPtr< IDiaEnumSymbols > DiaEnumSymbolsPtr;
typedef CComPtr< IDiaDataSource > DiaDataSourcePtr;
typedef CComPtr< IDiaSession > DiaSessionPtr;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// DIA Exceptions // DIA Exceptions
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -63,13 +70,18 @@ public:
} }
ULONGLONG getSize(); ULONGLONG getSize();
std::string getName();
python::object getType();
ULONG getSymTag(); ULONG getSymTag();
ULONG getRva();
ULONG getLocType();
python::object getValue();
python::object getChildByName(const std::string &_name); python::object getChildByName(const std::string &_name);
ULONG getChildCount(); ULONG getChildCount();
python::object getChildByIndex(ULONG _index); python::object getChildByIndex(ULONG _index);
std::string print();
protected: protected:
void throwIfNull(const char *desc) void throwIfNull(const char *desc)
@ -78,11 +90,14 @@ protected:
throw Exception(std::string(desc) + " failed, object not preinitialized"); throw Exception(std::string(desc) + " failed, object not preinitialized");
} }
Symbol(__inout CComPtr< IDiaSymbol > &_symbol) { Symbol(__inout DiaSymbolPtr &_symbol) {
m_symbol = _symbol.Detach(); m_symbol = _symbol.Detach();
} }
CComPtr< IDiaSymbol > m_symbol; static const char *symTagName[SymTagMax];
static const char *locTypeName[LocTypeMax];
DiaSymbolPtr m_symbol;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -98,13 +113,13 @@ public:
private: private:
GlobalScope( GlobalScope(
__inout CComPtr< IDiaDataSource > &_scope, __inout DiaDataSourcePtr &_scope,
__inout CComPtr< IDiaSession > &_session, __inout DiaSessionPtr &_session,
__inout CComPtr< IDiaSymbol > &_globalScope __inout DiaSymbolPtr &_globalScope
); );
CComPtr< IDiaDataSource > m_source; DiaDataSourcePtr m_source;
CComPtr< IDiaSession > m_session; DiaSessionPtr m_session;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -439,6 +439,10 @@
RelativePath=".\stdafx.h" RelativePath=".\stdafx.h"
> >
</File> </File>
<File
RelativePath=".\utils.h"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Resource Files" Name="Resource Files"

78
pykd/utils.h Normal file
View File

@ -0,0 +1,78 @@
#pragma once
////////////////////////////////////////////////////////////////////////////////
// std::string -> const WCHAR *
////////////////////////////////////////////////////////////////////////////////
class toWStr {
public:
toWStr(const std::string &sz)
{
m_buf.resize( sz.size() + 1, L'\0' );
::MultiByteToWideChar( CP_ACP, 0, sz.c_str(), sz.size(), &m_buf[0], m_buf.size() );
}
operator const WCHAR *() const {
return m_buf.empty() ? NULL : &m_buf[0];
}
private:
std::vector<WCHAR> m_buf;
};
////////////////////////////////////////////////////////////////////////////////
// BSTR wrapper
////////////////////////////////////////////////////////////////////////////////
class autoBstr {
public:
autoBstr() : m_bstr(NULL) {}
~autoBstr() {
free();
}
void free()
{
if (m_bstr)
{
SysFreeString(m_bstr);
m_bstr = NULL;
}
}
BSTR *operator &() {
return &m_bstr;
}
operator BSTR() const {
return m_bstr;
}
std::string asStr() const
{
return asStr(m_bstr);
}
static std::string asStr(BSTR bstr)
{
if (!bstr)
return "";
const int chars = static_cast<int>( wcslen(bstr) );
if (!chars)
return "";
std::string ret;
ret.resize(chars + 1, '\0');
::WideCharToMultiByte(
CP_ACP,
0,
bstr,
chars,
&ret[0],
ret.size(),
NULL,
NULL);
return ret;
}
private:
BSTR m_bstr;
};