For the BSTR debuggers :)

From: Egbert Nierop \(MVP for IIS\) (egbert_nierop_at_nospam.invalid)
Date: 03/10/05


Date: Thu, 10 Mar 2005 15:36:44 +0100


#pragma once
/* file brnocache.h
 * Made by Egbert Nierop, Nierop Webconsultancy, 2005
 * Usage at your own risk.
 * Made to avoid BSTR caching & testing which also could be done by a debug
version of OLEAUT32 and setting an environment variable.
 * Obviously, this code is more easy.
 * You can also
 * disable BSTR caching by calling into DisableBSTRCache. On W2k and XP and
2003, this gave no problems (yet)
 */

INT __stdcall SysReAllocStringLen2(BSTR * bstr, const OLECHAR* input, UINT
cch);
BSTR __stdcall SysAllocStringLen2(const OLECHAR* input, UINT cch);
BSTR __stdcall SysAllocString2(const OLECHAR * input);
INT __stdcall SysReAllocString2(BSTR * bstr, const OLECHAR* input);
void DisableBSTRCache(void);

#define SysAllocStringLen SysAllocStringLen2
#define SysReAllocStringLen SysReAllocStringLen2
#define SysAllocString SysAllocString2
#define SysReAllocString SysReAllocString2
//#ifndef NWC_REALLOC
//#define NWC_REALLOC
static INT __stdcall SysReAllocStringLen2(BSTR * bstr, const OLECHAR* input,
UINT cch)
{
 ATLASSERT(bstr != NULL);
 if (*bstr == NULL)
 {
  *bstr = SysAllocStringLen2(input, cch);
 }
 else
 {
  UINT copyIntoLen = input != NULL ? ::lstrlenW(input): 0;
  if (copyIntoLen > cch)
   copyIntoLen = cch;
  UINT newlen = cch * sizeof(OLECHAR) + sizeof(OLECHAR) + sizeof(UINT);

  BSTR temp = *bstr - sizeof(INT) / sizeof(OLECHAR);
  temp = (BSTR)::CoTaskMemRealloc(temp, newlen);

  if (temp != NULL)
  {
   UINT* plen = (UINT*)temp;
   plen[0] = cch * 2; //asign bytelength for BSTR
   if (copyIntoLen > 0) //copy values
    memcpy(&temp[sizeof(UINT) / sizeof(OLECHAR)],
     input,
     copyIntoLen * 2 + sizeof(OLECHAR));

   temp[sizeof(UINT) / sizeof(OLECHAR) + cch ] = 0; //terminate LPWSTR
   *bstr = &temp[sizeof(UINT) / sizeof(OLECHAR)];

  }

 }
 return *bstr == NULL ? FALSE : TRUE;
}
///<summary>
///
///</summary>
static BSTR __stdcall SysAllocStringLen2(const OLECHAR* input, UINT cch)
{
 UINT copyIntoLen = input != NULL ? ::lstrlenW(input) : 0;
 if (copyIntoLen > cch)
  copyIntoLen = cch;

 UINT newlen = cch * sizeof(OLECHAR) + sizeof(OLECHAR) + sizeof(UINT);
 BSTR temp = (BSTR)::CoTaskMemAlloc(newlen);
 UINT* plen = (UINT*)temp;
 plen[0] = cch * 2;
 if (copyIntoLen > 0)
  memcpy(&temp[sizeof(UINT) / sizeof(OLECHAR)],
   input,
   copyIntoLen * 2 + sizeof(OLECHAR));
 temp[sizeof(UINT) / sizeof(OLECHAR) + cch ] = 0;
 return &temp[sizeof(UINT) / sizeof(OLECHAR)];

}
///<summary>
/// Identical to SysAllocString
///</summary>
static BSTR __stdcall SysAllocString2(const OLECHAR * input)
{
 UINT slen = ::lstrlenW(input);
 UINT newlen = slen * sizeof(OLECHAR)+ sizeof(UINT) + sizeof(OLECHAR);
 BSTR temp = (BSTR)::CoTaskMemAlloc(newlen);
 //RtlZeroMemory(temp, newlen);
 UINT* plen = (UINT*)temp;
 plen[0] =slen * 2;
 memcpy(&temp[sizeof(UINT) / sizeof(OLECHAR)], input, slen * 2 +
sizeof(OLECHAR));
 return &temp[sizeof(UINT) / sizeof(OLECHAR)];
}

static INT __stdcall SysReAllocString2(BSTR * bstr, const OLECHAR* input)
throw()
{
 ATLASSERT(bstr != NULL);
 if (*bstr == NULL)
 {
  *bstr = SysAllocString2(input);
 }
 else
 {
  UINT slen = ::lstrlenW(input);
  UINT newlen = slen * sizeof(OLECHAR) + sizeof(OLECHAR) + sizeof(UINT);

  BSTR temp = *bstr - sizeof(INT) / sizeof(OLECHAR);
  temp = (BSTR)::CoTaskMemRealloc(temp, newlen);
  if (temp != NULL)
  {
   UINT* plen = (UINT*)temp;
   plen[0] =slen * 2;
   memcpy(&temp[sizeof(UINT) / sizeof(OLECHAR)], input, slen * 2 +
sizeof(OLECHAR));
   *bstr = &temp[sizeof(UINT) / sizeof(OLECHAR)];
  }

 }
 return *bstr == NULL ? FALSE : TRUE;
}
//#ifdef DEBUG
typedef int (*SETOANOCACHE)(void);
static void DisableBSTRCache(void)
{
  SETOANOCACHE SetOaNoCache = NULL;
  HINSTANCE hinst = LoadLibrary(_T("OLEAUT32.DLL"));
  if (hinst != NULL)
  {
   SetOaNoCache = (SETOANOCACHE) GetProcAddress(hinst, "SetOaNoCache");
   if (SetOaNoCache != NULL)
    SetOaNoCache();
   FreeLibrary(hinst);
  }
}
//#endif

//#endif



Relevant Pages

  • Re: SysFreeString - Is the memory mine to use as I please ?
    ... int __stdcall SysReAllocStringByteLen2(BSTR * bstr, PCSTR input, UINT cch) throw ... PSTR temp =::CoTaskMemRealloc( ... BSTR __stdcall SysAllocStringLen2 ...
    (microsoft.public.win32.programmer.kernel)
  • Re: bstr size issue
    ... BSTR is defined like typedef OLECHAR* BSTR; ... OLECHAR is defined like typedef WCHAR OLECHAR; ...
    (microsoft.public.vc.mfc)
  • Re: OLESTR
    ... The marshalling is not done by BSTR or any other type. ... OLESTR is a macro and OLECHAR is a typedef for WCHAR. ...
    (microsoft.public.vc.language)