diff options
author | dotnet-bot <dotnet-bot@microsoft.com> | 2015-01-30 14:14:42 -0800 |
---|---|---|
committer | dotnet-bot <dotnet-bot@microsoft.com> | 2015-01-30 14:14:42 -0800 |
commit | ef1e2ab328087c61a6878c1e84f4fc5d710aebce (patch) | |
tree | dee1bbb89e9d722e16b0d1485e3cdd1b6c8e2cfa /src/palrt/bstr.cpp | |
download | coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.gz coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.bz2 coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.zip |
Initial commit to populate CoreCLR repo
[tfs-changeset: 1407945]
Diffstat (limited to 'src/palrt/bstr.cpp')
-rw-r--r-- | src/palrt/bstr.cpp | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/src/palrt/bstr.cpp b/src/palrt/bstr.cpp new file mode 100644 index 0000000000..d15f0ef29e --- /dev/null +++ b/src/palrt/bstr.cpp @@ -0,0 +1,265 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// + +// +// =========================================================================== +// File: bstr.cpp +// +// =========================================================================== + + +/*++ + +Abstract: + + PALRT BSTR support + +Revision History: + +--*/ + +#include "common.h" +#include "intsafe.h" + +#define CCH_BSTRMAX 0x7FFFFFFF // 4 + (0x7ffffffb + 1 ) * 2 ==> 0xFFFFFFFC +#define CB_BSTRMAX 0xFFFFFFFa // 4 + (0xfffffff6 + 2) ==> 0xFFFFFFFC + +#define WIN32_ALLOC_ALIGN (16 - 1) + +inline HRESULT CbSysStringSize(ULONG cchSize, BOOL isByteLen, ULONG *result) +{ + if (result == NULL) + return E_INVALIDARG; + + // +2 for the null terminator + // + DWORD_PTR to store the byte length of the string + int constant = sizeof(WCHAR) + sizeof(DWORD_PTR) + WIN32_ALLOC_ALIGN; + + if (isByteLen) + { + if (SUCCEEDED(ULongAdd(constant, cchSize, result))) + { + *result = *result & ~WIN32_ALLOC_ALIGN; + return NOERROR; + } + } + else + { + ULONG temp = 0; // should not use in-place addition in ULongAdd + if (SUCCEEDED(ULongMult(cchSize, sizeof(WCHAR), &temp)) & + SUCCEEDED(ULongAdd(temp, constant, result))) + { + *result = *result & ~WIN32_ALLOC_ALIGN; + return NOERROR; + } + } + return INTSAFE_E_ARITHMETIC_OVERFLOW; +} + +/*** +*BSTR SysAllocStringLen(char*, unsigned int) +*Purpose: +* Allocation a bstr of the given length and initialize with +* the pasted in string +* +*Entry: +* [optional] +* +*Exit: +* return value = BSTR, NULL if the allocation failed. +* +***********************************************************************/ +STDAPI_(BSTR) SysAllocStringLen(const OLECHAR *psz, UINT len) +{ + + BSTR bstr; + DWORD cbTotal = 0; + + if (FAILED(CbSysStringSize(len, FALSE, &cbTotal))) + return NULL; + + bstr = (OLECHAR *)HeapAlloc(GetProcessHeap(), 0, cbTotal); + + if(bstr != NULL){ + +#if defined(_WIN64) + // 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, + // we need to ensure that the BSTR length can be found by looking one DWORD before the BSTR pointer. + *(DWORD_PTR *)bstr = (DWORD_PTR) 0; + bstr = (BSTR) ((char *) bstr + sizeof (DWORD)); +#endif + *(DWORD FAR*)bstr = (DWORD)len * sizeof(OLECHAR); + + bstr = (BSTR) ((char*) bstr + sizeof(DWORD)); + + if(psz != NULL){ + memcpy(bstr, psz, len * sizeof(OLECHAR)); + } + + bstr[len] = '\0'; // always 0 terminate + } + + return bstr; +} + +/*** +*BSTR SysAllocString(char*) +*Purpose: +* Allocation a bstr using the passed in string +* +*Entry: +* String to create a bstr for +* +*Exit: +* return value = BSTR, NULL if allocation failed +* +***********************************************************************/ +STDAPI_(BSTR) SysAllocString(const OLECHAR* psz) +{ + if(psz == NULL) + return NULL; + + return SysAllocStringLen(psz, (DWORD)wcslen(psz)); +} + +STDAPI_(BSTR) +SysAllocStringByteLen(const char FAR* psz, unsigned int len) +{ + BSTR bstr; + DWORD cbTotal = 0; + + if (FAILED(CbSysStringSize(len, TRUE, &cbTotal))) + return FALSE; + + bstr = (OLECHAR *)HeapAlloc(GetProcessHeap(), 0, cbTotal); + + if (bstr != NULL) { +#if defined(_WIN64) + *(DWORD FAR*)((char *)bstr + sizeof (DWORD)) = (DWORD)len; +#else + *(DWORD FAR*)bstr = (DWORD)len; +#endif + + bstr = (WCHAR*) ((char*) bstr + sizeof(DWORD_PTR)); + + if (psz != NULL) { + memcpy(bstr, psz, len); + } + + // NULL-terminate with both a narrow and wide zero. + *((char *)bstr + len) = '\0'; + *(WCHAR *)((char *)bstr + ((len + 1) & ~1)) = 0; + } + + return bstr; +} + +/*** +*void SysFreeString(BSTR) +*Purpose: +* Free the given BSTR. +* +*Entry: +* bstr = the BSTR to free +* +*Exit: +* None +* +***********************************************************************/ +STDAPI_(void) SysFreeString(BSTR bstr) +{ + if(bstr == NULL) + return; + HeapFree(GetProcessHeap(), 0, (BYTE *)bstr-sizeof(DWORD_PTR)); +} + +/*** +*unsigned int SysStringLen(BSTR) +*Purpose: +* return the length in characters of the given BSTR. +* +*Entry: +* bstr = the BSTR to return the length of +* +*Exit: +* return value = unsigned int, length in characters. +* +***********************************************************************/ +STDAPI_(unsigned int) +SysStringLen(BSTR bstr) +{ + if(bstr == NULL) + return 0; + return (unsigned int)((((DWORD FAR*)bstr)[-1]) / sizeof(OLECHAR)); +} + +/*** +*unsigned int SysStringByteLen(BSTR) +*Purpose: +* return the size in bytes of the given BSTR. +* +*Entry: +* bstr = the BSTR to return the size of +* +*Exit: +* return value = unsigned int, size in bytes. +* +***********************************************************************/ +STDAPI_(unsigned int) +SysStringByteLen(BSTR bstr) +{ + if(bstr == NULL) + return 0; + return (unsigned int)(((DWORD FAR*)bstr)[-1]); +} + +extern "C" HRESULT +ErrStringCopy(BSTR bstrSource, BSTR FAR *pbstrOut) +{ + if (bstrSource == NULL) { + *pbstrOut = NULL; + return NOERROR; + } + if ((*pbstrOut = SysAllocStringLen(bstrSource, + SysStringLen(bstrSource))) == NULL) + return E_OUTOFMEMORY; + + return NOERROR; +} + +/*** +*PRIVATE HRESULT ErrSysAllocString(char*, BSTR*) +*Purpose: +* This is an implementation of SysAllocString that check for the +* NULL return value and return the corresponding error - E_OUTOFMEMORY. +* +* This is simply a convenience, and this routine is only used +* internally by the oledisp component. +* +*Entry: +* psz = the source string +* +*Exit: +* return value = HRESULT +* S_OK +* E_OUTOFMEMORY +* +* *pbstrOut = the newly allocated BSTR +* +***********************************************************************/ +extern "C" HRESULT +ErrSysAllocString(const OLECHAR FAR* psz, BSTR FAR* pbstrOut) +{ + if(psz == NULL){ + *pbstrOut = NULL; + return NOERROR; + } + + if((*pbstrOut = SysAllocString(psz)) == NULL) + return E_OUTOFMEMORY; + + return NOERROR; +} |