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
impl_from_IHtmlLoadOptions(IHtmlLoadOptions * iface)37 static inline HTMLLoadOptions *impl_from_IHtmlLoadOptions(IHtmlLoadOptions *iface)
38 {
39 return CONTAINING_RECORD(iface, HTMLLoadOptions, IHtmlLoadOptions_iface);
40 }
41
HtmlLoadOptions_QueryInterface(IHtmlLoadOptions * iface,REFIID riid,void ** ppv)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
HtmlLoadOptions_AddRef(IHtmlLoadOptions * iface)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
HtmlLoadOptions_Release(IHtmlLoadOptions * iface)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
HtmlLoadOptions_QueryOption(IHtmlLoadOptions * iface,DWORD dwOption,LPVOID pBuffer,ULONG * pcbBuf)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
HtmlLoadOptions_SetOption(IHtmlLoadOptions * iface,DWORD dwOption,LPVOID pBuffer,ULONG cbBuf)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
HTMLLoadOptions_Create(IUnknown * pUnkOuter,REFIID riid,void ** ppv)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