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 #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