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