1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
7 // ===========================================================================
10 // ===========================================================================
26 #define CCH_BSTRMAX 0x7FFFFFFF // 4 + (0x7ffffffb + 1 ) * 2 ==> 0xFFFFFFFC
27 #define CB_BSTRMAX 0xFFFFFFFa // 4 + (0xfffffff6 + 2) ==> 0xFFFFFFFC
29 #define WIN32_ALLOC_ALIGN (16 - 1)
31 inline HRESULT CbSysStringSize(ULONG cchSize, BOOL isByteLen, ULONG *result)
36 // +2 for the null terminator
37 // + DWORD_PTR to store the byte length of the string
38 int constant = sizeof(WCHAR) + sizeof(DWORD_PTR) + WIN32_ALLOC_ALIGN;
42 if (SUCCEEDED(ULongAdd(constant, cchSize, result)))
44 *result = *result & ~WIN32_ALLOC_ALIGN;
50 ULONG temp = 0; // should not use in-place addition in ULongAdd
51 if (SUCCEEDED(ULongMult(cchSize, sizeof(WCHAR), &temp)) &
52 SUCCEEDED(ULongAdd(temp, constant, result)))
54 *result = *result & ~WIN32_ALLOC_ALIGN;
58 return INTSAFE_E_ARITHMETIC_OVERFLOW;
62 *BSTR SysAllocStringLen(char*, unsigned int)
64 * Allocation a bstr of the given length and initialize with
65 * the pasted in string
71 * return value = BSTR, NULL if the allocation failed.
73 ***********************************************************************/
74 STDAPI_(BSTR) SysAllocStringLen(const OLECHAR *psz, UINT len)
80 if (FAILED(CbSysStringSize(len, FALSE, &cbTotal)))
83 bstr = (OLECHAR *)HeapAlloc(GetProcessHeap(), 0, cbTotal);
88 // NOTE: There are some apps which peek back 4 bytes to look at the size of the BSTR. So, in case of 64-bit code,
89 // we need to ensure that the BSTR length can be found by looking one DWORD before the BSTR pointer.
90 *(DWORD_PTR *)bstr = (DWORD_PTR) 0;
91 bstr = (BSTR) ((char *) bstr + sizeof (DWORD));
93 *(DWORD FAR*)bstr = (DWORD)len * sizeof(OLECHAR);
95 bstr = (BSTR) ((char*) bstr + sizeof(DWORD));
98 memcpy(bstr, psz, len * sizeof(OLECHAR));
101 bstr[len] = '\0'; // always 0 terminate
108 *BSTR SysAllocString(char*)
110 * Allocation a bstr using the passed in string
113 * String to create a bstr for
116 * return value = BSTR, NULL if allocation failed
118 ***********************************************************************/
119 STDAPI_(BSTR) SysAllocString(const OLECHAR* psz)
124 return SysAllocStringLen(psz, (DWORD)wcslen(psz));
128 SysAllocStringByteLen(const char FAR* psz, unsigned int len)
133 if (FAILED(CbSysStringSize(len, TRUE, &cbTotal)))
136 bstr = (OLECHAR *)HeapAlloc(GetProcessHeap(), 0, cbTotal);
140 *(DWORD FAR*)((char *)bstr + sizeof (DWORD)) = (DWORD)len;
142 *(DWORD FAR*)bstr = (DWORD)len;
145 bstr = (WCHAR*) ((char*) bstr + sizeof(DWORD_PTR));
148 memcpy(bstr, psz, len);
151 // NULL-terminate with both a narrow and wide zero.
152 *((char *)bstr + len) = '\0';
153 *(WCHAR *)((char *)bstr + ((len + 1) & ~1)) = 0;
160 *void SysFreeString(BSTR)
162 * Free the given BSTR.
165 * bstr = the BSTR to free
170 ***********************************************************************/
171 STDAPI_(void) SysFreeString(BSTR bstr)
175 HeapFree(GetProcessHeap(), 0, (BYTE *)bstr-sizeof(DWORD_PTR));
179 *unsigned int SysStringLen(BSTR)
181 * return the length in characters of the given BSTR.
184 * bstr = the BSTR to return the length of
187 * return value = unsigned int, length in characters.
189 ***********************************************************************/
190 STDAPI_(unsigned int)
191 SysStringLen(BSTR bstr)
195 return (unsigned int)((((DWORD FAR*)bstr)[-1]) / sizeof(OLECHAR));
199 *unsigned int SysStringByteLen(BSTR)
201 * return the size in bytes of the given BSTR.
204 * bstr = the BSTR to return the size of
207 * return value = unsigned int, size in bytes.
209 ***********************************************************************/
210 STDAPI_(unsigned int)
211 SysStringByteLen(BSTR bstr)
215 return (unsigned int)(((DWORD FAR*)bstr)[-1]);
219 ErrStringCopy(BSTR bstrSource, BSTR FAR *pbstrOut)
221 if (bstrSource == NULL) {
225 if ((*pbstrOut = SysAllocStringLen(bstrSource,
226 SysStringLen(bstrSource))) == NULL)
227 return E_OUTOFMEMORY;
233 *PRIVATE HRESULT ErrSysAllocString(char*, BSTR*)
235 * This is an implementation of SysAllocString that check for the
236 * NULL return value and return the corresponding error - E_OUTOFMEMORY.
238 * This is simply a convenience, and this routine is only used
239 * internally by the oledisp component.
242 * psz = the source string
245 * return value = HRESULT
249 * *pbstrOut = the newly allocated BSTR
251 ***********************************************************************/
253 ErrSysAllocString(const OLECHAR FAR* psz, BSTR FAR* pbstrOut)
260 if((*pbstrOut = SysAllocString(psz)) == NULL)
261 return E_OUTOFMEMORY;