1 /* 2 * Copyright 2006 Jacek Caban for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "mshtml_private.h" 20 21 typedef struct load_opt { 22 DWORD option; 23 PVOID buffer; 24 DWORD size; 25 26 struct load_opt *next; 27 } load_opt; 28 29 typedef struct { 30 IHtmlLoadOptions IHtmlLoadOptions_iface; 31 32 LONG ref; 33 34 load_opt *opts; 35 } HTMLLoadOptions; 36 37 static inline HTMLLoadOptions *impl_from_IHtmlLoadOptions(IHtmlLoadOptions *iface) 38 { 39 return CONTAINING_RECORD(iface, HTMLLoadOptions, IHtmlLoadOptions_iface); 40 } 41 42 static HRESULT WINAPI HtmlLoadOptions_QueryInterface(IHtmlLoadOptions *iface, 43 REFIID riid, void **ppv) 44 { 45 HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface); 46 47 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); 48 49 if(IsEqualGUID(&IID_IUnknown, riid)) { 50 *ppv = &This->IHtmlLoadOptions_iface; 51 }else if(IsEqualGUID(&IID_IOptionArray, riid)) { 52 *ppv = &This->IHtmlLoadOptions_iface; 53 }else if(IsEqualGUID(&IID_IHtmlLoadOptions, riid)) { 54 *ppv = &This->IHtmlLoadOptions_iface; 55 }else { 56 *ppv = NULL; 57 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); 58 return E_NOINTERFACE; 59 } 60 61 IUnknown_AddRef((IUnknown*)*ppv); 62 return S_OK; 63 } 64 65 static ULONG WINAPI HtmlLoadOptions_AddRef(IHtmlLoadOptions *iface) 66 { 67 HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface); 68 LONG ref = InterlockedIncrement(&This->ref); 69 70 TRACE("(%p) ref=%d\n", This, ref); 71 72 return ref; 73 } 74 75 static ULONG WINAPI HtmlLoadOptions_Release(IHtmlLoadOptions *iface) 76 { 77 HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface); 78 LONG ref = InterlockedDecrement(&This->ref); 79 80 TRACE("(%p) ref=%d\n", This, ref); 81 82 if(!ref) { 83 load_opt *iter = This->opts, *last; 84 85 while(iter) { 86 last = iter; 87 iter = iter->next; 88 89 heap_free(last->buffer); 90 heap_free(last); 91 } 92 93 heap_free(This); 94 } 95 96 return ref; 97 } 98 99 static HRESULT WINAPI HtmlLoadOptions_QueryOption(IHtmlLoadOptions *iface, DWORD dwOption, 100 LPVOID pBuffer, ULONG *pcbBuf) 101 { 102 HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface); 103 load_opt *iter; 104 105 TRACE("(%p)->(%d %p %p)\n", This, dwOption, pBuffer, pcbBuf); 106 107 for(iter = This->opts; iter; iter = iter->next) { 108 if(iter->option == dwOption) 109 break; 110 } 111 112 if(!iter) { 113 *pcbBuf = 0; 114 return S_OK; 115 } 116 117 if(*pcbBuf < iter->size) { 118 *pcbBuf = iter->size; 119 return E_FAIL; 120 } 121 122 memcpy(pBuffer, iter->buffer, iter->size); 123 *pcbBuf = iter->size; 124 125 return S_OK; 126 } 127 128 static HRESULT WINAPI HtmlLoadOptions_SetOption(IHtmlLoadOptions *iface, DWORD dwOption, 129 LPVOID pBuffer, ULONG cbBuf) 130 { 131 HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface); 132 load_opt *iter = NULL; 133 134 TRACE("(%p)->(%d %p %d)\n", This, dwOption, pBuffer, cbBuf); 135 136 for(iter = This->opts; iter; iter = iter->next) { 137 if(iter->option == dwOption) 138 break; 139 } 140 141 if(!iter) { 142 iter = heap_alloc(sizeof(load_opt)); 143 iter->next = This->opts; 144 This->opts = iter; 145 146 iter->option = dwOption; 147 }else { 148 heap_free(iter->buffer); 149 } 150 151 if(!cbBuf) { 152 iter->buffer = NULL; 153 iter->size = 0; 154 155 return S_OK; 156 } 157 158 iter->size = cbBuf; 159 iter->buffer = heap_alloc(cbBuf); 160 memcpy(iter->buffer, pBuffer, iter->size); 161 162 return S_OK; 163 } 164 165 static const IHtmlLoadOptionsVtbl HtmlLoadOptionsVtbl = { 166 HtmlLoadOptions_QueryInterface, 167 HtmlLoadOptions_AddRef, 168 HtmlLoadOptions_Release, 169 HtmlLoadOptions_QueryOption, 170 HtmlLoadOptions_SetOption 171 }; 172 173 HRESULT HTMLLoadOptions_Create(IUnknown *pUnkOuter, REFIID riid, void** ppv) 174 { 175 HTMLLoadOptions *ret; 176 HRESULT hres; 177 178 TRACE("(%p %s %p)\n", pUnkOuter, debugstr_mshtml_guid(riid), ppv); 179 180 ret = heap_alloc(sizeof(HTMLLoadOptions)); 181 if(!ret) 182 return E_OUTOFMEMORY; 183 184 ret->IHtmlLoadOptions_iface.lpVtbl = &HtmlLoadOptionsVtbl; 185 ret->ref = 1; 186 ret->opts = NULL; 187 188 hres = IHtmlLoadOptions_QueryInterface(&ret->IHtmlLoadOptions_iface, riid, ppv); 189 IHtmlLoadOptions_Release(&ret->IHtmlLoadOptions_iface); 190 return hres; 191 } 192