Piotr Caban : urlmon: Added Uri IPersistStream_Save implementation.
Alexandre Julliard
julliard at winehq.org
Thu Jan 12 13:19:24 CST 2012
Module: wine
Branch: master
Commit: 3694ab67e538533560c3ddf3c98c9f7cfe712f08
URL: http://source.winehq.org/git/wine.git/?a=commit;h=3694ab67e538533560c3ddf3c98c9f7cfe712f08
Author: Piotr Caban <piotr at codeweavers.com>
Date: Thu Jan 12 15:34:58 2012 +0100
urlmon: Added Uri IPersistStream_Save implementation.
---
dlls/urlmon/uri.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 158 insertions(+), 6 deletions(-)
diff --git a/dlls/urlmon/uri.c b/dlls/urlmon/uri.c
index 741732b..4c6747d 100644
--- a/dlls/urlmon/uri.c
+++ b/dlls/urlmon/uri.c
@@ -17,6 +17,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#define NONAMELESSUNION
+
#include "urlmon_main.h"
#include "wine/debug.h"
@@ -5132,8 +5134,8 @@ static HRESULT WINAPI PersistStream_GetClassID(IPersistStream *iface, CLSID *pCl
static HRESULT WINAPI PersistStream_IsDirty(IPersistStream *iface)
{
Uri *This = impl_from_IPersistStream(iface);
- FIXME("(%p)\n", This);
- return E_NOTIMPL;
+ TRACE("(%p)\n", This);
+ return S_FALSE;
}
static HRESULT WINAPI PersistStream_Load(IPersistStream *iface, IStream *pStm)
@@ -5143,18 +5145,168 @@ static HRESULT WINAPI PersistStream_Load(IPersistStream *iface, IStream *pStm)
return E_NOTIMPL;
}
+struct persist_uri {
+ DWORD size;
+ DWORD unk1[2];
+ DWORD create_flags;
+ DWORD unk2[3];
+ DWORD fields_no;
+ BYTE data[1];
+};
+
+static inline BYTE* persist_stream_add_strprop(Uri *This, BYTE *p, DWORD type, DWORD len, WCHAR *data)
+{
+ len *= sizeof(WCHAR);
+ *(DWORD*)p = type;
+ p += sizeof(DWORD);
+ *(DWORD*)p = len+sizeof(WCHAR);
+ p += sizeof(DWORD);
+ memcpy(p, data, len);
+ p += len;
+ *(WCHAR*)p = 0;
+ return p+sizeof(WCHAR);
+}
+
static HRESULT WINAPI PersistStream_Save(IPersistStream *iface, IStream *pStm, BOOL fClearDirty)
{
Uri *This = impl_from_IPersistStream(iface);
- FIXME("(%p)->(%p %x)\n", This, pStm, fClearDirty);
- return E_NOTIMPL;
+ ULARGE_INTEGER size;
+ struct persist_uri *data;
+ BYTE *p;
+ HRESULT hres;
+
+ TRACE("(%p)->(%p %x)\n", This, pStm, fClearDirty);
+
+ if(!pStm)
+ return E_INVALIDARG;
+
+ hres = IPersistStream_GetSizeMax(&This->IPersistStream_iface, &size);
+ if(FAILED(hres))
+ return hres;
+
+ data = heap_alloc_zero(size.u.LowPart);
+ if(!data)
+ return E_OUTOFMEMORY;
+
+ data->size = size.u.LowPart;
+ data->create_flags = This->create_flags;
+
+ data->fields_no = 1;
+ p = persist_stream_add_strprop(This, data->data, Uri_PROPERTY_RAW_URI,
+ SysStringLen(This->raw_uri), This->raw_uri);
+ if(This->scheme_type!=URL_SCHEME_HTTP && This->scheme_type!=URL_SCHEME_HTTPS
+ && This->scheme_type!=URL_SCHEME_FTP) {
+ hres = IStream_Write(pStm, data, data->size-2, NULL);
+ heap_free(data);
+ return hres;
+ }
+
+ if(This->fragment_len) {
+ data->fields_no++;
+ p = persist_stream_add_strprop(This, p, Uri_PROPERTY_FRAGMENT,
+ This->fragment_len, This->canon_uri+This->fragment_start);
+ }
+
+ if(This->host_len) {
+ data->fields_no++;
+ if(This->host_type == Uri_HOST_IPV6)
+ p = persist_stream_add_strprop(This, p, Uri_PROPERTY_HOST,
+ This->host_len-2, This->canon_uri+This->host_start+1);
+ else
+ p = persist_stream_add_strprop(This, p, Uri_PROPERTY_HOST,
+ This->host_len, This->canon_uri+This->host_start);
+ }
+
+ if(This->userinfo_split > -1) {
+ data->fields_no++;
+ p = persist_stream_add_strprop(This, p, Uri_PROPERTY_PASSWORD,
+ This->userinfo_len-This->userinfo_split-1,
+ This->canon_uri+This->userinfo_start+This->userinfo_split+1);
+ }
+
+ if(This->path_len) {
+ data->fields_no++;
+ p = persist_stream_add_strprop(This, p, Uri_PROPERTY_PATH,
+ This->path_len, This->canon_uri+This->path_start);
+ }
+
+ if(This->has_port) {
+ data->fields_no++;
+ *(DWORD*)p = Uri_PROPERTY_PORT;
+ p += sizeof(DWORD);
+ *(DWORD*)p = sizeof(DWORD);
+ p += sizeof(DWORD);
+ *(DWORD*)p = This->port;
+ p += sizeof(DWORD);
+ }
+
+ if(This->query_len) {
+ data->fields_no++;
+ p = persist_stream_add_strprop(This, p, Uri_PROPERTY_QUERY,
+ This->query_len, This->canon_uri+This->query_start);
+ }
+
+ if(This->scheme_len) {
+ data->fields_no++;
+ p = persist_stream_add_strprop(This, p, Uri_PROPERTY_SCHEME_NAME,
+ This->scheme_len, This->canon_uri+This->scheme_start);
+ }
+
+ if(This->userinfo_start>-1 && This->userinfo_split!=0) {
+ data->fields_no++;
+ if(This->userinfo_split > -1)
+ p = persist_stream_add_strprop(This, p, Uri_PROPERTY_USER_NAME,
+ This->userinfo_split, This->canon_uri+This->userinfo_start);
+ else
+ p = persist_stream_add_strprop(This, p, Uri_PROPERTY_USER_NAME,
+ This->userinfo_len, This->canon_uri+This->userinfo_start);
+ }
+
+ hres = IStream_Write(pStm, data, data->size-2, NULL);
+ heap_free(data);
+ return hres;
}
static HRESULT WINAPI PersistStream_GetSizeMax(IPersistStream *iface, ULARGE_INTEGER *pcbSize)
{
Uri *This = impl_from_IPersistStream(iface);
- FIXME("(%p)->(%p)\n", This, pcbSize);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, pcbSize);
+
+ if(!pcbSize)
+ return E_INVALIDARG;
+
+ pcbSize->u.LowPart = 2+(SysStringLen(This->raw_uri)+1)*sizeof(WCHAR)
+ + 2*sizeof(DWORD) + sizeof(struct persist_uri);
+ pcbSize->u.HighPart = 0;
+ if(This->scheme_type!=URL_SCHEME_HTTP && This->scheme_type!=URL_SCHEME_HTTPS
+ && This->scheme_type!=URL_SCHEME_FTP)
+ return S_OK;
+
+ if(This->fragment_len)
+ pcbSize->u.LowPart += (This->fragment_len+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
+ if(This->host_len) {
+ if(This->host_type == Uri_HOST_IPV6)
+ pcbSize->u.LowPart += (This->host_len-1)*sizeof(WCHAR) + 2*sizeof(DWORD);
+ else
+ pcbSize->u.LowPart += (This->host_len+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
+ }
+ if(This->userinfo_split > -1)
+ pcbSize->u.LowPart += (This->userinfo_len-This->userinfo_split)*sizeof(WCHAR) + 2*sizeof(DWORD);
+ if(This->path_len)
+ pcbSize->u.LowPart += (This->path_len+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
+ if(This->has_port)
+ pcbSize->u.LowPart += 3*sizeof(DWORD);
+ if(This->query_len)
+ pcbSize->u.LowPart += (This->query_len+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
+ if(This->scheme_len)
+ pcbSize->u.LowPart += (This->scheme_len+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
+ if(This->userinfo_start>-1 && This->userinfo_split!=0) {
+ if(This->userinfo_split > -1)
+ pcbSize->u.LowPart += (This->userinfo_split+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
+ else
+ pcbSize->u.LowPart += (This->userinfo_len+1)*sizeof(WCHAR) + 2*sizeof(DWORD);
+ }
+ return S_OK;
}
static const IPersistStreamVtbl PersistStreamVtbl = {
More information about the wine-cvs
mailing list