From f1779ed51d87f97414b29ca212160a4637c59ca4 Mon Sep 17 00:00:00 2001 From: Francis Beaudet Date: Wed, 25 Nov 1998 17:20:36 +0000 Subject: [PATCH] Implemented 3 methods: SysAllocStringLen(), SysReAllocStringLen() and SysStringLen(). Ensure that the BSTR objects were allocated according to the Windows documentation. --- include/oleauto.h | 9 +++ ole/ole2disp.c | 158 ++++++++++++++++++++++++++++++++++++++++-- relay32/oleaut32.spec | 6 +- 3 files changed, 164 insertions(+), 9 deletions(-) diff --git a/include/oleauto.h b/include/oleauto.h index 4b675e6b9ce..3029fcd6186 100644 --- a/include/oleauto.h +++ b/include/oleauto.h @@ -10,6 +10,15 @@ INT32 WINAPI SysReAllocString32(LPBSTR32,LPOLESTR32); VOID WINAPI SysFreeString16(BSTR16); VOID WINAPI SysFreeString32(BSTR32); #define SysFreeString WINELIB_NAME(SysFreeString) +BSTR16 WINAPI SysAllocStringLen16(char*, int); +BSTR32 WINAPI SysAllocStringLen32(WCHAR*, int); +#define SysAllocStringLen WINELIB_NAME(SysAllocStringLen) +int WINAPI SysReAllocStringLen16(BSTR16*, char*, int); +int WINAPI SysReAllocStringLen32(BSTR32*, WCHAR*, int); +#define SysReAllocStringLen WINELIB_NAME(SysReAllocStringLen) +int WINAPI SysStringLen16(BSTR16); +int WINAPI SysStringLen32(BSTR32); +#define SysStringLen WINELIB_NAME(SysStringLen) typedef char OLECHAR; typedef void ITypeLib; diff --git a/ole/ole2disp.c b/ole/ole2disp.c index 58f7dfc22f3..2582b4409a6 100644 --- a/ole/ole2disp.c +++ b/ole/ole2disp.c @@ -4,6 +4,7 @@ * Copyright 1995 Martin von Loewis */ +#include #include "windows.h" #include "ole.h" #include "ole2.h" @@ -58,7 +59,8 @@ BSTR16 WINAPI SysAllocString16(LPOLESTR16 in) */ BSTR32 WINAPI SysAllocString32(LPOLESTR32 in) { - return HEAP_strdupW(GetProcessHeap(),0,in); + /* Delegate this to the SysAllocStringLen32 method. */ + return SysAllocStringLen32(in, lstrlen32W(in)); } /****************************************************************************** @@ -77,10 +79,24 @@ INT16 WINAPI SysReAllocString16(LPBSTR16 old,LPOLESTR16 in) */ INT32 WINAPI SysReAllocString32(LPBSTR32 old,LPOLESTR32 in) { - BSTR32 new=SysAllocString32(in); - HeapFree(GetProcessHeap(),0,*old); - *old=new; - return 1; + /* + * Sanity check + */ + if (old==NULL) + return 0; + + /* + * Make sure we free the old string. + */ + if (*old!=NULL) + SysFreeString32(*old); + + /* + * Allocate the new string + */ + *old = SysAllocString32(in); + + return 1; } /****************************************************************************** @@ -94,6 +110,73 @@ BSTR16 WINAPI SysAllocStringLen16(char *in, int len) return out; } +/****************************************************************************** + * SysAllocStringLen32 [OLEAUT32.4] + * + * In "Inside OLE, second edition" by Kraig Brockshmidt. In the Automation + * section, he describes the DWORD value placed before the BSTR data type. + * he describes it as a "DWORD count of characters". By experimenting with + * a windows application, this count seems to be a DWORD count of bytes in + * the string. Meaning that the count is double the number of wide + * characters in the string. + */ +BSTR32 WINAPI SysAllocStringLen32(WCHAR *in, int len) +{ + DWORD bufferSize; + DWORD* newBuffer; + WCHAR* stringBuffer; + + /* + * Find the lenth of the buffer passed-in in bytes. + */ + bufferSize = len * sizeof (WCHAR); + + /* + * Allocate a new buffer to hold the string. + * dont't forget to keep an empty spot at the begining of the + * buffer for the character count and an extra character at the + * end for the NULL. + */ + newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(), + 0, + bufferSize + sizeof(WCHAR) + sizeof(DWORD)); + + /* + * If the memory allocation failed, return a null pointer. + */ + if (newBuffer==0) + return 0; + + /* + * Copy the length of the string in the placeholder. + */ + *newBuffer = bufferSize; + + /* + * Skip the byte count. + */ + newBuffer++; + + /* + * Copy the information in the buffer. + * Since it is valid to pass a NULL pointer here, we'll initialize the + * buffer to nul if it is the case. + */ + if (in != 0) + memcpy(newBuffer, in, bufferSize); + else + memset(newBuffer, 0, bufferSize); + + /* + * Make sure that there is a nul character at the end of the + * string. + */ + stringBuffer = (WCHAR*)newBuffer; + stringBuffer[len] = L'\0'; + + return (LPWSTR)stringBuffer; +} + /****************************************************************************** * SysReAllocStringLen16 [OLE2DISP.5] */ @@ -105,6 +188,32 @@ int WINAPI SysReAllocStringLen16(BSTR16 *old,char *in,int len) return 1; } + +/****************************************************************************** + * SysReAllocStringLen32 [OLEAUT32.5] + */ +int WINAPI SysReAllocStringLen32(BSTR32* old, WCHAR* in, int len) +{ + /* + * Sanity check + */ + if (old==NULL) + return 0; + + /* + * Make sure we free the old string. + */ + if (*old!=NULL) + SysFreeString32(*old); + + /* + * Allocate the new string + */ + *old = SysAllocStringLen32(in, len); + + return 1; +} + /****************************************************************************** * SysFreeString16 [OLE2DISP.6] */ @@ -118,7 +227,21 @@ void WINAPI SysFreeString16(BSTR16 in) */ void WINAPI SysFreeString32(BSTR32 in) { - HeapFree(GetProcessHeap(),0,in); + DWORD* bufferPointer; + + /* + * We have to be careful when we free a BSTR pointer, it points to + * the beginning of the string but it skips the byte count contained + * before the string. + */ + bufferPointer = (DWORD*)in; + + bufferPointer--; + + /* + * Free the memory from it's "real" origin. + */ + HeapFree(GetProcessHeap(), 0, bufferPointer); } /****************************************************************************** @@ -129,6 +252,29 @@ int WINAPI SysStringLen16(BSTR16 str) return strlen(BSTR_GetAddr(str)); } +/****************************************************************************** + * SysStringLen32 [OLEAUT32.7] + * + * The Windows documentation states that the length returned by this function + * is not necessarely the same as the length returned by the _lstrlenW method. + * It is the same number that was passed in as the "len" parameter if the + * string was allocated with a SysAllocStringLen method call. + */ +int WINAPI SysStringLen32(BSTR32 str) +{ + DWORD* bufferPointer; + + /* + * The length of the string (in bytes) is contained in a DWORD placed + * just before the BSTR pointer + */ + bufferPointer = (DWORD*)str; + + bufferPointer--; + + return (int)(*bufferPointer/sizeof(WCHAR)); +} + /****************************************************************************** * CreateDispTypeInfo [OLE2DISP.31] */ diff --git a/relay32/oleaut32.spec b/relay32/oleaut32.spec index fe57d977fb1..148c19ba186 100644 --- a/relay32/oleaut32.spec +++ b/relay32/oleaut32.spec @@ -4,10 +4,10 @@ type win32 1 stub DllGetClassObject 2 stdcall SysAllocString(wstr) SysAllocString32 3 stdcall SysReAllocString(ptr wstr) SysReAllocString32 -4 stub SysAllocStringLen -5 stub SysReAllocStringLen +4 stdcall SysAllocStringLen(wstr long) SysAllocStringLen32 +5 stdcall SysReAllocStringLen(ptr ptr long) SysReAllocStringLen32 6 stdcall SysFreeString(wstr) SysFreeString32 -7 stub SysStringLen +7 stdcall SysStringLen(wstr) SysStringLen32 8 stub VariantInit 9 stub VariantClear 10 stub VariantCopy