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 #include "MathExtras.h"
30
31 #pragma warning(push, 0)
32 #include <WebCore/IntRect.h>
33 #include <WebCore/KURL.h>
34 #include <WebCore/PlatformString.h>
35 #pragma warning(pop)
36
37 using namespace WebCore;
38
39 static const double secondsPerDay = 60 * 60 * 24;
40
41 CFArrayCallBacks MarshallingHelpers::kIUnknownArrayCallBacks = {0, IUnknownRetainCallback, IUnknownReleaseCallback, 0, 0};
42 CFDictionaryValueCallBacks MarshallingHelpers::kIUnknownDictionaryValueCallBacks = {0, IUnknownRetainCallback, IUnknownReleaseCallback, 0, 0};
43
BSTRToKURL(BSTR urlStr)44 KURL MarshallingHelpers::BSTRToKURL(BSTR urlStr)
45 {
46 return KURL(KURL(), String(urlStr, SysStringLen(urlStr)));
47 }
48
KURLToBSTR(const KURL & url)49 BSTR MarshallingHelpers::KURLToBSTR(const KURL& url)
50 {
51 return SysAllocStringLen(url.string().characters(), url.string().length());
52 }
53
PathStringToFileCFURLRef(const String & string)54 CFURLRef MarshallingHelpers::PathStringToFileCFURLRef(const String& string)
55 {
56 CFStringRef cfPath = CFStringCreateWithCharactersNoCopy(0, (const UniChar*)string.characters(), string.length(), kCFAllocatorNull);
57 CFURLRef pathURL = CFURLCreateWithFileSystemPath(0, cfPath, kCFURLWindowsPathStyle, false);
58 CFRelease(cfPath);
59 return pathURL;
60 }
61
FileCFURLRefToPathString(CFURLRef fileURL)62 String MarshallingHelpers::FileCFURLRefToPathString(CFURLRef fileURL)
63 {
64 CFStringRef string = CFURLCopyFileSystemPath(fileURL, kCFURLWindowsPathStyle);
65 String result(string);
66 CFRelease(string);
67 return result;
68 }
69
BSTRToCFURLRef(BSTR urlStr)70 CFURLRef MarshallingHelpers::BSTRToCFURLRef(BSTR urlStr)
71 {
72 CFStringRef urlCFString = BSTRToCFStringRef(urlStr);
73 if (!urlCFString)
74 return 0;
75
76 CFURLRef urlRef = CFURLCreateWithString(0, urlCFString, 0);
77 CFRelease(urlCFString);
78
79 return urlRef;
80 }
81
BSTRToCFStringRef(BSTR str)82 CFStringRef MarshallingHelpers::BSTRToCFStringRef(BSTR str)
83 {
84 return CFStringCreateWithCharacters(0, (const UniChar*)(str ? str : TEXT("")), SysStringLen(str));
85 }
86
LPCOLESTRToCFStringRef(LPCOLESTR str)87 CFStringRef MarshallingHelpers::LPCOLESTRToCFStringRef(LPCOLESTR str)
88 {
89 return CFStringCreateWithCharacters(0, (const UniChar*)(str ? str : TEXT("")), (CFIndex)(str ? wcslen(str) : 0));
90 }
91
CFStringRefToBSTR(CFStringRef str)92 BSTR MarshallingHelpers::CFStringRefToBSTR(CFStringRef str)
93 {
94 if (!str)
95 return 0;
96
97 const UniChar* uniChars = CFStringGetCharactersPtr(str);
98 if (uniChars)
99 return SysAllocStringLen((LPCTSTR)uniChars, CFStringGetLength(str));
100
101 CFIndex length = CFStringGetLength(str);
102 BSTR bstr = SysAllocStringLen(0, length);
103 if (bstr) {
104 CFStringGetCharacters(str, CFRangeMake(0, length), (UniChar*)bstr);
105 bstr[length] = 0;
106 }
107 return bstr;
108 }
109
CFNumberRefToInt(CFNumberRef num)110 int MarshallingHelpers::CFNumberRefToInt(CFNumberRef num)
111 {
112 int number;
113 CFNumberGetValue(num, kCFNumberIntType, &number);
114 return number;
115 }
116
intToCFNumberRef(int num)117 CFNumberRef MarshallingHelpers::intToCFNumberRef(int num)
118 {
119 return CFNumberCreate(0, kCFNumberSInt32Type, &num);
120 }
121
windowsEpochAbsoluteTime()122 CFAbsoluteTime MarshallingHelpers::windowsEpochAbsoluteTime()
123 {
124 static CFAbsoluteTime windowsEpochAbsoluteTime = 0;
125 if (!windowsEpochAbsoluteTime) {
126 CFGregorianDate windowsEpochDate = {1899, 12, 30, 0, 0, 0.0};
127 windowsEpochAbsoluteTime = CFGregorianDateGetAbsoluteTime(windowsEpochDate, 0) / secondsPerDay;
128 }
129 return windowsEpochAbsoluteTime;
130 }
131
DATEToCFAbsoluteTime(DATE date)132 CFAbsoluteTime MarshallingHelpers::DATEToCFAbsoluteTime(DATE date)
133 {
134 // <http://msdn2.microsoft.com/en-us/library/ms221627.aspx>
135 // DATE: This is the same numbering system used by most spreadsheet programs,
136 // although some specify incorrectly that February 29, 1900 existed, and thus
137 // set January 1, 1900 to 1.0. The date can be converted to and from an MS-DOS
138 // representation using VariantTimeToDosDateTime, which is discussed in
139 // Conversion and Manipulation Functions.
140
141 // CFAbsoluteTime: Type used to represent a specific point in time relative
142 // to the absolute reference date of 1 Jan 2001 00:00:00 GMT.
143 // Absolute time is measured by the number of seconds between the reference
144 // date and the specified date. Negative values indicate dates/times before
145 // the reference date. Positive values indicate dates/times after the
146 // reference date.
147
148 return round((date + windowsEpochAbsoluteTime()) * secondsPerDay);
149 }
150
CFAbsoluteTimeToDATE(CFAbsoluteTime absoluteTime)151 DATE MarshallingHelpers::CFAbsoluteTimeToDATE(CFAbsoluteTime absoluteTime)
152 {
153 return (round(absoluteTime)/secondsPerDay - windowsEpochAbsoluteTime());
154 }
155
156 // utility method to store a 1-dim string vector into a newly created SAFEARRAY
stringArrayToSafeArray(CFArrayRef inArray)157 SAFEARRAY* MarshallingHelpers::stringArrayToSafeArray(CFArrayRef inArray)
158 {
159 CFIndex size = CFArrayGetCount(inArray);
160 SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_BSTR, 0, (ULONG) size, 0);
161 long count = 0;
162 for (CFIndex i=0; i<size; i++) {
163 CFStringRef item = (CFStringRef) CFArrayGetValueAtIndex(inArray, i);
164 BSTR bstr = CFStringRefToBSTR(item);
165 ::SafeArrayPutElement(sa, &count, bstr);
166 SysFreeString(bstr); // SafeArrayPutElement() should make a copy of the string
167 count++;
168 }
169 return sa;
170 }
171
172 // utility method to store a 1-dim int vector into a newly created SAFEARRAY
intArrayToSafeArray(CFArrayRef inArray)173 SAFEARRAY* MarshallingHelpers::intArrayToSafeArray(CFArrayRef inArray)
174 {
175 CFIndex size = CFArrayGetCount(inArray);
176 SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_I4, 0, (ULONG) size, 0);
177 long count = 0;
178 for (CFIndex i=0; i<size; i++) {
179 CFNumberRef item = (CFNumberRef) CFArrayGetValueAtIndex(inArray, i);
180 int number = CFNumberRefToInt(item);
181 ::SafeArrayPutElement(sa, &count, &number);
182 count++;
183 }
184 return sa;
185 }
186
intRectToSafeArray(const WebCore::IntRect & rect)187 SAFEARRAY* MarshallingHelpers::intRectToSafeArray(const WebCore::IntRect& rect)
188 {
189 SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_I4, 0, 4, 0);
190 long count = 0;
191 int value;
192
193 value = rect.x();
194 ::SafeArrayPutElement(sa, &count, &value);
195 count++;
196
197 value = rect.y();
198 ::SafeArrayPutElement(sa, &count, &value);
199 count++;
200
201 value = rect.width();
202 ::SafeArrayPutElement(sa, &count, &value);
203 count++;
204
205 value = rect.height();
206 ::SafeArrayPutElement(sa, &count, &value);
207 count++;
208
209 return sa;
210 }
211
212 // utility method to store a 1-dim IUnknown* vector into a newly created SAFEARRAY
iunknownArrayToSafeArray(CFArrayRef inArray)213 SAFEARRAY* MarshallingHelpers::iunknownArrayToSafeArray(CFArrayRef inArray)
214 {
215 CFIndex size = CFArrayGetCount(inArray);
216 SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_UNKNOWN, 0, (ULONG) size, (LPVOID)&IID_IUnknown);
217 long count = 0;
218 for (CFIndex i=0; i<size; i++) {
219 IUnknown* item = (IUnknown*) CFArrayGetValueAtIndex(inArray, i);
220 ::SafeArrayPutElement(sa, &count, item); // SafeArrayPutElement() adds a reference to the IUnknown added
221 count++;
222 }
223 return sa;
224 }
225
safeArrayToStringArray(SAFEARRAY * inArray)226 CFArrayRef MarshallingHelpers::safeArrayToStringArray(SAFEARRAY* inArray)
227 {
228 long lBound=0, uBound=-1;
229 HRESULT hr = ::SafeArrayGetLBound(inArray, 1, &lBound);
230 if (SUCCEEDED(hr))
231 hr = ::SafeArrayGetUBound(inArray, 1, &uBound);
232 long len = (SUCCEEDED(hr)) ? (uBound-lBound+1) : 0;
233 CFStringRef* items = 0;
234 if (len > 0) {
235 items = new CFStringRef[len];
236 for (; lBound <= uBound; lBound++) {
237 BSTR str;
238 hr = ::SafeArrayGetElement(inArray, &lBound, &str);
239 items[lBound] = BSTRToCFStringRef(str);
240 SysFreeString(str);
241 }
242 }
243 CFArrayRef result = CFArrayCreate(0, (const void**)items, len, &kCFTypeArrayCallBacks);
244 if (items)
245 delete[] items;
246 return result;
247 }
248
safeArrayToIntArray(SAFEARRAY * inArray)249 CFArrayRef MarshallingHelpers::safeArrayToIntArray(SAFEARRAY* inArray)
250 {
251 long lBound=0, uBound=-1;
252 HRESULT hr = ::SafeArrayGetLBound(inArray, 1, &lBound);
253 if (SUCCEEDED(hr))
254 hr = ::SafeArrayGetUBound(inArray, 1, &uBound);
255 long len = (SUCCEEDED(hr)) ? (uBound-lBound+1) : 0;
256 CFNumberRef* items = 0;
257 if (len > 0) {
258 items = new CFNumberRef[len];
259 for (; lBound <= uBound; lBound++) {
260 int num;
261 hr = ::SafeArrayGetElement(inArray, &lBound, &num);
262 items[lBound] = intToCFNumberRef(num);
263 }
264 }
265 CFArrayRef result = CFArrayCreate(0, (const void**) items, len, &kCFTypeArrayCallBacks);
266 if (items)
267 delete[] items;
268 return result;
269 }
270
safeArrayToIUnknownArray(SAFEARRAY * inArray)271 CFArrayRef MarshallingHelpers::safeArrayToIUnknownArray(SAFEARRAY* inArray)
272 {
273 long lBound=0, uBound=-1;
274 HRESULT hr = ::SafeArrayGetLBound(inArray, 1, &lBound);
275 if (SUCCEEDED(hr))
276 hr = ::SafeArrayGetUBound(inArray, 1, &uBound);
277 long len = (SUCCEEDED(hr)) ? (uBound-lBound+1) : 0;
278 void* items;
279 hr = ::SafeArrayAccessData(inArray, &items);
280 CFArrayRef result = CFArrayCreate(0, (const void**) items, len, &kIUnknownArrayCallBacks);
281 hr = ::SafeArrayUnaccessData(inArray);
282 return result;
283 }
284
IUnknownRetainCallback(CFAllocatorRef,const void * value)285 const void* MarshallingHelpers::IUnknownRetainCallback(CFAllocatorRef /*allocator*/, const void* value)
286 {
287 ((IUnknown*) value)->AddRef();
288 return value;
289 }
290
IUnknownReleaseCallback(CFAllocatorRef,const void * value)291 void MarshallingHelpers::IUnknownReleaseCallback(CFAllocatorRef /*allocator*/, const void* value)
292 {
293 ((IUnknown*) value)->Release();
294 }
295