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