| /* |
| * Copyright 2010 Jacek Caban for CodeWeavers |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "config.h" |
| |
| #include <stdarg.h> |
| |
| #define COBJMACROS |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "winuser.h" |
| #include "ole2.h" |
| #include "shlobj.h" |
| |
| #include "mshtml_private.h" |
| #include "pluginhost.h" |
| |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(mshtml); |
| |
| /* Parts of npapi.h */ |
| |
| #define NP_VERSION_MAJOR 0 |
| #define NP_VERSION_MINOR 25 |
| |
| typedef unsigned char NPBool; |
| typedef INT16 NPError; |
| typedef INT16 NPReason; |
| typedef char *NPMIMEType; |
| |
| typedef struct _NPP { |
| void *pdata; |
| void *ndata; |
| } NPP_t, *NPP; |
| |
| typedef struct _NPStream { |
| void *pdata; |
| void *ndata; |
| const char *url; |
| UINT32 end; |
| UINT32 lastmodified; |
| void *notifyData; |
| const char *headers; |
| } NPStream; |
| |
| typedef struct _NPSavedData { |
| INT32 len; |
| void *buf; |
| } NPSavedData; |
| |
| typedef struct _NPRect { |
| UINT16 top; |
| UINT16 left; |
| UINT16 bottom; |
| UINT16 right; |
| } NPRect; |
| |
| typedef enum { |
| NPFocusNext = 0, |
| NPFocusPrevious = 1 |
| } NPFocusDirection; |
| |
| #define NP_ABI_MASK 0 |
| |
| typedef enum { |
| NPPVpluginNameString = 1, |
| NPPVpluginDescriptionString, |
| NPPVpluginWindowBool, |
| NPPVpluginTransparentBool, |
| NPPVjavaClass, |
| NPPVpluginWindowSize, |
| NPPVpluginTimerInterval, |
| NPPVpluginScriptableInstance = (10 | NP_ABI_MASK), |
| NPPVpluginScriptableIID = 11, |
| NPPVjavascriptPushCallerBool = 12, |
| NPPVpluginKeepLibraryInMemory = 13, |
| NPPVpluginNeedsXEmbed = 14, |
| NPPVpluginScriptableNPObject = 15, |
| NPPVformValue = 16, |
| NPPVpluginUrlRequestsDisplayedBool = 17, |
| NPPVpluginWantsAllNetworkStreams = 18, |
| NPPVpluginNativeAccessibleAtkPlugId = 19, |
| NPPVpluginCancelSrcStream = 20, |
| NPPVSupportsAdvancedKeyHandling = 21 |
| } NPPVariable; |
| |
| typedef enum { |
| NPNVxDisplay = 1, |
| NPNVxtAppContext, |
| NPNVnetscapeWindow, |
| NPNVjavascriptEnabledBool, |
| NPNVasdEnabledBool, |
| NPNVisOfflineBool, |
| NPNVserviceManager = (10 | NP_ABI_MASK), |
| NPNVDOMElement = (11 | NP_ABI_MASK), |
| NPNVDOMWindow = (12 | NP_ABI_MASK), |
| NPNVToolkit = (13 | NP_ABI_MASK), |
| NPNVSupportsXEmbedBool = 14, |
| NPNVWindowNPObject = 15, |
| NPNVPluginElementNPObject = 16, |
| NPNVSupportsWindowless = 17, |
| NPNVprivateModeBool = 18, |
| NPNVsupportsAdvancedKeyHandling = 21 |
| } NPNVariable; |
| |
| typedef enum { |
| NPWindowTypeWindow = 1, |
| NPWindowTypeDrawable |
| } NPWindowType; |
| |
| typedef struct _NPWindow { |
| void *window; |
| INT32 x; |
| INT32 y; |
| UINT32 width; |
| UINT32 height; |
| NPRect clipRect; |
| NPWindowType type; |
| } NPWindow; |
| |
| typedef struct _NPFullPrint { |
| NPBool pluginPrinted; |
| NPBool printOne; |
| void *platformPrint; |
| } NPFullPrint; |
| |
| typedef struct _NPEmbedPrint { |
| NPWindow window; |
| void *platformPrint; |
| } NPEmbedPrint; |
| |
| typedef struct _NPPrint { |
| UINT16 mode; |
| union { |
| NPFullPrint fullPrint; |
| NPEmbedPrint embedPrint; |
| } print; |
| } NPPrint; |
| |
| typedef HRGN NPRegion; |
| |
| #define NPERR_BASE 0 |
| #define NPERR_NO_ERROR (NPERR_BASE + 0) |
| #define NPERR_GENERIC_ERROR (NPERR_BASE + 1) |
| #define NPERR_INVALID_INSTANCE_ERROR (NPERR_BASE + 2) |
| #define NPERR_INVALID_FUNCTABLE_ERROR (NPERR_BASE + 3) |
| #define NPERR_MODULE_LOAD_FAILED_ERROR (NPERR_BASE + 4) |
| #define NPERR_OUT_OF_MEMORY_ERROR (NPERR_BASE + 5) |
| #define NPERR_INVALID_PLUGIN_ERROR (NPERR_BASE + 6) |
| #define NPERR_INVALID_PLUGIN_DIR_ERROR (NPERR_BASE + 7) |
| #define NPERR_INCOMPATIBLE_VERSION_ERROR (NPERR_BASE + 8) |
| #define NPERR_INVALID_PARAM (NPERR_BASE + 9) |
| #define NPERR_INVALID_URL (NPERR_BASE + 10) |
| #define NPERR_FILE_NOT_FOUND (NPERR_BASE + 11) |
| #define NPERR_NO_DATA (NPERR_BASE + 12) |
| #define NPERR_STREAM_NOT_SEEKABLE (NPERR_BASE + 13) |
| |
| /* Parts of npfunctions.h */ |
| |
| typedef NPError (CDECL *NPP_NewProcPtr)(NPMIMEType,NPP,UINT16,INT16,char**,char**,NPSavedData*); |
| typedef NPError (CDECL *NPP_DestroyProcPtr)(NPP,NPSavedData**); |
| typedef NPError (CDECL *NPP_SetWindowProcPtr)(NPP,NPWindow*); |
| typedef NPError (CDECL *NPP_NewStreamProcPtr)(NPP,NPMIMEType,NPStream*,NPBool,UINT16*); |
| typedef NPError (CDECL *NPP_DestroyStreamProcPtr)(NPP,NPStream*,NPReason); |
| typedef INT32 (CDECL *NPP_WriteReadyProcPtr)(NPP,NPStream*); |
| typedef INT32 (CDECL *NPP_WriteProcPtr)(NPP,NPStream*,INT32,INT32,void*); |
| typedef void (CDECL *NPP_StreamAsFileProcPtr)(NPP,NPStream*,const char*); |
| typedef void (CDECL *NPP_PrintProcPtr)(NPP,NPPrint*); |
| typedef INT16 (CDECL *NPP_HandleEventProcPtr)(NPP,void*); |
| typedef void (CDECL *NPP_URLNotifyProcPtr)(NPP,const char*,NPReason,void*); |
| typedef NPError (CDECL *NPP_GetValueProcPtr)(NPP,NPPVariable,void*); |
| typedef NPError (CDECL *NPP_SetValueProcPtr)(NPP,NPNVariable,void*); |
| typedef NPBool (CDECL *NPP_GotFocusPtr)(NPP,NPFocusDirection); |
| typedef void (CDECL *NPP_LostFocusPtr)(NPP); |
| |
| typedef struct _NPPluginFuncs { |
| UINT16 size; |
| UINT16 version; |
| NPP_NewProcPtr newp; |
| NPP_DestroyProcPtr destroy; |
| NPP_SetWindowProcPtr setwindow; |
| NPP_NewStreamProcPtr newstream; |
| NPP_DestroyStreamProcPtr destroystream; |
| NPP_StreamAsFileProcPtr asfile; |
| NPP_WriteReadyProcPtr writeready; |
| NPP_WriteProcPtr write; |
| NPP_PrintProcPtr print; |
| NPP_HandleEventProcPtr event; |
| NPP_URLNotifyProcPtr urlnotify; |
| void *javaClass; |
| NPP_GetValueProcPtr getvalue; |
| NPP_SetValueProcPtr setvalue; |
| NPP_GotFocusPtr gotfocus; |
| NPP_LostFocusPtr lostfocus; |
| } NPPluginFuncs; |
| |
| static nsIDOMElement *get_dom_element(NPP instance) |
| { |
| nsISupports *instance_unk = (nsISupports*)instance->ndata; |
| nsIPluginInstance *plugin_instance; |
| nsIDOMElement *elem; |
| nsresult nsres; |
| |
| nsres = nsISupports_QueryInterface(instance_unk, &IID_nsIPluginInstance, (void**)&plugin_instance); |
| if(NS_FAILED(nsres)) { |
| ERR("Could not get nsIPluginInstance interface: %08x\n", nsres); |
| return NULL; |
| } |
| |
| nsres = nsIPluginInstance_GetDOMElement(plugin_instance, &elem); |
| nsIPluginInstance_Release(plugin_instance); |
| if(NS_FAILED(nsres)) { |
| ERR("GetDOMElement failed: %08x\n", nsres); |
| return NULL; |
| } |
| |
| return elem; |
| } |
| |
| static HTMLWindow *get_elem_window(nsIDOMElement *elem) |
| { |
| nsIDOMWindow *nswindow; |
| nsIDOMDocument *nsdoc; |
| HTMLWindow *window; |
| nsresult nsres; |
| |
| nsres = nsIDOMElement_GetOwnerDocument(elem, &nsdoc); |
| if(NS_FAILED(nsres)) |
| return NULL; |
| |
| nsres = nsIDOMDocument_GetDefaultView(nsdoc, &nswindow); |
| nsIDOMDocument_Release(nsdoc); |
| if(NS_FAILED(nsres) || !nswindow) |
| return NULL; |
| |
| window = nswindow_to_window(nswindow); |
| nsIDOMWindow_Release(nswindow); |
| |
| return window; |
| } |
| |
| static BOOL parse_classid(const PRUnichar *classid, CLSID *clsid) |
| { |
| const WCHAR *ptr; |
| unsigned len; |
| HRESULT hres; |
| |
| static const PRUnichar clsidW[] = {'c','l','s','i','d',':'}; |
| |
| if(strncmpiW(classid, clsidW, sizeof(clsidW)/sizeof(WCHAR))) |
| return FALSE; |
| |
| ptr = classid + sizeof(clsidW)/sizeof(WCHAR); |
| len = strlenW(ptr); |
| |
| if(len == 38) { |
| hres = CLSIDFromString(ptr, clsid); |
| }else if(len == 36) { |
| WCHAR buf[39]; |
| |
| buf[0] = '{'; |
| memcpy(buf+1, ptr, len*sizeof(WCHAR)); |
| buf[37] = '}'; |
| buf[38] = 0; |
| hres = CLSIDFromString(buf, clsid); |
| }else { |
| return FALSE; |
| } |
| |
| return SUCCEEDED(hres); |
| } |
| |
| static BOOL get_elem_clsid(nsIDOMElement *elem, CLSID *clsid) |
| { |
| nsAString attr_str, val_str; |
| nsresult nsres; |
| BOOL ret = FALSE; |
| |
| static const PRUnichar classidW[] = {'c','l','a','s','s','i','d',0}; |
| |
| nsAString_InitDepend(&attr_str, classidW); |
| nsAString_Init(&val_str, NULL); |
| nsres = nsIDOMElement_GetAttribute(elem, &attr_str, &val_str); |
| nsAString_Finish(&attr_str); |
| if(NS_SUCCEEDED(nsres)) { |
| const PRUnichar *val; |
| |
| nsAString_GetData(&val_str, &val); |
| if(*val) |
| ret = parse_classid(val, clsid); |
| }else { |
| ERR("GetAttribute failed: %08x\n", nsres); |
| } |
| |
| nsAString_Finish(&attr_str); |
| return ret; |
| } |
| |
| static IUnknown *create_activex_object(HTMLWindow *window, nsIDOMElement *nselem, CLSID *clsid) |
| { |
| IClassFactoryEx *cfex; |
| IClassFactory *cf; |
| IUnknown *obj; |
| DWORD policy; |
| HRESULT hres; |
| |
| if(!get_elem_clsid(nselem, clsid)) { |
| WARN("Could not determine element CLSID\n"); |
| return NULL; |
| } |
| |
| TRACE("clsid %s\n", debugstr_guid(clsid)); |
| |
| policy = 0; |
| hres = IInternetHostSecurityManager_ProcessUrlAction(&window->doc->IInternetHostSecurityManager_iface, |
| URLACTION_ACTIVEX_RUN, (BYTE*)&policy, sizeof(policy), (BYTE*)clsid, sizeof(GUID), 0, 0); |
| if(FAILED(hres) || policy != URLPOLICY_ALLOW) { |
| WARN("ProcessUrlAction returned %08x %x\n", hres, policy); |
| return NULL; |
| } |
| |
| hres = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf); |
| if(FAILED(hres)) |
| return NULL; |
| |
| hres = IClassFactory_QueryInterface(cf, &IID_IClassFactoryEx, (void**)&cfex); |
| if(SUCCEEDED(hres)) { |
| FIXME("Use IClassFactoryEx\n"); |
| IClassFactoryEx_Release(cfex); |
| } |
| |
| hres = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)&obj); |
| if(FAILED(hres)) |
| return NULL; |
| |
| return obj; |
| } |
| |
| static NPError CDECL NPP_New(NPMIMEType pluginType, NPP instance, UINT16 mode, INT16 argc, char **argn, |
| char **argv, NPSavedData *saved) |
| { |
| nsIDOMElement *nselem; |
| HTMLWindow *window; |
| IUnknown *obj; |
| CLSID clsid; |
| NPError err = NPERR_NO_ERROR; |
| |
| TRACE("(%s %p %x %d %p %p %p)\n", debugstr_a(pluginType), instance, mode, argc, argn, argv, saved); |
| |
| nselem = get_dom_element(instance); |
| if(!nselem) { |
| ERR("Could not get DOM element\n"); |
| return NPERR_GENERIC_ERROR; |
| } |
| |
| window = get_elem_window(nselem); |
| if(!window) { |
| ERR("Could not get element's window object\n"); |
| nsIDOMElement_Release(nselem); |
| return NPERR_GENERIC_ERROR; |
| } |
| |
| obj = create_activex_object(window, nselem, &clsid); |
| if(obj) { |
| PluginHost *host; |
| HRESULT hres; |
| |
| hres = create_plugin_host(window->doc, nselem, obj, &clsid, &host); |
| nsIDOMElement_Release(nselem); |
| IUnknown_Release(obj); |
| if(SUCCEEDED(hres)) |
| instance->pdata = host; |
| else |
| err = NPERR_GENERIC_ERROR; |
| }else { |
| err = NPERR_GENERIC_ERROR; |
| } |
| |
| nsIDOMElement_Release(nselem); |
| return err; |
| } |
| |
| static NPError CDECL NPP_Destroy(NPP instance, NPSavedData **save) |
| { |
| PluginHost *host = instance->pdata; |
| |
| TRACE("(%p %p)\n", instance, save); |
| |
| if(!host) |
| return NPERR_GENERIC_ERROR; |
| |
| detach_plugin_host(host); |
| IOleClientSite_Release(&host->IOleClientSite_iface); |
| instance->pdata = NULL; |
| return NPERR_NO_ERROR; |
| } |
| |
| static NPError CDECL NPP_SetWindow(NPP instance, NPWindow *window) |
| { |
| PluginHost *host = instance->pdata; |
| RECT pos_rect = {0, 0, window->width, window->height}; |
| |
| TRACE("(%p %p)\n", instance, window); |
| |
| if(!host) |
| return NPERR_GENERIC_ERROR; |
| |
| update_plugin_window(host, window->window, &pos_rect); |
| return NPERR_NO_ERROR; |
| } |
| |
| static NPError CDECL NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, UINT16 *stype) |
| { |
| TRACE("\n"); |
| return NPERR_GENERIC_ERROR; |
| } |
| |
| static NPError CDECL NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) |
| { |
| TRACE("\n"); |
| return NPERR_GENERIC_ERROR; |
| } |
| |
| static INT32 CDECL NPP_WriteReady(NPP instance, NPStream *stream) |
| { |
| TRACE("\n"); |
| return NPERR_GENERIC_ERROR; |
| } |
| |
| static INT32 CDECL NPP_Write(NPP instance, NPStream *stream, INT32 offset, INT32 len, void *buffer) |
| { |
| TRACE("\n"); |
| return NPERR_GENERIC_ERROR; |
| } |
| |
| static void CDECL NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) |
| { |
| TRACE("\n"); |
| } |
| |
| static void CDECL NPP_Print(NPP instance, NPPrint *platformPrint) |
| { |
| FIXME("\n"); |
| } |
| |
| static INT16 CDECL NPP_HandleEvent(NPP instance, void *event) |
| { |
| TRACE("\n"); |
| return NPERR_GENERIC_ERROR; |
| } |
| |
| static void CDECL NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData) |
| { |
| TRACE("\n"); |
| } |
| |
| static NPError CDECL NPP_GetValue(NPP instance, NPPVariable variable, void *ret_value) |
| { |
| TRACE("\n"); |
| return NPERR_GENERIC_ERROR; |
| } |
| |
| static NPError CDECL NPP_SetValue(NPP instance, NPNVariable variable, void *value) |
| { |
| TRACE("\n"); |
| return NPERR_GENERIC_ERROR; |
| } |
| |
| static NPBool CDECL NPP_GotFocus(NPP instance, NPFocusDirection direction) |
| { |
| FIXME("\n"); |
| return NPERR_GENERIC_ERROR; |
| } |
| |
| static void CDECL NPP_LostFocus(NPP instance) |
| { |
| FIXME("\n"); |
| } |
| |
| /*********************************************************************** |
| * NP_GetEntryPoints (mshtml.@) |
| */ |
| NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* funcs) |
| { |
| TRACE("(%p)\n", funcs); |
| |
| funcs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; |
| funcs->newp = NPP_New; |
| funcs->destroy = NPP_Destroy; |
| funcs->setwindow = NPP_SetWindow; |
| funcs->newstream = NPP_NewStream; |
| funcs->destroystream = NPP_DestroyStream; |
| funcs->asfile = NPP_StreamAsFile; |
| funcs->writeready = NPP_WriteReady; |
| funcs->write = NPP_Write; |
| funcs->print = NPP_Print; |
| funcs->event = NPP_HandleEvent; |
| funcs->urlnotify = NPP_URLNotify; |
| funcs->javaClass = NULL; |
| funcs->getvalue = NPP_GetValue; |
| funcs->setvalue = NPP_SetValue; |
| funcs->gotfocus = NPP_GotFocus; |
| funcs->lostfocus = NPP_LostFocus; |
| |
| return NPERR_NO_ERROR; |
| } |