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 44 KURL MarshallingHelpers::BSTRToKURL(BSTR urlStr) 45 { 46 return KURL(KURL(), String(urlStr, SysStringLen(urlStr))); 47 } 48 49 BSTR MarshallingHelpers::KURLToBSTR(const KURL& url) 50 { 51 return SysAllocStringLen(url.string().characters(), url.string().length()); 52 } 53 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 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 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 82 CFStringRef MarshallingHelpers::BSTRToCFStringRef(BSTR str) 83 { 84 return CFStringCreateWithCharacters(0, (const UniChar*)(str ? str : TEXT("")), SysStringLen(str)); 85 } 86 87 CFStringRef MarshallingHelpers::LPCOLESTRToCFStringRef(LPCOLESTR str) 88 { 89 return CFStringCreateWithCharacters(0, (const UniChar*)(str ? str : TEXT("")), (CFIndex)(str ? wcslen(str) : 0)); 90 } 91 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 110 int MarshallingHelpers::CFNumberRefToInt(CFNumberRef num) 111 { 112 int number; 113 CFNumberGetValue(num, kCFNumberIntType, &number); 114 return number; 115 } 116 117 CFNumberRef MarshallingHelpers::intToCFNumberRef(int num) 118 { 119 return CFNumberCreate(0, kCFNumberSInt32Type, &num); 120 } 121 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 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 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 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 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 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 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 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 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 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 285 const void* MarshallingHelpers::IUnknownRetainCallback(CFAllocatorRef /*allocator*/, const void* value) 286 { 287 ((IUnknown*) value)->AddRef(); 288 return value; 289 } 290 291 void MarshallingHelpers::IUnknownReleaseCallback(CFAllocatorRef /*allocator*/, const void* value) 292 { 293 ((IUnknown*) value)->Release(); 294 } 295