Invalid null pointer when using _bstr_t - c++

I have a COM DLL that I am developing and I am running into a few issues. I have a try catch around a block of code and in the catch I get a _bstr_t from the exception. What I wanted to do was catch that exception and print it out to a string, however, it is throwing an Invalid null pointer error at me when that exception gets thrown. I tried looking at the MSDN on how to check for a null pointer, but it doesn't seem like it is working. I can't really debug the error because this is on a client machine and when trying to output the information I get this error.
catch(const _com_error& ex)
{
::OutputDebugStringW(ex.Description());
_variant_t ret;
std::string str = "#N/A ExcelException: ";
_bstr_t desc = ex.Description();
if(!desc || desc.GetBSTR() == L"")
{
str += ConvertBSTRToMBS(desc);
}
ret.SetString(str.c_str());
*Result = ret.Detach();
}
std::string ConvertBSTRToMBS(_bstr_t bstr)
{
std::string converted((char *)bstr);
return converted;
}

Due to a mistake in if condition, ConvertBSTRToMBS is called only when bstr is null.
Correct it as follows
if(!!desc && desc.length() != 0)
{
str += ConvertBSTRToMBS(desc);
}
The strange !!desc expression means !(desc.operator!()).
_bstr_t::operator! returns true if BSTR is null, therefore you have to negate it to check for non-null.

Related

Bad cast exception on poco-library when I tried to cast Int64

I wrote some code for parse JSON string.
I got "Bad Cast Exception" sometimes.
In My JSON string 1. 2. don't raise exception and 3. 4. raise exception.
A difference between two group is that 1. 2.'s BCodeW is in range long and 3. 4.'s BCodeW is in range Int64.
Why the casting raise the exception ?
I wrote some guard code for Bad Cast Exception but I wanna know the reason of exception.
Thanks for reading.
my environment is below.
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11)
poco-1.6.0 (using Poco::JSON)
CentOS release 6.6 (Final)
My JSON string example below.
{"y":37.56376,"x":126.97287,"poiY":37.563686111111,"poiX":126.97302222222,"jibunY":37.563805555556,"jibunX":126.97285833333,"BCodeW":1114016700,"poi":"...","jibun":"..."}
{"y":37.59771,"x":127.041493,"poiY":37.597605555556,"poiX":127.041725,"jibunY":37.597547222222,"jibunX":127.04176666667,"BCodeW":1129013600,"poi":"...","jibun":"..."}
{"y":36.760035,"x":127.250362,"poiY":36.759905555556,"poiX":127.25036111111,"jibunY":36.760119444444,"jibunX":127.25040833333,"BCodeW":4413125029,"poi":"...","jibun":"..."}
{"y":36.129513,"x":128.34381,"poiY":36.128672222222,"poiX":128.34373888889,"jibunY":36.129738888889,"jibunX":128.34425833333,"BCodeW":4719010200,"poi":"...","jibun":"..."}
My Code is below.
bool CUBIUtils::ParseAddressResult( llong& _BCodeW, char* _szPOI, char* _szJibun, char* _szAPIResult )
{
JSON::Parser parser;
try
{
JSON::Object::Ptr _object = parser.parse(_szAPIResult).extract<JSON::Object::Ptr>();
if ( NULL == _object)
{
formatlog( LOG_ERROR, "JSON parsing failed");
return false;
}
formatlog( LOG_DEBUG, "CUBIUtils::%s(%d) AddrSrc: %s", __func__, __LINE__, _szAPIResult);
_BCodeW = 0;
try
{
_BCodeW = _object->get("BCodeW").extract<Int64>();
}
catch(exception &_e)
{
_BCodeW = _object->get("BCodeW").extract<int>();
}
strcpy( _szPOI, _object->get("poi").extract<std::string>().c_str());
strcpy( _szJibun, _object->get("jibun").extract<std::string>().c_str());
}
catch(exception &e)
{
formatlog( LOG_ERROR, "CUBIUtils::%s(%d) JSON parsing Exception. %s", __func__, __LINE__, e.what());
return false;
}
return true;
}
Var.h in Poco's source code says.
/// Invoke this method to perform a safe conversion.
///
/// Example usage:
/// Var any("42");
/// int i = any.convert<int>();
///
/// Throws a RangeException if the value does not fit
/// into the result variable.
/// Throws a NotImplementedException if conversion is
/// not available for the given type.
/// Throws InvalidAccessException if Var is empty.
Below Code works.
use convert<T>() instead of extract<T>()
Data type is different. "i", "l"
extract get data which are exactly match type.
_BCodeW = 0;
if ( _object->isNull("BCodeW"))
cout << "BCodeW is NULL" << endl;
else
{
Dynamic::Var _BCodeWVar = _object->get("BCodeW");
cout << "Data Type is " << _BCodeWVar.type().name() << endl;
_BCodeW = _BCodeWVar.convert<Int64>();
cout << "BCodeW is " << _BCodeW << endl;
}
The problem here is not in the JSON parsing and/or data extraction. It is in the comparison line:
if (NULL == _object)
that line will result in BadCastException being thrown.
The reason is because the operator== resolves to
inline bool operator == (const Poco::Int32& other, const Var& da)
and conversion of Poco::JSON::Object::Ptr to Poco::Int32 throws.
Replace the offending line with
if (_object.isNull())
and all will be well.

Create a function to get a username using a try and catch method in C++

I'm trying to create a function to get a username using a try and catch method in C++. Unfortunately this code doesn't work, and my application closes when it tries to run.
QString UserInfo::getFullUserName()
{
DBG_ENTERFUNC(getFullUserName);
QString result;
qDebug("trying to get the username");
try
{
struct passwd fullUserData=*getpwnam(getUserName().toLatin1());
result = fullUserData.pw_gecos;
// it is the first of the comma seperated records that contain the user name
result = result.split(",").first();
if (result.isEmpty())
{
result = getUserName();
}
}
catch (...)
{
qDebug("exception caught");
}
qDebug() << result;
#endif
DBG_EXITFUNC;
return result;
}
The problem occurs in this line of code as I have placed prints after it that are never reached.
struct passwd fullUserData=*getpwnam(getUserName().toLatin1());
Does anyone know what is the issue here?
*Edit--------
Here is my function getUserName()
QString UserInfo::GetUserName()
{
DBG_ENTERFUNC(GetUserName);
QString result;
foreach (QString environmentEntry, QProcess::systemEnvironment())
{
QString varName = environmentEntry.section('=',0,0);
QString varValue = environmentEntry.section('=',1,1);
if (varName == "USER" || varName == "USERNAME")
{
result = varValue;
}
}
DBG_EXITFUNC;
return result;
}
getpwnam() returns NULL when the username was not found. You are potentially dereferencing a NULL pointer.
*getpwnam(getUserName().toLatin1());
// ^ potential NULL pointer deref
Always check before deferencing a potentially invalid pointer:
struct passwd *fullUserData = getpwnam(getUserName().toLatin1());
// ^ note pointer
if (fullUserData != NULL) {
result = fullUserData->pw_gecos;
// ^^ fullUserData is a struct pointer
} else {
// throw Exception
}
If this is confusing to you, you might want to read up on C++ and pointers.

Can I check if memory block is readable without raising exception with C++?

I need the following for the exception handler in C++ code. Say, I have the following code block:
void myFunction(LPCTSTR pStr, int ncbNumCharsInStr)
{
__try
{
//Do work with 'pStr'
}
__except(1)
{
//Catch all
//But here I need to log `pStr` into event log
//For that I don't want to raise another exception
//if memory block of size `ncbNumCharsInStr` * sizeof(TCHAR)
//pointed by 'pStr' is unreadable.
if(memory_readable(pStr, ncbNumCharsInStr * sizeof(TCHAR)))
{
Log(L"Failed processing: %s", pStr);
}
else
{
Log(L"String at 0x%X, %d chars long is unreadable!", pStr, ncbNumCharsInStr);
}
}
}
Is there any way to implement memory_readable?
The VirtualQuery function might be able to help. The following is a quick stab at how you could implement memory_readable using it.
bool memory_readable(void *ptr, size_t byteCount)
{
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery(ptr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == 0)
return false;
if (mbi.State != MEM_COMMIT)
return false;
if (mbi.Protect == PAGE_NOACCESS || mbi.Protect == PAGE_EXECUTE)
return false;
// This checks that the start of memory block is in the same "region" as the
// end. If it isn't you "simplify" the problem into checking that the rest of
// the memory is readable.
size_t blockOffset = (size_t)((char *)ptr - (char *)mbi.AllocationBase);
size_t blockBytesPostPtr = mbi.RegionSize - blockOffset;
if (blockBytesPostPtr < byteCount)
return memory_readable((char *)ptr + blockBytesPostPtr,
byteCount - blockBytesPostPtr);
return true;
}
NOTE: My background is C, so while I suspect that there are better options than casting to a char * in C++ I'm not sure what they are.
You can use the ReadProcessMemory function. If the function returns 0, the address is not readable otherwise it is readable.
Return Value
If the function fails, the return value is 0 (zero). To get extended
error information, call GetLastError.
The function fails if the requested read operation crosses into an
area of the process that is inaccessible.
If the function succeeds, the return value is nonzero.

ReadDebuggeeMemoryEx failed to read debuggee

I have write a debugger extension for my VisualStuido2010 to display my class type. I write my code base on the EEAddin sample provided by Microsoft. But I failed on call ReadDebuggeeMemoryEx.
I can't get any reason for this fail. GetLastError() returns 0.
ObjectId objid;
DWORD nGot;
int state = E_FAIL;
if ( pHelper->ReadDebuggeeMemoryEx(pHelper, pHelper->GetRealAddress(pHelper), sizeof(ObjectId), &objid, &nGot) )
{
}else { log("Fail ReadDebuggeeMemoryEx %d\n", GetLastError());}
The function ReadDebuggeeMemoryEx(...) returns a HRESULT not a BOOL.
Try something like :
if (pHelper->ReadDebuggeeMemoryEx(...) == S_OK) {
// good
} else {
// bad
}

mysql_real_query returns 1, mysql_error returns a NULL string

When I run a first query, mysql_real_query returns 1, from what I understand, this is normal, I have to call mysql_errno() and mysql_error() to get information about the error. But why does mysql_error() return a NULL string?
After running a second query or mysql_ping I receive a violation exception.
Any clue to what's happening ?
Also, should I be using C++ connector in a C++ program or may the C connector (which is what I am using) work as well. Would I have to compile it under my compiler to get it to work?
Here is a part of the code I use, may this help someone pinpoint me the solution. I do not know what is wrong here.
char req[50];
static char *serverOptions_p[] = {
"abc",
"--datadir=C:/Documents and Settings/All Users/Application Data/MySQL/MySQL Server 5.5/data/abc",
"--language=C:/Program Files/MySQL/MySQL Server 5.5/share/english",
NULL
};
int numElements = sizeof (serverOptions_p) / sizeof(char *) - 1;
static char *serverGroups_p[] = { "mysql_server", NULL };
if (mysql_library_init(numElements, serverOptions_p, (char **) serverGroups_p)) {
return;
}
d_connectionHandle_p = mysql_init(NULL);
if (d_connectionHandle_p) {
my_bool mb = true;
mysql_options(d_connectionHandle_p, MYSQL_OPT_RECONNECT, &mb);
if (mysql_real_connect(d_connectionHandle_p, server_p, user_p, password_p, database_p, 0, NULL, 0)) {
sprintf(req, "CREATE DATABASE %s", database_p);
mysql_real_query(d_connectionHandle_p, requete, strlen(requete));
}
}
else {
return;
}
int e;
strcpy(req, "SELECT * FROM test");
if ((e = mysql_real_query(d_connectionHandle_p, req, strlen(req))) != 0) { // This is where it returns 1
const char *err = mysql_error(d_connectionHandle_p); // Returns an empty string
if (err)
{
}
}
According to the manual, a non-zero return value means an error occurred:
Return Values
Zero if the statement was successful. Nonzero if an error occurred.