Home | History | Annotate | Download | only in win
      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