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