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 "CFDictionaryPropertyBag.h" 29 30 #include "MarshallingHelpers.h" 31 #include "WebKit.h" 32 33 // CFDictionaryPropertyBag ----------------------------------------------- 34 35 CFDictionaryPropertyBag::CFDictionaryPropertyBag() 36 : m_refCount(0) 37 { 38 gClassCount++; 39 gClassNameCount.add("CFDictionaryPropertyBag"); 40 } 41 42 CFDictionaryPropertyBag::~CFDictionaryPropertyBag() 43 { 44 gClassCount--; 45 gClassNameCount.remove("CFDictionaryPropertyBag"); 46 } 47 48 COMPtr<CFDictionaryPropertyBag> CFDictionaryPropertyBag::createInstance() 49 { 50 return new CFDictionaryPropertyBag; 51 } 52 53 void CFDictionaryPropertyBag::setDictionary(CFMutableDictionaryRef dictionary) 54 { 55 m_dictionary = dictionary; 56 } 57 58 CFMutableDictionaryRef CFDictionaryPropertyBag::dictionary() const 59 { 60 return m_dictionary.get(); 61 } 62 63 // IUnknown ------------------------------------------------------------------- 64 65 HRESULT STDMETHODCALLTYPE CFDictionaryPropertyBag::QueryInterface(REFIID riid, void** ppvObject) 66 { 67 *ppvObject = 0; 68 if (IsEqualGUID(riid, IID_IUnknown)) 69 *ppvObject = static_cast<IPropertyBag*>(this); 70 else if (IsEqualGUID(riid, IID_IPropertyBag)) 71 *ppvObject = static_cast<IPropertyBag*>(this); 72 else if (IsEqualGUID(riid, __uuidof(this))) 73 *ppvObject = this; 74 else 75 return E_NOINTERFACE; 76 77 AddRef(); 78 return S_OK; 79 } 80 81 ULONG STDMETHODCALLTYPE CFDictionaryPropertyBag::AddRef(void) 82 { 83 return ++m_refCount; 84 } 85 86 ULONG STDMETHODCALLTYPE CFDictionaryPropertyBag::Release(void) 87 { 88 ULONG newRef = --m_refCount; 89 if (!newRef) 90 delete(this); 91 92 return newRef; 93 } 94 95 // IPropertyBag ------------------------------------------------------------ 96 97 static bool ConvertCFTypeToVariant(VARIANT* pVar, void* cfObj) 98 { 99 if (!cfObj) { 100 V_VT(pVar) = VT_NULL; 101 return true; 102 } 103 else { 104 // if caller expects a string, retrieve BSTR from CFStringRef 105 if (V_VT(pVar) == VT_BSTR) { 106 V_BSTR(pVar) = MarshallingHelpers::CFStringRefToBSTR((CFStringRef) cfObj); 107 return true; 108 } else if (V_VT(pVar) == VT_I4) { 109 V_I4(pVar) = MarshallingHelpers::CFNumberRefToInt((CFNumberRef) cfObj); 110 return true; 111 } else if (!!(V_VT(pVar)&VT_ARRAY)) { 112 if ((V_VT(pVar)&~VT_ARRAY) == VT_BSTR) { 113 V_ARRAY(pVar) = MarshallingHelpers::stringArrayToSafeArray((CFArrayRef) cfObj); 114 return true; 115 } else if ((V_VT(pVar)&~VT_ARRAY) == VT_I4) { 116 V_ARRAY(pVar) = MarshallingHelpers::intArrayToSafeArray((CFArrayRef) cfObj); 117 return true; 118 } else if ((V_VT(pVar)&~VT_ARRAY) == VT_UNKNOWN) { 119 V_ARRAY(pVar) = MarshallingHelpers::iunknownArrayToSafeArray((CFArrayRef) cfObj); 120 return true; 121 } 122 } 123 } 124 return false; 125 } 126 127 static bool ConvertVariantToCFType(VARIANT* pVar, void** cfObj) 128 { 129 if (V_VT(pVar) == VT_NULL) { 130 *cfObj = 0; 131 return true; 132 } 133 else { 134 // if caller expects a string, retrieve BSTR from CFStringRef 135 if (V_VT(pVar) == VT_BSTR) { 136 *cfObj = (void*) MarshallingHelpers::BSTRToCFStringRef(V_BSTR(pVar)); 137 return true; 138 } else if (V_VT(pVar) == VT_I4) { 139 *cfObj = (void*) MarshallingHelpers::intToCFNumberRef(V_I4(pVar)); 140 return true; 141 } else if (!!(V_VT(pVar)&VT_ARRAY)) { 142 if ((V_VT(pVar)&~VT_ARRAY) == VT_BSTR) { 143 *cfObj = (void*) MarshallingHelpers::safeArrayToStringArray(V_ARRAY(pVar)); 144 return true; 145 } else if ((V_VT(pVar)&~VT_ARRAY) == VT_I4) { 146 *cfObj = (void*) MarshallingHelpers::safeArrayToIntArray(V_ARRAY(pVar)); 147 return true; 148 } else if ((V_VT(pVar)&~VT_ARRAY) == VT_UNKNOWN) { 149 *cfObj = (void*) MarshallingHelpers::safeArrayToIUnknownArray(V_ARRAY(pVar)); 150 return true; 151 } 152 } 153 } 154 return false; 155 } 156 157 HRESULT STDMETHODCALLTYPE CFDictionaryPropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog * /*pErrorLog*/) 158 { 159 if (!pszPropName) 160 return E_POINTER; 161 if (m_dictionary) { 162 void* value; 163 CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(pszPropName); 164 HRESULT hr = E_FAIL; 165 if (CFDictionaryGetValueIfPresent(m_dictionary.get(), key, (const void**) &value)) { 166 if (ConvertCFTypeToVariant(pVar, value)) 167 hr = S_OK; 168 } else 169 hr = E_INVALIDARG; 170 CFRelease(key); 171 return hr; 172 } 173 return E_FAIL; 174 } 175 176 HRESULT STDMETHODCALLTYPE CFDictionaryPropertyBag::Write(LPCOLESTR pszPropName, VARIANT* pVar) 177 { 178 if (!pszPropName || !pVar) 179 return E_POINTER; 180 if (!m_dictionary) { 181 m_dictionary.adoptCF(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); 182 } 183 void* cfObj; 184 if (ConvertVariantToCFType(pVar, &cfObj)) { 185 CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(pszPropName); 186 CFDictionaryAddValue(m_dictionary.get(), key, cfObj); 187 // CFDictionaryAddValue should automatically retain the CF objects passed in, so release them here 188 CFRelease(key); 189 CFRelease(cfObj); 190 return S_OK; 191 } 192 return E_FAIL; 193 }