forked from chakra-core/ChakraCore
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbstr.cpp
More file actions
187 lines (153 loc) · 4.25 KB
/
bstr.cpp
File metadata and controls
187 lines (153 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
/*++
Module Name:
misc/bstr.cpp
Abstract:
Implementation of bstr related functionality
--*/
#include "pal/palinternal.h"
// Redefining here to not have to pull in all of palrt.h in order to get intsafe
#define S_OK ((HRESULT)0x00000000L)
#define E_INVALIDARG ((HRESULT) 0x80070057L)
#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
#define FAILED(Status) ((HRESULT)(Status)<0)
#define STDAPICALLTYPE __stdcall
#define NULL 0
#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE
#include "pal_assert.h"
#include "rt/intsafe.h"
#define WIN32_ALLOC_ALIGN (16 - 1)
PALIMPORT size_t __cdecl PAL_wcslen(const WCHAR *);
typedef WCHAR OLECHAR;
typedef WCHAR *BSTR;
inline HRESULT CbSysStringSize(ULONG cchSize, BOOL isByteLen, ULONG *result)
{
if (result == nullptr)
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;
}
/***
*void SysFreeString(BSTR)
*Purpose:
* Free a bstr using the passed in string
*
*Entry:
* BSTR to free
*
*Exit:
* return value = void
*
***********************************************************************/
STDAPI_(void) SysFreeString(BSTR bstr)
{
if (bstr != NULL)
{
bstr = (BSTR) ((char*) bstr - sizeof(DWORD));
#if defined(_WIN64)
bstr = (BSTR) ((char*) bstr - sizeof(DWORD));
#endif
HeapFree(GetProcessHeap(), 0, (LPVOID) bstr);
}
}
/***
*UINT SysStringLen(BSTR)
*Purpose:
* Return the length of the string in characters (not including null terminator)
*
*Entry:
* BSTR whose length to return
*
*Exit:
* return value = length of the string
*
***********************************************************************/
STDAPI_(UINT) SysStringLen(BSTR bstr)
{
if (bstr == NULL)
{
return 0;
}
return (UINT)((((DWORD FAR*)bstr)[-1]) / sizeof(OLECHAR));
}
/***
*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)PAL_wcslen(psz));
}