winmm: Rearrange device mapping when a new default device is chosen.
[wine] / dlls / mshtml / loadopts.c
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 "config.h"
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "optary.h"
31
32 #include "wine/debug.h"
33
34 #include "mshtml_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37
38 typedef struct load_opt {
39     DWORD option;
40     PVOID buffer;
41     DWORD size;
42
43     struct load_opt *next;
44 } load_opt;
45
46 typedef struct {
47     IHtmlLoadOptions IHtmlLoadOptions_iface;
48
49     LONG ref;
50
51     load_opt *opts;
52 } HTMLLoadOptions;
53
54 static inline HTMLLoadOptions *impl_from_IHtmlLoadOptions(IHtmlLoadOptions *iface)
55 {
56     return CONTAINING_RECORD(iface, HTMLLoadOptions, IHtmlLoadOptions_iface);
57 }
58
59 static HRESULT WINAPI HtmlLoadOptions_QueryInterface(IHtmlLoadOptions *iface,
60         REFIID riid, void **ppv)
61 {
62     HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface);
63
64     *ppv = NULL;
65
66     if(IsEqualGUID(&IID_IUnknown, riid)) {
67         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
68         *ppv = &This->IHtmlLoadOptions_iface;
69     }else if(IsEqualGUID(&IID_IOptionArray, riid)) {
70         TRACE("(%p)->(IID_IOptionArray %p)\n", This, ppv);
71         *ppv = &This->IHtmlLoadOptions_iface;
72     }else if(IsEqualGUID(&IID_IHtmlLoadOptions, riid)) {
73         TRACE("(%p)->(IID_IHtmlLoadOptions %p)\n", This, ppv);
74         *ppv = &This->IHtmlLoadOptions_iface;
75     }
76
77     if(*ppv) {
78         IHtmlLoadOptions_AddRef(&This->IHtmlLoadOptions_iface);
79         return S_OK;
80     }
81
82     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
83     return E_NOINTERFACE;
84 }
85
86 static ULONG WINAPI HtmlLoadOptions_AddRef(IHtmlLoadOptions *iface)
87 {
88     HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface);
89     LONG ref = InterlockedIncrement(&This->ref);
90
91     TRACE("(%p) ref=%d\n", This, ref);
92
93     return ref;
94 }
95
96 static ULONG WINAPI HtmlLoadOptions_Release(IHtmlLoadOptions *iface)
97 {
98     HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface);
99     LONG ref = InterlockedDecrement(&This->ref);
100
101     TRACE("(%p) ref=%d\n", This, ref);
102
103     if(!ref) {
104         load_opt *iter = This->opts, *last;
105
106         while(iter) {
107             last = iter;
108             iter = iter->next;
109
110             heap_free(last->buffer);
111             heap_free(last);
112         }
113
114         heap_free(This);
115     }
116
117     return ref;
118 }
119
120 static HRESULT WINAPI HtmlLoadOptions_QueryOption(IHtmlLoadOptions *iface, DWORD dwOption,
121         LPVOID pBuffer, ULONG *pcbBuf)
122 {
123     HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface);
124     load_opt *iter;
125
126     TRACE("(%p)->(%d %p %p)\n", This, dwOption, pBuffer, pcbBuf);
127
128     for(iter = This->opts; iter; iter = iter->next) {
129         if(iter->option == dwOption)
130             break;
131     }
132
133     if(!iter) {
134         *pcbBuf = 0;
135         return S_OK;
136     }
137
138     if(*pcbBuf < iter->size) {
139         *pcbBuf = iter->size;
140         return E_FAIL;
141     }
142
143     memcpy(pBuffer, iter->buffer, iter->size);
144     *pcbBuf = iter->size;
145
146     return S_OK;
147 }
148
149 static HRESULT WINAPI HtmlLoadOptions_SetOption(IHtmlLoadOptions *iface, DWORD dwOption,
150         LPVOID pBuffer, ULONG cbBuf)
151 {
152     HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface);
153     load_opt *iter = NULL;
154
155     TRACE("(%p)->(%d %p %d)\n", This, dwOption, pBuffer, cbBuf);
156
157     for(iter = This->opts; iter; iter = iter->next) {
158         if(iter->option == dwOption)
159             break;
160     }
161
162     if(!iter) {
163         iter = heap_alloc(sizeof(load_opt));
164         iter->next = This->opts;
165         This->opts = iter;
166
167         iter->option = dwOption;
168     }else {
169         heap_free(iter->buffer);
170     }
171
172     if(!cbBuf) {
173         iter->buffer = NULL;
174         iter->size = 0;
175
176         return S_OK;
177     }
178
179     iter->size = cbBuf;
180     iter->buffer = heap_alloc(cbBuf);
181     memcpy(iter->buffer, pBuffer, iter->size);
182
183     return S_OK;
184 }
185
186 static const IHtmlLoadOptionsVtbl HtmlLoadOptionsVtbl = {
187     HtmlLoadOptions_QueryInterface,
188     HtmlLoadOptions_AddRef,
189     HtmlLoadOptions_Release,
190     HtmlLoadOptions_QueryOption,
191     HtmlLoadOptions_SetOption
192 };
193
194 HRESULT HTMLLoadOptions_Create(IUnknown *pUnkOuter, REFIID riid, void** ppv)
195 {
196     HTMLLoadOptions *ret;
197     HRESULT hres;
198
199     TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
200
201     ret = heap_alloc(sizeof(HTMLLoadOptions));
202
203     ret->IHtmlLoadOptions_iface.lpVtbl = &HtmlLoadOptionsVtbl;
204     ret->ref = 1;
205     ret->opts = NULL;
206
207     hres = IHtmlLoadOptions_QueryInterface(&ret->IHtmlLoadOptions_iface, riid, ppv);
208     IHtmlLoadOptions_Release(&ret->IHtmlLoadOptions_iface);
209
210     return hres;
211 }