urlmon: SecManagerImpl_QueryInterface clean up.
[wine] / dlls / mshtml / npplugin.c
1 /*
2  * Copyright 2010 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
23 #define COBJMACROS
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "ole2.h"
29 #include "shlobj.h"
30
31 #include "mshtml_private.h"
32 #include "pluginhost.h"
33
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37
38 /* Parts of npapi.h */
39
40 #define NP_VERSION_MAJOR 0
41 #define NP_VERSION_MINOR 25
42
43 typedef unsigned char NPBool;
44 typedef INT16 NPError;
45 typedef INT16 NPReason;
46 typedef char *NPMIMEType;
47
48 typedef struct _NPP {
49     void *pdata;
50     void *ndata;
51 } NPP_t, *NPP;
52
53 typedef struct _NPStream {
54     void *pdata;
55     void *ndata;
56     const char *url;
57     UINT32 end;
58     UINT32 lastmodified;
59     void *notifyData;
60     const char *headers;
61 } NPStream;
62
63 typedef struct _NPSavedData {
64     INT32 len;
65     void *buf;
66 } NPSavedData;
67
68 typedef struct _NPRect {
69     UINT16 top;
70     UINT16 left;
71     UINT16 bottom;
72     UINT16 right;
73 } NPRect;
74
75 typedef enum {
76     NPFocusNext = 0,
77     NPFocusPrevious = 1
78 } NPFocusDirection;
79
80 #define NP_ABI_MASK 0
81
82 typedef enum {
83     NPPVpluginNameString = 1,
84     NPPVpluginDescriptionString,
85     NPPVpluginWindowBool,
86     NPPVpluginTransparentBool,
87     NPPVjavaClass,
88     NPPVpluginWindowSize,
89     NPPVpluginTimerInterval,
90     NPPVpluginScriptableInstance = (10 | NP_ABI_MASK),
91     NPPVpluginScriptableIID = 11,
92     NPPVjavascriptPushCallerBool = 12,
93     NPPVpluginKeepLibraryInMemory = 13,
94     NPPVpluginNeedsXEmbed = 14,
95     NPPVpluginScriptableNPObject = 15,
96     NPPVformValue = 16,
97     NPPVpluginUrlRequestsDisplayedBool = 17,
98     NPPVpluginWantsAllNetworkStreams = 18,
99     NPPVpluginNativeAccessibleAtkPlugId = 19,
100     NPPVpluginCancelSrcStream = 20,
101     NPPVSupportsAdvancedKeyHandling = 21
102 } NPPVariable;
103
104 typedef enum {
105     NPNVxDisplay = 1,
106     NPNVxtAppContext,
107     NPNVnetscapeWindow,
108     NPNVjavascriptEnabledBool,
109     NPNVasdEnabledBool,
110     NPNVisOfflineBool,
111     NPNVserviceManager = (10 | NP_ABI_MASK),
112     NPNVDOMElement     = (11 | NP_ABI_MASK),
113     NPNVDOMWindow      = (12 | NP_ABI_MASK),
114     NPNVToolkit        = (13 | NP_ABI_MASK),
115     NPNVSupportsXEmbedBool = 14,
116     NPNVWindowNPObject = 15,
117     NPNVPluginElementNPObject = 16,
118     NPNVSupportsWindowless = 17,
119     NPNVprivateModeBool = 18,
120     NPNVsupportsAdvancedKeyHandling = 21
121 } NPNVariable;
122
123 typedef enum {
124     NPWindowTypeWindow = 1,
125     NPWindowTypeDrawable
126 } NPWindowType;
127
128 typedef struct _NPWindow {
129     void *window;
130     INT32 x;
131     INT32 y;
132     UINT32 width;
133     UINT32 height;
134     NPRect clipRect;
135     NPWindowType type;
136 } NPWindow;
137
138 typedef struct _NPFullPrint {
139     NPBool pluginPrinted;
140     NPBool printOne;
141     void *platformPrint;
142 } NPFullPrint;
143
144 typedef struct _NPEmbedPrint {
145     NPWindow window;
146     void *platformPrint;
147 } NPEmbedPrint;
148
149 typedef struct _NPPrint {
150     UINT16 mode;
151     union {
152         NPFullPrint fullPrint;
153         NPEmbedPrint embedPrint;
154     } print;
155 } NPPrint;
156
157 typedef HRGN NPRegion;
158
159 #define NPERR_BASE                         0
160 #define NPERR_NO_ERROR                    (NPERR_BASE + 0)
161 #define NPERR_GENERIC_ERROR               (NPERR_BASE + 1)
162 #define NPERR_INVALID_INSTANCE_ERROR      (NPERR_BASE + 2)
163 #define NPERR_INVALID_FUNCTABLE_ERROR     (NPERR_BASE + 3)
164 #define NPERR_MODULE_LOAD_FAILED_ERROR    (NPERR_BASE + 4)
165 #define NPERR_OUT_OF_MEMORY_ERROR         (NPERR_BASE + 5)
166 #define NPERR_INVALID_PLUGIN_ERROR        (NPERR_BASE + 6)
167 #define NPERR_INVALID_PLUGIN_DIR_ERROR    (NPERR_BASE + 7)
168 #define NPERR_INCOMPATIBLE_VERSION_ERROR  (NPERR_BASE + 8)
169 #define NPERR_INVALID_PARAM               (NPERR_BASE + 9)
170 #define NPERR_INVALID_URL                 (NPERR_BASE + 10)
171 #define NPERR_FILE_NOT_FOUND              (NPERR_BASE + 11)
172 #define NPERR_NO_DATA                     (NPERR_BASE + 12)
173 #define NPERR_STREAM_NOT_SEEKABLE         (NPERR_BASE + 13)
174
175 /* Parts of npfunctions.h */
176
177 typedef NPError (CDECL *NPP_NewProcPtr)(NPMIMEType,NPP,UINT16,INT16,char**,char**,NPSavedData*);
178 typedef NPError (CDECL *NPP_DestroyProcPtr)(NPP,NPSavedData**);
179 typedef NPError (CDECL *NPP_SetWindowProcPtr)(NPP,NPWindow*);
180 typedef NPError (CDECL *NPP_NewStreamProcPtr)(NPP,NPMIMEType,NPStream*,NPBool,UINT16*);
181 typedef NPError (CDECL *NPP_DestroyStreamProcPtr)(NPP,NPStream*,NPReason);
182 typedef INT32 (CDECL *NPP_WriteReadyProcPtr)(NPP,NPStream*);
183 typedef INT32 (CDECL *NPP_WriteProcPtr)(NPP,NPStream*,INT32,INT32,void*);
184 typedef void (CDECL *NPP_StreamAsFileProcPtr)(NPP,NPStream*,const char*);
185 typedef void (CDECL *NPP_PrintProcPtr)(NPP,NPPrint*);
186 typedef INT16 (CDECL *NPP_HandleEventProcPtr)(NPP,void*);
187 typedef void (CDECL *NPP_URLNotifyProcPtr)(NPP,const char*,NPReason,void*);
188 typedef NPError (CDECL *NPP_GetValueProcPtr)(NPP,NPPVariable,void*);
189 typedef NPError (CDECL *NPP_SetValueProcPtr)(NPP,NPNVariable,void*);
190 typedef NPBool (CDECL *NPP_GotFocusPtr)(NPP,NPFocusDirection);
191 typedef void (CDECL *NPP_LostFocusPtr)(NPP);
192
193 typedef struct _NPPluginFuncs {
194     UINT16 size;
195     UINT16 version;
196     NPP_NewProcPtr newp;
197     NPP_DestroyProcPtr destroy;
198     NPP_SetWindowProcPtr setwindow;
199     NPP_NewStreamProcPtr newstream;
200     NPP_DestroyStreamProcPtr destroystream;
201     NPP_StreamAsFileProcPtr asfile;
202     NPP_WriteReadyProcPtr writeready;
203     NPP_WriteProcPtr write;
204     NPP_PrintProcPtr print;
205     NPP_HandleEventProcPtr event;
206     NPP_URLNotifyProcPtr urlnotify;
207     void *javaClass;
208     NPP_GetValueProcPtr getvalue;
209     NPP_SetValueProcPtr setvalue;
210     NPP_GotFocusPtr gotfocus;
211     NPP_LostFocusPtr lostfocus;
212 } NPPluginFuncs;
213
214 static nsIDOMElement *get_dom_element(NPP instance)
215 {
216     nsISupports *instance_unk = (nsISupports*)instance->ndata;
217     nsIPluginInstance *plugin_instance;
218     nsIDOMElement *elem;
219     nsresult nsres;
220
221     nsres = nsISupports_QueryInterface(instance_unk, &IID_nsIPluginInstance, (void**)&plugin_instance);
222     if(NS_FAILED(nsres)) {
223         ERR("Could not get nsIPluginInstance interface: %08x\n", nsres);
224         return NULL;
225     }
226
227     nsres = nsIPluginInstance_GetDOMElement(plugin_instance, &elem);
228     nsIPluginInstance_Release(plugin_instance);
229     if(NS_FAILED(nsres)) {
230         ERR("GetDOMElement failed: %08x\n", nsres);
231         return NULL;
232     }
233
234     return elem;
235 }
236
237 static HTMLInnerWindow *get_elem_window(nsIDOMElement *elem)
238 {
239     nsIDOMWindow *nswindow;
240     nsIDOMDocument *nsdoc;
241     HTMLOuterWindow *window;
242     nsresult nsres;
243
244     nsres = nsIDOMElement_GetOwnerDocument(elem, &nsdoc);
245     if(NS_FAILED(nsres))
246         return NULL;
247
248     nsres = nsIDOMDocument_GetDefaultView(nsdoc, &nswindow);
249     nsIDOMDocument_Release(nsdoc);
250     if(NS_FAILED(nsres) || !nswindow)
251         return NULL;
252
253     window = nswindow_to_window(nswindow);
254     nsIDOMWindow_Release(nswindow);
255
256     return window->base.inner_window;
257 }
258
259 static BOOL parse_classid(const PRUnichar *classid, CLSID *clsid)
260 {
261     const WCHAR *ptr;
262     unsigned len;
263     HRESULT hres;
264
265     static const PRUnichar clsidW[] = {'c','l','s','i','d',':'};
266
267     if(strncmpiW(classid, clsidW, sizeof(clsidW)/sizeof(WCHAR)))
268         return FALSE;
269
270     ptr = classid + sizeof(clsidW)/sizeof(WCHAR);
271     len = strlenW(ptr);
272
273     if(len == 38) {
274         hres = CLSIDFromString(ptr, clsid);
275     }else if(len == 36) {
276         WCHAR buf[39];
277
278         buf[0] = '{';
279         memcpy(buf+1, ptr, len*sizeof(WCHAR));
280         buf[37] = '}';
281         buf[38] = 0;
282         hres = CLSIDFromString(buf, clsid);
283     }else {
284         return FALSE;
285     }
286
287     return SUCCEEDED(hres);
288 }
289
290 static BOOL get_elem_clsid(nsIDOMElement *elem, CLSID *clsid)
291 {
292     nsAString attr_str, val_str;
293     nsresult nsres;
294     BOOL ret = FALSE;
295
296     static const PRUnichar classidW[] = {'c','l','a','s','s','i','d',0};
297
298     nsAString_InitDepend(&attr_str, classidW);
299     nsAString_Init(&val_str, NULL);
300     nsres = nsIDOMElement_GetAttribute(elem, &attr_str, &val_str);
301     nsAString_Finish(&attr_str);
302     if(NS_SUCCEEDED(nsres)) {
303         const PRUnichar *val;
304
305         nsAString_GetData(&val_str, &val);
306         if(*val)
307             ret = parse_classid(val, clsid);
308     }else {
309         ERR("GetAttribute failed: %08x\n", nsres);
310     }
311
312     nsAString_Finish(&attr_str);
313     return ret;
314 }
315
316 static IUnknown *create_activex_object(HTMLInnerWindow *window, nsIDOMElement *nselem, CLSID *clsid)
317 {
318     IClassFactoryEx *cfex;
319     IClassFactory *cf;
320     IUnknown *obj;
321     DWORD policy;
322     HRESULT hres;
323
324     if(!get_elem_clsid(nselem, clsid)) {
325         WARN("Could not determine element CLSID\n");
326         return NULL;
327     }
328
329     TRACE("clsid %s\n", debugstr_guid(clsid));
330
331     policy = 0;
332     hres = IInternetHostSecurityManager_ProcessUrlAction(&window->doc->IInternetHostSecurityManager_iface,
333             URLACTION_ACTIVEX_RUN, (BYTE*)&policy, sizeof(policy), (BYTE*)clsid, sizeof(GUID), 0, 0);
334     if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
335         WARN("ProcessUrlAction returned %08x %x\n", hres, policy);
336         return NULL;
337     }
338
339     hres = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
340     if(FAILED(hres))
341         return NULL;
342
343     hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex);
344     if(SUCCEEDED(hres)) {
345         FIXME("Use IClassFactoryEx\n");
346         IClassFactoryEx_Release(cfex);
347     }
348
349     hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj);
350     if(FAILED(hres))
351         return NULL;
352
353     return obj;
354 }
355
356 static NPError CDECL NPP_New(NPMIMEType pluginType, NPP instance, UINT16 mode, INT16 argc, char **argn,
357         char **argv, NPSavedData *saved)
358 {
359     nsIDOMElement *nselem;
360     HTMLInnerWindow *window;
361     IUnknown *obj;
362     CLSID clsid;
363     NPError err = NPERR_NO_ERROR;
364
365     TRACE("(%s %p %x %d %p %p %p)\n", debugstr_a(pluginType), instance, mode, argc, argn, argv, saved);
366
367     nselem = get_dom_element(instance);
368     if(!nselem) {
369         ERR("Could not get DOM element\n");
370         return NPERR_GENERIC_ERROR;
371     }
372
373     window = get_elem_window(nselem);
374     if(!window) {
375         ERR("Could not get element's window object\n");
376         nsIDOMElement_Release(nselem);
377         return NPERR_GENERIC_ERROR;
378     }
379
380     obj = create_activex_object(window, nselem, &clsid);
381     if(obj) {
382         PluginHost *host;
383         HRESULT hres;
384
385         hres = create_plugin_host(window->doc, nselem, obj, &clsid, &host);
386         nsIDOMElement_Release(nselem);
387         IUnknown_Release(obj);
388         if(SUCCEEDED(hres))
389             instance->pdata = host;
390         else
391             err = NPERR_GENERIC_ERROR;
392     }else {
393         err = NPERR_GENERIC_ERROR;
394     }
395
396     nsIDOMElement_Release(nselem);
397     return err;
398 }
399
400 static NPError CDECL NPP_Destroy(NPP instance, NPSavedData **save)
401 {
402     PluginHost *host = instance->pdata;
403
404     TRACE("(%p %p)\n", instance, save);
405
406     if(!host)
407         return NPERR_GENERIC_ERROR;
408
409     detach_plugin_host(host);
410     IOleClientSite_Release(&host->IOleClientSite_iface);
411     instance->pdata = NULL;
412     return NPERR_NO_ERROR;
413 }
414
415 static NPError CDECL NPP_SetWindow(NPP instance, NPWindow *window)
416 {
417     PluginHost *host = instance->pdata;
418     RECT pos_rect = {0, 0, window->width, window->height};
419
420     TRACE("(%p %p)\n", instance, window);
421
422     if(!host)
423         return NPERR_GENERIC_ERROR;
424
425     update_plugin_window(host, window->window, &pos_rect);
426     return NPERR_NO_ERROR;
427 }
428
429 static NPError CDECL NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, UINT16 *stype)
430 {
431     TRACE("\n");
432     return NPERR_GENERIC_ERROR;
433 }
434
435 static NPError CDECL NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason)
436 {
437     TRACE("\n");
438     return NPERR_GENERIC_ERROR;
439 }
440
441 static INT32 CDECL NPP_WriteReady(NPP instance, NPStream *stream)
442 {
443     TRACE("\n");
444     return NPERR_GENERIC_ERROR;
445 }
446
447 static INT32 CDECL NPP_Write(NPP instance, NPStream *stream, INT32 offset, INT32 len, void *buffer)
448 {
449     TRACE("\n");
450     return NPERR_GENERIC_ERROR;
451 }
452
453 static void CDECL NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname)
454 {
455     TRACE("\n");
456 }
457
458 static void CDECL NPP_Print(NPP instance, NPPrint *platformPrint)
459 {
460     FIXME("\n");
461 }
462
463 static INT16 CDECL NPP_HandleEvent(NPP instance, void *event)
464 {
465     TRACE("\n");
466     return NPERR_GENERIC_ERROR;
467 }
468
469 static void CDECL NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData)
470 {
471     TRACE("\n");
472 }
473
474 static NPError CDECL NPP_GetValue(NPP instance, NPPVariable variable, void *ret_value)
475 {
476     TRACE("\n");
477     return NPERR_GENERIC_ERROR;
478 }
479
480 static NPError CDECL NPP_SetValue(NPP instance, NPNVariable variable, void *value)
481 {
482     TRACE("\n");
483     return NPERR_GENERIC_ERROR;
484 }
485
486 static NPBool CDECL NPP_GotFocus(NPP instance, NPFocusDirection direction)
487 {
488     FIXME("\n");
489     return NPERR_GENERIC_ERROR;
490 }
491
492 static void CDECL NPP_LostFocus(NPP instance)
493 {
494     FIXME("\n");
495 }
496
497 /***********************************************************************
498  *          NP_GetEntryPoints (mshtml.@)
499  */
500 NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* funcs)
501 {
502     TRACE("(%p)\n", funcs);
503
504     funcs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
505     funcs->newp = NPP_New;
506     funcs->destroy = NPP_Destroy;
507     funcs->setwindow = NPP_SetWindow;
508     funcs->newstream = NPP_NewStream;
509     funcs->destroystream = NPP_DestroyStream;
510     funcs->asfile = NPP_StreamAsFile;
511     funcs->writeready = NPP_WriteReady;
512     funcs->write = NPP_Write;
513     funcs->print = NPP_Print;
514     funcs->event = NPP_HandleEvent;
515     funcs->urlnotify = NPP_URLNotify;
516     funcs->javaClass = NULL;
517     funcs->getvalue = NPP_GetValue;
518     funcs->setvalue = NPP_SetValue;
519     funcs->gotfocus = NPP_GotFocus;
520     funcs->lostfocus = NPP_LostFocus;
521
522     return NPERR_NO_ERROR;
523 }