• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }