1 /*
2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "WebKitDLL.h"
28 #include "MarshallingHelpers.h"
29
30 #pragma warning(push, 0)
31 #include <WebCore/IntRect.h>
32 #include <WebCore/KURL.h>
33 #include <WebCore/PlatformString.h>
34 #pragma warning(pop)
35
36 using namespace WebCore;
37
38 static const double secondsPerDay = 60 * 60 * 24;
39
40 CFArrayCallBacks MarshallingHelpers::kIUnknownArrayCallBacks = {0, IUnknownRetainCallback, IUnknownReleaseCallback, 0, 0};
41 CFDictionaryValueCallBacks MarshallingHelpers::kIUnknownDictionaryValueCallBacks = {0, IUnknownRetainCallback, IUnknownReleaseCallback, 0, 0};
42
BSTRToKURL(BSTR urlStr)43 KURL MarshallingHelpers::BSTRToKURL(BSTR urlStr)
44 {
45 return KURL(KURL(), String(urlStr, SysStringLen(urlStr)));
46 }
47
KURLToBSTR(const KURL & url)48 BSTR MarshallingHelpers::KURLToBSTR(const KURL& url)
49 {
50 return SysAllocStringLen(url.string().characters(), url.string().length());
51 }
52
PathStringToFileCFURLRef(const String & string)53 CFURLRef MarshallingHelpers::PathStringToFileCFURLRef(const String& string)
54 {
55 CFStringRef cfPath = CFStringCreateWithCharactersNoCopy(0, (const UniChar*)string.characters(), string.length(), kCFAllocatorNull);
56 CFURLRef pathURL = CFURLCreateWithFileSystemPath(0, cfPath, kCFURLWindowsPathStyle, false);
57 CFRelease(cfPath);
58 return pathURL;
59 }
60
FileCFURLRefToPathString(CFURLRef fileURL)61 String MarshallingHelpers::FileCFURLRefToPathString(CFURLRef fileURL)
62 {
63 CFStringRef string = CFURLCopyFileSystemPath(fileURL, kCFURLWindowsPathStyle);
64 String result(string);
65 CFRelease(string);
66 return result;
67 }
68
BSTRToCFURLRef(BSTR urlStr)69 CFURLRef MarshallingHelpers::BSTRToCFURLRef(BSTR urlStr)
70 {
71 CFStringRef urlCFString = BSTRToCFStringRef(urlStr);
72 if (!urlCFString)
73 return 0;
74
75 CFURLRef urlRef = CFURLCreateWithString(0, urlCFString, 0);
76 CFRelease(urlCFString);
77
78 return urlRef;
79 }
80
BSTRToCFStringRef(BSTR str)81 CFStringRef MarshallingHelpers::BSTRToCFStringRef(BSTR str)
82 {
83 return CFStringCreateWithCharacters(0, (const UniChar*)(str ? str : TEXT("")), SysStringLen(str));
84 }
85
LPCOLESTRToCFStringRef(LPCOLESTR str)86 CFStringRef MarshallingHelpers::LPCOLESTRToCFStringRef(LPCOLESTR str)
87 {
88 return CFStringCreateWithCharacters(0, (const UniChar*)(str ? str : TEXT("")), (CFIndex)(str ? wcslen(str) : 0));
89 }
90
CFStringRefToBSTR(CFStringRef str)91 BSTR MarshallingHelpers::CFStringRefToBSTR(CFStringRef str)
92 {
93 if (!str)
94 return 0;
95
96 const UniChar* uniChars = CFStringGetCharactersPtr(str);
97 if (uniChars)
98 return SysAllocStringLen((LPCTSTR)uniChars, CFStringGetLength(str));
99
100 CFIndex length = CFStringGetLength(str);
101 BSTR bstr = SysAllocStringLen(0, length);
102 if (bstr) {
103 CFStringGetCharacters(str, CFRangeMake(0, length), (UniChar*)bstr);
104 bstr[length] = 0;
105 }
106 return bstr;
107 }
108
CFNumberRefToInt(CFNumberRef num)109 int MarshallingHelpers::CFNumberRefToInt(CFNumberRef num)
110 {
111 int number;
112 CFNumberGetValue(num, kCFNumberIntType, &number);
113 return number;
114 }
115
intToCFNumberRef(int num)116 CFNumberRef MarshallingHelpers::intToCFNumberRef(int num)
117 {
118 return CFNumberCreate(0, kCFNumberSInt32Type, &num);
119 }
120
windowsEpochAbsoluteTime()121 CFAbsoluteTime MarshallingHelpers::windowsEpochAbsoluteTime()
122 {
123 static CFAbsoluteTime windowsEpochAbsoluteTime = 0;
124 if (!windowsEpochAbsoluteTime) {
125 CFGregorianDate windowsEpochDate = {1899, 12, 30, 0, 0, 0.0};
126 windowsEpochAbsoluteTime = CFGregorianDateGetAbsoluteTime(windowsEpochDate, 0) / secondsPerDay;
127 }
128 return windowsEpochAbsoluteTime;
129 }
130
DATEToCFAbsoluteTime(DATE date)131 CFAbsoluteTime MarshallingHelpers::DATEToCFAbsoluteTime(DATE date)
132 {
133 // <http://msdn2.microsoft.com/en-us/library/ms221627.aspx>
134 // DATE: This is the same numbering system used by most spreadsheet programs,
135 // although some specify incorrectly that February 29, 1900 existed, and thus
136 // set January 1, 1900 to 1.0. The date can be converted to and from an MS-DOS
137 // representation using VariantTimeToDosDateTime, which is discussed in
138 // Conversion and Manipulation Functions.
139
140 // CFAbsoluteTime: Type used to represent a specific point in time relative
141 // to the absolute reference date of 1 Jan 2001 00:00:00 GMT.
142 // Absolute time is measured by the number of seconds between the reference
143 // date and the specified date. Negative values indicate dates/times before
144 // the reference date. Positive values indicate dates/times after the
145 // reference date.
146
147 return (date + windowsEpochAbsoluteTime()) * secondsPerDay;
148 }
149
CFAbsoluteTimeToDATE(CFAbsoluteTime absoluteTime)150 DATE MarshallingHelpers::CFAbsoluteTimeToDATE(CFAbsoluteTime absoluteTime)
151 {
152 return (absoluteTime/secondsPerDay - windowsEpochAbsoluteTime());
153 }
154
155 // utility method to store a 1-dim string vector into a newly created SAFEARRAY
stringArrayToSafeArray(CFArrayRef inArray)156 SAFEARRAY* MarshallingHelpers::stringArrayToSafeArray(CFArrayRef inArray)
157 {
158 CFIndex size = CFArrayGetCount(inArray);
159 SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_BSTR, 0, (ULONG) size, 0);
160 long count = 0;
161 for (CFIndex i=0; i<size; i++) {
162 CFStringRef item = (CFStringRef) CFArrayGetValueAtIndex(inArray, i);
163 BSTR bstr = CFStringRefToBSTR(item);
164 ::SafeArrayPutElement(sa, &count, bstr);
165 SysFreeString(bstr); // SafeArrayPutElement() should make a copy of the string
166 count++;
167 }
168 return sa;
169 }
170
171 // utility method to store a 1-dim int vector into a newly created SAFEARRAY
intArrayToSafeArray(CFArrayRef inArray)172 SAFEARRAY* MarshallingHelpers::intArrayToSafeArray(CFArrayRef inArray)
173 {
174 CFIndex size = CFArrayGetCount(inArray);
175 SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_I4, 0, (ULONG) size, 0);
176 long count = 0;
177 for (CFIndex i=0; i<size; i++) {
178 CFNumberRef item = (CFNumberRef) CFArrayGetValueAtIndex(inArray, i);
179 int number = CFNumberRefToInt(item);
180 ::SafeArrayPutElement(sa, &count, &number);
181 count++;
182 }
183 return sa;
184 }
185
intRectToSafeArray(const WebCore::IntRect & rect)186 SAFEARRAY* MarshallingHelpers::intRectToSafeArray(const WebCore::IntRect& rect)
187 {
188 SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_I4, 0, 4, 0);
189 long count = 0;
190 int value;
191
192 value = rect.x();
193 ::SafeArrayPutElement(sa, &count, &value);
194 count++;
195
196 value = rect.y();
197 ::SafeArrayPutElement(sa, &count, &value);
198 count++;
199
200 value = rect.width();
201 ::SafeArrayPutElement(sa, &count, &value);
202 count++;
203
204 value = rect.height();
205 ::SafeArrayPutElement(sa, &count, &value);
206 count++;
207
208 return sa;
209 }
210
211 // utility method to store a 1-dim IUnknown* vector into a newly created SAFEARRAY
iunknownArrayToSafeArray(CFArrayRef inArray)212 SAFEARRAY* MarshallingHelpers::iunknownArrayToSafeArray(CFArrayRef inArray)
213 {
214 CFIndex size = CFArrayGetCount(inArray);
215 SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_UNKNOWN, 0, (ULONG) size, (LPVOID)&IID_IUnknown);
216 long count = 0;
217 for (CFIndex i=0; i<size; i++) {
218 IUnknown* item = (IUnknown*) CFArrayGetValueAtIndex(inArray, i);
219 ::SafeArrayPutElement(sa, &count, item); // SafeArrayPutElement() adds a reference to the IUnknown added
220 count++;
221 }
222 return sa;
223 }
224
safeArrayToStringArray(SAFEARRAY * inArray)225 CFArrayRef MarshallingHelpers::safeArrayToStringArray(SAFEARRAY* inArray)
226 {
227 long lBound=0, uBound=-1;
228 HRESULT hr = ::SafeArrayGetLBound(inArray, 1, &lBound);
229 if (SUCCEEDED(hr))
230 hr = ::SafeArrayGetUBound(inArray, 1, &uBound);
231 long len = (SUCCEEDED(hr)) ? (uBound-lBound+1) : 0;
232 CFStringRef* items = 0;
233 if (len > 0) {
234 items = new CFStringRef[len];
235 for (; lBound <= uBound; lBound++) {
236 BSTR str;
237 hr = ::SafeArrayGetElement(inArray, &lBound, &str);
238 items[lBound] = BSTRToCFStringRef(str);
239 SysFreeString(str);
240 }
241 }
242 CFArrayRef result = CFArrayCreate(0, (const void**)items, len, &kCFTypeArrayCallBacks);
243 if (items)
244 delete[] items;
245 return result;
246 }
247
safeArrayToIntArray(SAFEARRAY * inArray)248 CFArrayRef MarshallingHelpers::safeArrayToIntArray(SAFEARRAY* inArray)
249 {
250 long lBound=0, uBound=-1;
251 HRESULT hr = ::SafeArrayGetLBound(inArray, 1, &lBound);
252 if (SUCCEEDED(hr))
253 hr = ::SafeArrayGetUBound(inArray, 1, &uBound);
254 long len = (SUCCEEDED(hr)) ? (uBound-lBound+1) : 0;
255 CFNumberRef* items = 0;
256 if (len > 0) {
257 items = new CFNumberRef[len];
258 for (; lBound <= uBound; lBound++) {
259 int num;
260 hr = ::SafeArrayGetElement(inArray, &lBound, &num);
261 items[lBound] = intToCFNumberRef(num);
262 }
263 }
264 CFArrayRef result = CFArrayCreate(0, (const void**) items, len, &kCFTypeArrayCallBacks);
265 if (items)
266 delete[] items;
267 return result;
268 }
269
safeArrayToIUnknownArray(SAFEARRAY * inArray)270 CFArrayRef MarshallingHelpers::safeArrayToIUnknownArray(SAFEARRAY* inArray)
271 {
272 long lBound=0, uBound=-1;
273 HRESULT hr = ::SafeArrayGetLBound(inArray, 1, &lBound);
274 if (SUCCEEDED(hr))
275 hr = ::SafeArrayGetUBound(inArray, 1, &uBound);
276 long len = (SUCCEEDED(hr)) ? (uBound-lBound+1) : 0;
277 void* items;
278 hr = ::SafeArrayAccessData(inArray, &items);
279 CFArrayRef result = CFArrayCreate(0, (const void**) items, len, &kIUnknownArrayCallBacks);
280 hr = ::SafeArrayUnaccessData(inArray);
281 return result;
282 }
283
IUnknownRetainCallback(CFAllocatorRef,const void * value)284 const void* MarshallingHelpers::IUnknownRetainCallback(CFAllocatorRef /*allocator*/, const void* value)
285 {
286 ((IUnknown*) value)->AddRef();
287 return value;
288 }
289
IUnknownReleaseCallback(CFAllocatorRef,const void * value)290 void MarshallingHelpers::IUnknownReleaseCallback(CFAllocatorRef /*allocator*/, const void* value)
291 {
292 ((IUnknown*) value)->Release();
293 }
294