Jacek Caban : mshtml: Added hack to allow pass post data to IPersistMoniker ::Load.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Feb 15 07:01:12 CST 2006


Module: wine
Branch: refs/heads/master
Commit: 4b511edf8d5ab2a0ab0fe08d762ec2ded445bcd0
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=4b511edf8d5ab2a0ab0fe08d762ec2ded445bcd0

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Feb 15 11:52:33 2006 +0100

mshtml: Added hack to allow pass post data to IPersistMoniker::Load.

---

 dlls/mshtml/mshtml_private.h |    2 +
 dlls/mshtml/nsembed.c        |   27 ++++++++++++
 dlls/mshtml/nsiface.idl      |   11 +++++
 dlls/mshtml/persist.c        |   94 +++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 131 insertions(+), 3 deletions(-)

diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index 52968bc..2bc9560 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -158,6 +158,8 @@ PRUint32 nsACString_GetData(const nsACSt
 void nsACString_SetData(nsACString*,const char*);
 void nsACString_Destroy(nsACString*);
 
+nsIInputStream *create_nsstream(const char*,PRInt32);
+
 IHlink *Hlink_Create(void);
 
 DEFINE_GUID(CLSID_AboutProtocol, 0x3050F406, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c
index 809c273..dbe0d56 100644
--- a/dlls/mshtml/nsembed.c
+++ b/dlls/mshtml/nsembed.c
@@ -38,6 +38,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
 #define NS_APPSTARTUPNOTIFIER_CONTRACTID "@mozilla.org/embedcomp/appstartup-notifier;1"
 #define NS_WEBBROWSER_CONTRACTID "@mozilla.org/embedding/browser/nsWebBrowser;1"
 #define NS_PROFILE_CONTRACTID "@mozilla.org/profile/manager;1"
+#define NS_STRINGSTREAM_CONTRACTID "@mozilla.org/io/string-input-stream;1"
 
 #define APPSTARTUP_TOPIC "app-startup"
 
@@ -388,6 +389,32 @@ void nsACString_Destroy(nsACString *str)
     HeapFree(GetProcessHeap(), 0, str);
 }
 
+nsIInputStream *create_nsstream(const char *data, PRInt32 data_len)
+{
+    nsIStringInputStream *ret;
+    nsresult nsres;
+
+    if(!pCompMgr)
+        return NULL;
+
+    nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
+            NS_STRINGSTREAM_CONTRACTID, NULL, &IID_nsIStringInputStream,
+            (void**)&ret);
+    if(NS_FAILED(nsres)) {
+        ERR("Could not get nsIStringInputStream\n");
+        return NULL;
+    }
+
+    nsres = nsIStringInputStream_SetData(ret, data, data_len);
+    if(NS_FAILED(nsres)) {
+        ERR("AdoptData failed: %08lx\n", nsres);
+        nsIStringInputStream_Release(ret);
+        return NULL;
+    }
+
+    return (nsIInputStream*)ret;
+}
+
 void close_gecko()
 {
     TRACE("()\n");
diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl
index 382e7b9..a54df54 100644
--- a/dlls/mshtml/nsiface.idl
+++ b/dlls/mshtml/nsiface.idl
@@ -145,6 +145,17 @@ interface nsIInputStream : nsISupports
 
 [
     object,
+    uuid(450cd2d4-f0fd-424d-b365-b1251f80fd53)
+]
+interface nsIStringInputStream : nsIInputStream
+{
+    nsresult SetData(const char *data, PRInt32 dataLen);
+    nsresult AdoptData(char *data, PRInt32 dataLen);
+    nsresult ShareData(const char *data, PRInt32 dataLen);
+}
+
+[
+    object,
     uuid(07a22cc0-0ce5-11d3-9331-00104ba0fd40)
 ]
 interface nsIURI : nsISupports
diff --git a/dlls/mshtml/persist.c b/dlls/mshtml/persist.c
index ae883a0..7649ee6 100644
--- a/dlls/mshtml/persist.c
+++ b/dlls/mshtml/persist.c
@@ -32,6 +32,7 @@
 #include "shlguid.h"
 
 #include "wine/debug.h"
+#include "wine/unicode.h"
 
 #include "mshtml_private.h"
 
@@ -221,6 +222,8 @@ static HRESULT WINAPI BindStatusCallback
     return E_NOTIMPL;
 }
 
+#undef STATUSCLB_THIS
+
 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
     BindStatusCallback_QueryInterface,
     BindStatusCallback_AddRef,
@@ -238,12 +241,14 @@ static const IBindStatusCallbackVtbl Bin
 static BindStatusCallback *BindStatusCallback_Create(HTMLDocument *doc, LPOLESTR url)
 {
     BindStatusCallback *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(BindStatusCallback));
+
     ret->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl;
     ret->ref = 0;
     ret->url = url;
     ret->doc = doc;
     ret->stream = NULL;
     IHTMLDocument2_AddRef(HTMLDOC(doc));
+
     return ret;
 }
 
@@ -285,6 +290,80 @@ static HRESULT WINAPI PersistMoniker_IsD
     return E_NOTIMPL;
 }
 
+static nsIInputStream *get_post_data_stream(IBindCtx *bctx)
+{
+    nsIInputStream *ret = NULL;
+    IBindStatusCallback *callback;
+    IHttpNegotiate *http_negotiate;
+    BINDINFO bindinfo;
+    DWORD bindf = 0;
+    DWORD post_len = 0, headers_len = 0;
+    LPWSTR headers = NULL;
+    WCHAR emptystr[] = {0};
+    char *data;
+    HRESULT hres;
+
+    static WCHAR _BSCB_Holder_[] =
+        {'_','B','S','C','B','_','H','o','l','d','e','r','_',0};
+
+
+    /* FIXME: This should be done in URLMoniker */
+    if(!bctx)
+        return NULL;
+
+    hres = IBindCtx_GetObjectParam(bctx, _BSCB_Holder_, (IUnknown**)&callback);
+    if(FAILED(hres))
+        return NULL;
+
+    hres = IBindStatusCallback_QueryInterface(callback, &IID_IHttpNegotiate,
+                                              (void**)&http_negotiate);
+    if(SUCCEEDED(hres)) {
+        hres = IHttpNegotiate_BeginningTransaction(http_negotiate, emptystr,
+                                                   emptystr, 0, &headers);
+        IHttpNegotiate_Release(http_negotiate);
+
+        if(SUCCEEDED(hres) && headers)
+            headers_len = WideCharToMultiByte(CP_ACP, 0, headers, -1, NULL, 0, NULL, NULL);
+    }
+
+    memset(&bindinfo, 0, sizeof(bindinfo));
+    bindinfo.cbSize = sizeof(bindinfo);
+
+    hres = IBindStatusCallback_GetBindInfo(callback, &bindf, &bindinfo);
+
+    if(SUCCEEDED(hres) && bindinfo.dwBindVerb == BINDVERB_POST)
+        post_len = bindinfo.cbStgmedData-1;
+
+    if(headers_len || post_len) {
+        int len = headers_len;
+
+        static const char content_length[] = "Content-Length: %lu\r\n\r\n";
+
+        data = HeapAlloc(GetProcessHeap(), 0, headers_len+post_len+sizeof(content_length)+8);
+
+        if(headers_len) {
+            WideCharToMultiByte(CP_ACP, 0, headers, -1, data, -1, NULL, NULL);
+            CoTaskMemFree(headers);
+        }
+
+        if(post_len) {
+            sprintf(data+headers_len-1, content_length, post_len);
+            len = strlen(data);
+
+            memcpy(data+len, bindinfo.stgmedData.u.hGlobal, post_len);
+        }
+
+        TRACE("data = %s\n", debugstr_an(data, len+post_len));
+
+        ret = create_nsstream(data, strlen(data));
+    }
+
+    ReleaseBindInfo(&bindinfo);
+    IBindStatusCallback_Release(callback);
+
+    return ret;
+}
+
 static HRESULT WINAPI PersistMoniker_Load(IPersistMoniker *iface, BOOL fFullyAvailable,
         IMoniker *pimkName, LPBC pibc, DWORD grfMode)
 {
@@ -358,15 +437,23 @@ static HRESULT WINAPI PersistMoniker_Loa
          * It uses Gecko's LoadURI instead of IMoniker's BindToStorage. Should we improve
          * it (to do so we'd have to use not frozen interfaces)?
          */
+
+        nsIInputStream *post_data_stream = get_post_data_stream(pibc);;
+
         This->nscontainer->load_call = TRUE;
         nsres = nsIWebNavigation_LoadURI(This->nscontainer->navigation, url,
-                LOAD_FLAGS_NONE, NULL, NULL, NULL);
+                LOAD_FLAGS_NONE, NULL, post_data_stream, NULL);
         This->nscontainer->load_call = FALSE;
 
-        if(NS_SUCCEEDED(nsres))
+        if(post_data_stream)
+            nsIInputStream_Release(post_data_stream);
+
+        if(NS_SUCCEEDED(nsres)) {
+            CoTaskMemFree(url);
             return S_OK;
-        else
+        }else {
             WARN("LoadURI failed: %08lx\n", nsres);
+        }
     }    
 
     /* FIXME: Use grfMode */
@@ -378,6 +465,7 @@ static HRESULT WINAPI PersistMoniker_Loa
         IBinding_Abort(This->status_callback->binding);
 
     callback = This->status_callback = BindStatusCallback_Create(This, url);
+    CoTaskMemFree(url);
 
     if(pibc) {
         pbind = pibc;




More information about the wine-cvs mailing list