diff --git a/reactos/lib/urlmon/Makefile b/reactos/lib/urlmon/Makefile new file mode 100644 index 00000000000..3fdca915d1c --- /dev/null +++ b/reactos/lib/urlmon/Makefile @@ -0,0 +1,9 @@ +# $Id: Makefile 10513 2004-08-13 06:14:48Z rcampbell $ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = winedll + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk \ No newline at end of file diff --git a/reactos/lib/urlmon/Makefile.in b/reactos/lib/urlmon/Makefile.in new file mode 100644 index 00000000000..95aaaf5ba9a --- /dev/null +++ b/reactos/lib/urlmon/Makefile.in @@ -0,0 +1,19 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = urlmon.dll +IMPORTS = cabinet ole32 shlwapi wininet user32 advapi32 kernel32 ntdll +EXTRALIBS = -luuid + +C_SRCS = \ + regsvr.c \ + sec_mgr.c \ + umon.c \ + urlmon_main.c + +SUBDIRS = tests + +@MAKE_DLL_RULES@ + +### Dependencies: diff --git a/reactos/lib/urlmon/Makefile.ros-template b/reactos/lib/urlmon/Makefile.ros-template new file mode 100644 index 00000000000..84f2d8b5ce9 --- /dev/null +++ b/reactos/lib/urlmon/Makefile.ros-template @@ -0,0 +1,19 @@ +# $Id: Makefile.ros-template 11910 2004-12-03 23:37:44Z blight $ + +TARGET_NAME = urlmon + +TARGET_OBJECTS = @C_SRCS@ + +TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__ + +TARGET_SDKLIBS = @IMPORTS@ wine.a wine_uuid.a ntdll.a wininet.a + +TARGET_BASE = $(TARGET_BASE_LIB_RICHEDIT) + +TARGET_NORC = yes + +default: all + +DEP_OBJECTS = $(TARGET_OBJECTS) + +include $(TOOLS_PATH)/depend.mk diff --git a/reactos/lib/urlmon/regsvr.c b/reactos/lib/urlmon/regsvr.c new file mode 100644 index 00000000000..050f580f700 --- /dev/null +++ b/reactos/lib/urlmon/regsvr.c @@ -0,0 +1,553 @@ +/* + * self-registerable dll functions for urlmon.dll + * + * Copyright (C) 2003 John K. Hohm + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define COM_NO_WINDOWS_H +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "wingdi.h" +#include "winreg.h" +#include "winerror.h" + +#include "objbase.h" + +#include "urlmon.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(urlmon); + +/* + * Near the bottom of this file are the exported DllRegisterServer and + * DllUnregisterServer, which make all this worthwhile. + */ + +/*********************************************************************** + * interface for self-registering + */ +struct regsvr_interface +{ + IID const *iid; /* NULL for end of list */ + LPCSTR name; /* can be NULL to omit */ + IID const *base_iid; /* can be NULL to omit */ + int num_methods; /* can be <0 to omit */ + CLSID const *ps_clsid; /* can be NULL to omit */ + CLSID const *ps_clsid32; /* can be NULL to omit */ +}; + +static HRESULT register_interfaces(struct regsvr_interface const *list); +static HRESULT unregister_interfaces(struct regsvr_interface const *list); + +struct regsvr_coclass +{ + CLSID const *clsid; /* NULL for end of list */ + LPCSTR name; /* can be NULL to omit */ + LPCSTR ips; /* can be NULL to omit */ + LPCSTR ips32; /* can be NULL to omit */ + LPCSTR ips32_tmodel; /* can be NULL to omit */ + LPCSTR progid; /* can be NULL to omit */ + LPCSTR viprogid; /* can be NULL to omit */ + LPCSTR progid_extra; /* can be NULL to omit */ +}; + +static HRESULT register_coclasses(struct regsvr_coclass const *list); +static HRESULT unregister_coclasses(struct regsvr_coclass const *list); + +/*********************************************************************** + * static string constants + */ +static WCHAR const interface_keyname[10] = { + 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 }; +static WCHAR const base_ifa_keyname[14] = { + 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', + 'e', 0 }; +static WCHAR const num_methods_keyname[11] = { + 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 }; +static WCHAR const ps_clsid_keyname[15] = { + 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's', + 'i', 'd', 0 }; +static WCHAR const ps_clsid32_keyname[17] = { + 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's', + 'i', 'd', '3', '2', 0 }; +static WCHAR const clsid_keyname[6] = { + 'C', 'L', 'S', 'I', 'D', 0 }; +static WCHAR const curver_keyname[7] = { + 'C', 'u', 'r', 'V', 'e', 'r', 0 }; +static WCHAR const ips_keyname[13] = { + 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', + 0 }; +static WCHAR const ips32_keyname[15] = { + 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', + '3', '2', 0 }; +static WCHAR const progid_keyname[7] = { + 'P', 'r', 'o', 'g', 'I', 'D', 0 }; +static WCHAR const viprogid_keyname[25] = { + 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p', + 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D', + 0 }; +static char const tmodel_valuename[] = "ThreadingModel"; + +/*********************************************************************** + * static helper functions + */ +static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid); +static LONG register_key_defvalueW(HKEY base, WCHAR const *name, + WCHAR const *value); +static LONG register_key_defvalueA(HKEY base, WCHAR const *name, + char const *value); +static LONG register_progid(WCHAR const *clsid, + char const *progid, char const *curver_progid, + char const *name, char const *extra); +static LONG recursive_delete_key(HKEY key); +static LONG recursive_delete_keyA(HKEY base, char const *name); +static LONG recursive_delete_keyW(HKEY base, WCHAR const *name); + +/*********************************************************************** + * register_interfaces + */ +static HRESULT register_interfaces(struct regsvr_interface const *list) +{ + LONG res = ERROR_SUCCESS; + HKEY interface_key; + + res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &interface_key, NULL); + if (res != ERROR_SUCCESS) goto error_return; + + for (; res == ERROR_SUCCESS && list->iid; ++list) { + WCHAR buf[39]; + HKEY iid_key; + + StringFromGUID2(list->iid, buf, 39); + res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &iid_key, NULL); + if (res != ERROR_SUCCESS) goto error_close_interface_key; + + if (list->name) { + res = RegSetValueExA(iid_key, NULL, 0, REG_SZ, + (CONST BYTE*)(list->name), + strlen(list->name) + 1); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + if (list->base_iid) { + register_key_guid(iid_key, base_ifa_keyname, list->base_iid); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + if (0 <= list->num_methods) { + static WCHAR const fmt[3] = { '%', 'd', 0 }; + HKEY key; + + res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &key, NULL); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + + wsprintfW(buf, fmt, list->num_methods); + res = RegSetValueExW(key, NULL, 0, REG_SZ, + (CONST BYTE*)buf, + (lstrlenW(buf) + 1) * sizeof(WCHAR)); + RegCloseKey(key); + + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + if (list->ps_clsid) { + register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + if (list->ps_clsid32) { + register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + error_close_iid_key: + RegCloseKey(iid_key); + } + +error_close_interface_key: + RegCloseKey(interface_key); +error_return: + return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * unregister_interfaces + */ +static HRESULT unregister_interfaces(struct regsvr_interface const *list) +{ + LONG res = ERROR_SUCCESS; + HKEY interface_key; + + res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, + KEY_READ | KEY_WRITE, &interface_key); + if (res == ERROR_FILE_NOT_FOUND) return S_OK; + if (res != ERROR_SUCCESS) goto error_return; + + for (; res == ERROR_SUCCESS && list->iid; ++list) { + WCHAR buf[39]; + + StringFromGUID2(list->iid, buf, 39); + res = recursive_delete_keyW(interface_key, buf); + } + + RegCloseKey(interface_key); +error_return: + return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * register_coclasses + */ +static HRESULT register_coclasses(struct regsvr_coclass const *list) +{ + LONG res = ERROR_SUCCESS; + HKEY coclass_key; + + res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL); + if (res != ERROR_SUCCESS) goto error_return; + + for (; res == ERROR_SUCCESS && list->clsid; ++list) { + WCHAR buf[39]; + HKEY clsid_key; + + StringFromGUID2(list->clsid, buf, 39); + res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL); + if (res != ERROR_SUCCESS) goto error_close_coclass_key; + + if (list->name) { + res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ, + (CONST BYTE*)(list->name), + strlen(list->name) + 1); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + if (list->ips) { + res = register_key_defvalueA(clsid_key, ips_keyname, list->ips); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + if (list->ips32) { + HKEY ips32_key; + + res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, + &ips32_key, NULL); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + + res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ, + (CONST BYTE*)list->ips32, + lstrlenA(list->ips32) + 1); + if (res == ERROR_SUCCESS && list->ips32_tmodel) + res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ, + (CONST BYTE*)list->ips32_tmodel, + strlen(list->ips32_tmodel) + 1); + RegCloseKey(ips32_key); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + if (list->progid) { + res = register_key_defvalueA(clsid_key, progid_keyname, + list->progid); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + + res = register_progid(buf, list->progid, NULL, + list->name, list->progid_extra); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + if (list->viprogid) { + res = register_key_defvalueA(clsid_key, viprogid_keyname, + list->viprogid); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + + res = register_progid(buf, list->viprogid, list->progid, + list->name, list->progid_extra); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + error_close_clsid_key: + RegCloseKey(clsid_key); + } + +error_close_coclass_key: + RegCloseKey(coclass_key); +error_return: + return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * unregister_coclasses + */ +static HRESULT unregister_coclasses(struct regsvr_coclass const *list) +{ + LONG res = ERROR_SUCCESS; + HKEY coclass_key; + + res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, + KEY_READ | KEY_WRITE, &coclass_key); + if (res == ERROR_FILE_NOT_FOUND) return S_OK; + if (res != ERROR_SUCCESS) goto error_return; + + for (; res == ERROR_SUCCESS && list->clsid; ++list) { + WCHAR buf[39]; + + StringFromGUID2(list->clsid, buf, 39); + res = recursive_delete_keyW(coclass_key, buf); + if (res != ERROR_SUCCESS) goto error_close_coclass_key; + + if (list->progid) { + res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid); + if (res != ERROR_SUCCESS) goto error_close_coclass_key; + } + + if (list->viprogid) { + res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid); + if (res != ERROR_SUCCESS) goto error_close_coclass_key; + } + } + +error_close_coclass_key: + RegCloseKey(coclass_key); +error_return: + return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * regsvr_key_guid + */ +static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid) +{ + WCHAR buf[39]; + + StringFromGUID2(guid, buf, 39); + return register_key_defvalueW(base, name, buf); +} + +/*********************************************************************** + * regsvr_key_defvalueW + */ +static LONG register_key_defvalueW( + HKEY base, + WCHAR const *name, + WCHAR const *value) +{ + LONG res; + HKEY key; + + res = RegCreateKeyExW(base, name, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &key, NULL); + if (res != ERROR_SUCCESS) return res; + res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value, + (lstrlenW(value) + 1) * sizeof(WCHAR)); + RegCloseKey(key); + return res; +} + +/*********************************************************************** + * regsvr_key_defvalueA + */ +static LONG register_key_defvalueA( + HKEY base, + WCHAR const *name, + char const *value) +{ + LONG res; + HKEY key; + + res = RegCreateKeyExW(base, name, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &key, NULL); + if (res != ERROR_SUCCESS) return res; + res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value, + lstrlenA(value) + 1); + RegCloseKey(key); + return res; +} + +/*********************************************************************** + * regsvr_progid + */ +static LONG register_progid( + WCHAR const *clsid, + char const *progid, + char const *curver_progid, + char const *name, + char const *extra) +{ + LONG res; + HKEY progid_key; + + res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0, + NULL, 0, KEY_READ | KEY_WRITE, NULL, + &progid_key, NULL); + if (res != ERROR_SUCCESS) return res; + + if (name) { + res = RegSetValueExA(progid_key, NULL, 0, REG_SZ, + (CONST BYTE*)name, strlen(name) + 1); + if (res != ERROR_SUCCESS) goto error_close_progid_key; + } + + if (clsid) { + res = register_key_defvalueW(progid_key, clsid_keyname, clsid); + if (res != ERROR_SUCCESS) goto error_close_progid_key; + } + + if (curver_progid) { + res = register_key_defvalueA(progid_key, curver_keyname, + curver_progid); + if (res != ERROR_SUCCESS) goto error_close_progid_key; + } + + if (extra) { + HKEY extra_key; + + res = RegCreateKeyExA(progid_key, extra, 0, + NULL, 0, KEY_READ | KEY_WRITE, NULL, + &extra_key, NULL); + if (res == ERROR_SUCCESS) + RegCloseKey(extra_key); + } + +error_close_progid_key: + RegCloseKey(progid_key); + return res; +} + +/*********************************************************************** + * recursive_delete_key + */ +static LONG recursive_delete_key(HKEY key) +{ + LONG res; + WCHAR subkey_name[MAX_PATH]; + DWORD cName; + HKEY subkey; + + for (;;) { + cName = sizeof(subkey_name) / sizeof(WCHAR); + res = RegEnumKeyExW(key, 0, subkey_name, &cName, + NULL, NULL, NULL, NULL); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { + res = ERROR_SUCCESS; /* presumably we're done enumerating */ + break; + } + res = RegOpenKeyExW(key, subkey_name, 0, + KEY_READ | KEY_WRITE, &subkey); + if (res == ERROR_FILE_NOT_FOUND) continue; + if (res != ERROR_SUCCESS) break; + + res = recursive_delete_key(subkey); + RegCloseKey(subkey); + if (res != ERROR_SUCCESS) break; + } + + if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); + return res; +} + +/*********************************************************************** + * recursive_delete_keyA + */ +static LONG recursive_delete_keyA(HKEY base, char const *name) +{ + LONG res; + HKEY key; + + res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key); + if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; + if (res != ERROR_SUCCESS) return res; + res = recursive_delete_key(key); + RegCloseKey(key); + return res; +} + +/*********************************************************************** + * recursive_delete_keyW + */ +static LONG recursive_delete_keyW(HKEY base, WCHAR const *name) +{ + LONG res; + HKEY key; + + res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key); + if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; + if (res != ERROR_SUCCESS) return res; + res = recursive_delete_key(key); + RegCloseKey(key); + return res; +} + +/*********************************************************************** + * coclass list + */ +static struct regsvr_coclass const coclass_list[] = { + { &CLSID_StdURLMoniker, + "URL Moniker", + NULL, + "urlmon.dll", + "Apartment" + }, + { NULL } /* list terminator */ +}; + +/*********************************************************************** + * interface list + */ + +static struct regsvr_interface const interface_list[] = { + { NULL } /* list terminator */ +}; + +/*********************************************************************** + * DllRegisterServer (URLMON.@) + */ +HRESULT WINAPI URLMON_DllRegisterServer(void) +{ + HRESULT hr; + + TRACE("\n"); + + hr = register_coclasses(coclass_list); + if (SUCCEEDED(hr)) + hr = register_interfaces(interface_list); + return hr; +} + +/*********************************************************************** + * DllUnregisterServer (URLMON.@) + */ +HRESULT WINAPI URLMON_DllUnregisterServer(void) +{ + HRESULT hr; + + TRACE("\n"); + + hr = unregister_coclasses(coclass_list); + if (SUCCEEDED(hr)) + hr = unregister_interfaces(interface_list); + return hr; +} diff --git a/reactos/lib/urlmon/sec_mgr.c b/reactos/lib/urlmon/sec_mgr.c new file mode 100644 index 00000000000..10fc1a88d34 --- /dev/null +++ b/reactos/lib/urlmon/sec_mgr.c @@ -0,0 +1,455 @@ +/* + * Internet Security and Zone Manager + * + * Copyright (c) 2004 Huw D M Davies + * Copyright 2004 Jacek Caban + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "wine/debug.h" +#include "ole2.h" +#include "wine/unicode.h" +#include "urlmon.h" +#include "urlmon_main.h" + +WINE_DEFAULT_DEBUG_CHANNEL(urlmon); + +/*********************************************************************** + * InternetSecurityManager implementation + * + */ +typedef struct SecManagerImpl{ + + IInternetSecurityManagerVtbl* lpvtbl1; /* VTable relative to the IInternetSecurityManager interface.*/ + + ULONG ref; /* reference counter for this object */ + +} SecManagerImpl; + +static HRESULT WINAPI SecManagerImpl_QueryInterface(IInternetSecurityManager* iface,REFIID riid,void** ppvObject) +{ + SecManagerImpl *This = (SecManagerImpl *)iface; + + TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject); + + /* Perform a sanity check on the parameters.*/ + if ( (This==0) || (ppvObject==0) ) + return E_INVALIDARG; + + /* Initialize the return parameter */ + *ppvObject = 0; + + /* Compare the riid with the interface IDs implemented by this object.*/ + if (IsEqualIID(&IID_IUnknown, riid) || + IsEqualIID(&IID_IInternetSecurityManager, riid)) + *ppvObject = iface; + + /* Check that we obtained an interface.*/ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* Query Interface always increases the reference count by one when it is successful */ + IInternetSecurityManager_AddRef(iface); + + return S_OK; +} + +static ULONG WINAPI SecManagerImpl_AddRef(IInternetSecurityManager* iface) +{ + SecManagerImpl *This = (SecManagerImpl *)iface; + + TRACE("(%p)\n",This); + + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI SecManagerImpl_Release(IInternetSecurityManager* iface) +{ + SecManagerImpl *This = (SecManagerImpl *)iface; + ULONG ref; + TRACE("(%p)\n",This); + + ref = InterlockedDecrement(&This->ref); + + /* destroy the object if there's no more reference on it */ + if (ref==0){ + HeapFree(GetProcessHeap(),0,This); + } + return ref; +} + +static HRESULT WINAPI SecManagerImpl_SetSecuritySite(IInternetSecurityManager *iface, + IInternetSecurityMgrSite *pSite) +{ + FIXME("(%p)->(%p)\n", iface, pSite); + return E_NOTIMPL; +} + +static HRESULT WINAPI SecManagerImpl_GetSecuritySite(IInternetSecurityManager *iface, + IInternetSecurityMgrSite **ppSite) +{ + FIXME("(%p)->( %p)\n", iface, ppSite); + return E_NOTIMPL; +} + +static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManager *iface, + LPCWSTR pwszUrl, DWORD *pdwZone, + DWORD dwFlags) +{ + FIXME("(%p)->(%s %p %08lx)\n", iface, debugstr_w(pwszUrl), pdwZone, dwFlags); + return E_NOTIMPL; +} + +static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManager *iface, + LPCWSTR pwszUrl, + BYTE *pbSecurityId, DWORD *pcbSecurityId, + DWORD dwReserved) +{ + FIXME("(%p)->(%s %p %p %08lx)\n", iface, debugstr_w(pwszUrl), pbSecurityId, pcbSecurityId, + dwReserved); + return E_NOTIMPL; +} + + +static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManager *iface, + LPCWSTR pwszUrl, DWORD dwAction, + BYTE *pPolicy, DWORD cbPolicy, + BYTE *pContext, DWORD cbContext, + DWORD dwFlags, DWORD dwReserved) +{ + FIXME("(%p)->(%s %08lx %p %08lx %p %08lx %08lx %08lx)\n", iface, debugstr_w(pwszUrl), dwAction, + pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved); + return E_NOTIMPL; +} + + +static HRESULT WINAPI SecManagerImpl_QueryCustomPolicy(IInternetSecurityManager *iface, + LPCWSTR pwszUrl, REFGUID guidKey, + BYTE **ppPolicy, DWORD *pcbPolicy, + BYTE *pContext, DWORD cbContext, + DWORD dwReserved) +{ + FIXME("(%p)->(%s %s %p %p %p %08lx %08lx )\n", iface, debugstr_w(pwszUrl), debugstr_guid(guidKey), + ppPolicy, pcbPolicy, pContext, cbContext, dwReserved); + return E_NOTIMPL; +} + +static HRESULT WINAPI SecManagerImpl_SetZoneMapping(IInternetSecurityManager *iface, + DWORD dwZone, LPCWSTR pwszPattern, DWORD dwFlags) +{ + FIXME("(%p)->(%08lx %s %08lx)\n", iface, dwZone, debugstr_w(pwszPattern),dwFlags); + return E_NOTIMPL; +} + +static HRESULT WINAPI SecManagerImpl_GetZoneMappings(IInternetSecurityManager *iface, + DWORD dwZone, IEnumString **ppenumString, DWORD dwFlags) +{ + FIXME("(%p)->(%08lx %p %08lx)\n", iface, dwZone, ppenumString,dwFlags); + return E_NOTIMPL; +} + +static IInternetSecurityManagerVtbl VT_SecManagerImpl = +{ + SecManagerImpl_QueryInterface, + SecManagerImpl_AddRef, + SecManagerImpl_Release, + SecManagerImpl_SetSecuritySite, + SecManagerImpl_GetSecuritySite, + SecManagerImpl_MapUrlToZone, + SecManagerImpl_GetSecurityId, + SecManagerImpl_ProcessUrlAction, + SecManagerImpl_QueryCustomPolicy, + SecManagerImpl_SetZoneMapping, + SecManagerImpl_GetZoneMappings +}; + +HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) +{ + SecManagerImpl *This; + + TRACE("(%p,%p)\n",pUnkOuter,ppobj); + This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); + + /* Initialize the virtual function table. */ + This->lpvtbl1 = &VT_SecManagerImpl; + This->ref = 1; + + *ppobj = This; + return S_OK; +} + +/*********************************************************************** + * InternetZoneManager implementation + * + */ +typedef struct { + IInternetZoneManagerVtbl* lpVtbl; + ULONG ref; +} ZoneMgrImpl; + +/******************************************************************** + * IInternetZoneManager_QueryInterface + */ +static HRESULT WINAPI ZoneMgrImpl_QueryInterface(IInternetZoneManager* iface, REFIID riid, void** ppvObject) +{ + ZoneMgrImpl* This = (ZoneMgrImpl*)iface; + + TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppvObject); + + if(!This || !ppvObject) + return E_INVALIDARG; + + if(!IsEqualIID(&IID_IUnknown, riid) && !IsEqualIID(&IID_IInternetZoneManager, riid)) { + FIXME("Unknown interface: %s\n", debugstr_guid(riid)); + *ppvObject = NULL; + return E_NOINTERFACE; + } + + *ppvObject = iface; + IInternetZoneManager_AddRef(iface); + + return S_OK; +} + +/******************************************************************** + * IInternetZoneManager_AddRef + */ +static ULONG WINAPI ZoneMgrImpl_AddRef(IInternetZoneManager* iface) +{ + ZoneMgrImpl* This = (ZoneMgrImpl*)iface; + + TRACE("(%p) was %lu\n", This, This->ref); + + return InterlockedIncrement(&This->ref); +} + +/******************************************************************** + * IInternetZoneManager_Release + */ +static ULONG WINAPI ZoneMgrImpl_Release(IInternetZoneManager* iface) +{ + ZoneMgrImpl* This = (ZoneMgrImpl*)iface; + ULONG ref; + + TRACE("(%p) was %lu\n", This, This->ref); + ref = InterlockedDecrement(&This->ref); + + if(!ref) + HeapFree(GetProcessHeap(), 0, This); + + return ref; +} + +/******************************************************************** + * IInternetZoneManager_GetZoneAttributes + */ +static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributes(IInternetZoneManager* iface, + DWORD dwZone, + ZONEATTRIBUTES* pZoneAttributes) +{ + FIXME("(%p)->(%ld %p) stub\n", iface, dwZone, pZoneAttributes); + return E_NOTIMPL; +} + +/******************************************************************** + * IInternetZoneManager_SetZoneAttributes + */ +static HRESULT WINAPI ZoneMgrImpl_SetZoneAttributes(IInternetZoneManager* iface, + DWORD dwZone, + ZONEATTRIBUTES* pZoneAttributes) +{ + FIXME("(%p)->(%08lx %p) stub\n", iface, dwZone, pZoneAttributes); + return E_NOTIMPL; +} + +/******************************************************************** + * IInternetZoneManager_GetZoneCustomPolicy + */ +static HRESULT WINAPI ZoneMgrImpl_GetZoneCustomPolicy(IInternetZoneManager* iface, + DWORD dwZone, + REFGUID guidKey, + BYTE** ppPolicy, + DWORD* pcbPolicy, + URLZONEREG ulrZoneReg) +{ + FIXME("(%p)->(%08lx %s %p %p %08x) stub\n", iface, dwZone, debugstr_guid(guidKey), + ppPolicy, pcbPolicy, ulrZoneReg); + return E_NOTIMPL; +} + +/******************************************************************** + * IInternetZoneManager_SetZoneCustomPolicy + */ +static HRESULT WINAPI ZoneMgrImpl_SetZoneCustomPolicy(IInternetZoneManager* iface, + DWORD dwZone, + REFGUID guidKey, + BYTE* ppPolicy, + DWORD cbPolicy, + URLZONEREG ulrZoneReg) +{ + FIXME("(%p)->(%08lx %s %p %08lx %08x) stub\n", iface, dwZone, debugstr_guid(guidKey), + ppPolicy, cbPolicy, ulrZoneReg); + return E_NOTIMPL; +} + +/******************************************************************** + * IInternetZoneManager_GetZoneActionPolicy + */ +static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicy(IInternetZoneManager* iface, + DWORD dwZone, + DWORD dwAction, + BYTE* pPolicy, + DWORD cbPolicy, + URLZONEREG urlZoneReg) +{ + FIXME("(%p)->(%08lx %08lx %p %08lx %08x) stub\n", iface, dwZone, dwAction, pPolicy, + cbPolicy, urlZoneReg); + return E_NOTIMPL; +} + +/******************************************************************** + * IInternetZoneManager_SetZoneActionPolicy + */ +static HRESULT WINAPI ZoneMgrImpl_SetZoneActionPolicy(IInternetZoneManager* iface, + DWORD dwZone, + DWORD dwAction, + BYTE* pPolicy, + DWORD cbPolicy, + URLZONEREG urlZoneReg) +{ + FIXME("(%p)->(%08lx %08lx %p %08lx %08x) stub\n", iface, dwZone, dwAction, pPolicy, + cbPolicy, urlZoneReg); + return E_NOTIMPL; +} + +/******************************************************************** + * IInternetZoneManager_LogAction + */ +static HRESULT WINAPI ZoneMgrImpl_LogAction(IInternetZoneManager* iface, + DWORD dwAction, + LPCWSTR pwszUrl, + LPCWSTR pwszText, + DWORD dwLogFlags) +{ + FIXME("(%p)->(%08lx %s %s %08lx) stub\n", iface, dwAction, debugstr_w(pwszUrl), + debugstr_w(pwszText), dwLogFlags); + return E_NOTIMPL; +} + +/******************************************************************** + * IInternetZoneManager_CreateZoneEnumerator + */ +static HRESULT WINAPI ZoneMgrImpl_CreateZoneEnumerator(IInternetZoneManager* iface, + DWORD* pdwEnum, + DWORD* pdwCount, + DWORD dwFlags) +{ + FIXME("(%p)->(%p %p %08lx) stub\n", iface, pdwEnum, pdwCount, dwFlags); + return E_NOTIMPL; +} + +/******************************************************************** + * IInternetZoneManager_GetZoneAt + */ +static HRESULT WINAPI ZoneMgrImpl_GetZoneAt(IInternetZoneManager* iface, + DWORD dwEnum, + DWORD dwIndex, + DWORD* pdwZone) +{ + FIXME("(%p)->(%08lx %08lx %p) stub\n", iface, dwEnum, dwIndex, pdwZone); + return E_NOTIMPL; +} + +/******************************************************************** + * IInternetZoneManager_DestroyZoneEnumerator + */ +static HRESULT WINAPI ZoneMgrImpl_DestroyZoneEnumerator(IInternetZoneManager* iface, + DWORD dwEnum) +{ + FIXME("(%p)->(%08lx) stub\n", iface, dwEnum); + return E_NOTIMPL; +} + +/******************************************************************** + * IInternetZoneManager_CopyTemplatePoliciesToZone + */ +static HRESULT WINAPI ZoneMgrImpl_CopyTemplatePoliciesToZone(IInternetZoneManager* iface, + DWORD dwTemplate, + DWORD dwZone, + DWORD dwReserved) +{ + FIXME("(%p)->(%08lx %08lx %08lx) stub\n", iface, dwTemplate, dwZone, dwReserved); + return E_NOTIMPL; +} + +/******************************************************************** + * IInternetZoneManager_Construct + */ +static IInternetZoneManagerVtbl ZoneMgrImplVtbl = { + ZoneMgrImpl_QueryInterface, + ZoneMgrImpl_AddRef, + ZoneMgrImpl_Release, + ZoneMgrImpl_GetZoneAttributes, + ZoneMgrImpl_SetZoneAttributes, + ZoneMgrImpl_GetZoneCustomPolicy, + ZoneMgrImpl_SetZoneCustomPolicy, + ZoneMgrImpl_GetZoneActionPolicy, + ZoneMgrImpl_SetZoneActionPolicy, + ZoneMgrImpl_LogAction, + ZoneMgrImpl_CreateZoneEnumerator, + ZoneMgrImpl_GetZoneAt, + ZoneMgrImpl_DestroyZoneEnumerator, + ZoneMgrImpl_CopyTemplatePoliciesToZone, +}; +HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) +{ + ZoneMgrImpl* ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ZoneMgrImpl)); + + TRACE("(%p %p)\n", pUnkOuter, ppobj); + ret->lpVtbl = &ZoneMgrImplVtbl; + ret->ref = 1; + *ppobj = (IInternetZoneManager*)ret; + + return S_OK; +} + +/*********************************************************************** + * CoInternetCreateSecurityManager (URLMON.@) + * + */ +HRESULT WINAPI CoInternetCreateSecurityManager( IServiceProvider *pSP, + IInternetSecurityManager **ppSM, DWORD dwReserved ) +{ + TRACE("%p %p %ld\n", pSP, ppSM, dwReserved ); + return SecManagerImpl_Construct(NULL, (void**) ppSM); +} + +/******************************************************************** + * CoInternetCreateZoneManager (URLMON.@) + */ +HRESULT WINAPI CoInternetCreateZoneManager(IServiceProvider* pSP, IInternetZoneManager** ppZM, DWORD dwReserved) +{ + TRACE("(%p %p %lx)\n", pSP, ppZM, dwReserved); + return ZoneMgrImpl_Construct(NULL, (void**)ppZM); +} diff --git a/reactos/lib/urlmon/umon.c b/reactos/lib/urlmon/umon.c new file mode 100644 index 00000000000..98b227bb3c8 --- /dev/null +++ b/reactos/lib/urlmon/umon.c @@ -0,0 +1,1412 @@ +/* + * UrlMon + * + * Copyright 1999 Ulrich Czekalla for Corel Corporation + * Copyright 2002 Huw D M Davies 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define COM_NO_WINDOWS_H +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winternl.h" +#include "winuser.h" +#include "objbase.h" +#include "wine/debug.h" +#include "wine/unicode.h" +#include "ole2.h" +#include "urlmon.h" +#include "wininet.h" +#include "shlwapi.h" +#include "urlmon_main.h" + +WINE_DEFAULT_DEBUG_CHANNEL(urlmon); + +/* native urlmon.dll uses this key, too */ +static const WCHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 }; + +/*static BOOL registered_wndclass = FALSE;*/ + +/* filemoniker data structure */ +typedef struct URLMonikerImpl{ + + IMonikerVtbl* lpvtbl1; /* VTable relative to the IMoniker interface.*/ + IBindingVtbl* lpvtbl2; /* VTable to IBinding interface */ + + ULONG ref; /* reference counter for this object */ + + LPOLESTR URLName; /* URL string identified by this URLmoniker */ + + HWND hwndCallback; + IBindCtx *pBC; + HINTERNET hinternet, hconnect, hrequest; +} URLMonikerImpl; + +/******************************************************************************* + * URLMoniker_QueryInterface + *******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + + TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject); + + /* Perform a sanity check on the parameters.*/ + if ( (This==0) || (ppvObject==0) ) + return E_INVALIDARG; + + /* Initialize the return parameter */ + *ppvObject = 0; + + /* Compare the riid with the interface IDs implemented by this object.*/ + if (IsEqualIID(&IID_IUnknown, riid) || + IsEqualIID(&IID_IPersist, riid) || + IsEqualIID(&IID_IPersistStream,riid) || + IsEqualIID(&IID_IMoniker, riid) + ) + *ppvObject = iface; + + /* Check that we obtained an interface.*/ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* Query Interface always increases the reference count by one when it is successful */ + IMoniker_AddRef(iface); + + return S_OK; +} + +/****************************************************************************** + * URLMoniker_AddRef + ******************************************************************************/ +static ULONG WINAPI URLMonikerImpl_AddRef(IMoniker* iface) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + + TRACE("(%p)\n",This); + + return InterlockedIncrement(&This->ref); +} + +/****************************************************************************** + * URLMoniker_Release + ******************************************************************************/ +static ULONG WINAPI URLMonikerImpl_Release(IMoniker* iface) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + ULONG ref; + + TRACE("(%p)\n",This); + + ref = InterlockedDecrement(&This->ref); + + /* destroy the object if there's no more reference on it */ + if (ref == 0) { + if (This->URLName!=NULL) + HeapFree(GetProcessHeap(),0,This->URLName); + + HeapFree(GetProcessHeap(),0,This); + } + + return ref; +} + +/****************************************************************************** + * URLMoniker_GetClassID + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_GetClassID(IMoniker* iface, + CLSID *pClassID)/* Pointer to CLSID of object */ +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + + TRACE("(%p,%p)\n",This,pClassID); + + if (pClassID==NULL) + return E_POINTER; + /* Windows always returns CLSID_StdURLMoniker */ + *pClassID = CLSID_StdURLMoniker; + return S_OK; +} + +/****************************************************************************** + * URLMoniker_IsDirty + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_IsDirty(IMoniker* iface) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + /* Note that the OLE-provided implementations of the IPersistStream::IsDirty + method in the OLE-provided moniker interfaces always return S_FALSE because + their internal state never changes. */ + + TRACE("(%p)\n",This); + + return S_FALSE; +} + +/****************************************************************************** + * URLMoniker_Load + * + * NOTE + * Writes a ULONG containing length of unicode string, followed + * by that many unicode characters + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_Load(IMoniker* iface,IStream* pStm) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + + HRESULT res; + ULONG len; + ULONG got; + TRACE("(%p,%p)\n",This,pStm); + + if(!pStm) + return E_INVALIDARG; + + res = IStream_Read(pStm, &len, sizeof(ULONG), &got); + if(SUCCEEDED(res)) { + if(got == sizeof(ULONG)) { + if(This->URLName) + HeapFree(GetProcessHeap(), 0, This->URLName); + This->URLName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(len+1)); + if(!This->URLName) + res = E_OUTOFMEMORY; + else { + res = IStream_Read(pStm, This->URLName, len, NULL); + This->URLName[len] = 0; + } + } + else + res = E_FAIL; + } + return res; +} + +/****************************************************************************** + * URLMoniker_Save + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_Save(IMoniker* iface, + IStream* pStm,/* pointer to the stream where the object is to be saved */ + BOOL fClearDirty)/* Specifies whether to clear the dirty flag */ +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + + HRESULT res; + ULONG len; + TRACE("(%p,%p,%d)\n",This,pStm,fClearDirty); + + if(!pStm) + return E_INVALIDARG; + + len = strlenW(This->URLName); + res=IStream_Write(pStm,&len,sizeof(ULONG),NULL); + if(SUCCEEDED(res)) + res=IStream_Write(pStm,&This->URLName,len*sizeof(WCHAR),NULL); + return res; + +} + +/****************************************************************************** + * URLMoniker_GetSizeMax + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_GetSizeMax(IMoniker* iface, + ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */ +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + + TRACE("(%p,%p)\n",This,pcbSize); + + if(!pcbSize) + return E_INVALIDARG; + + pcbSize->u.LowPart = sizeof(ULONG) + (strlenW(This->URLName) * sizeof(WCHAR)); + pcbSize->u.HighPart = 0; + return S_OK; +} + +/****************************************************************************** + * URLMoniker_BindToObject + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_BindToObject(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + REFIID riid, + VOID** ppvResult) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + + *ppvResult=0; + + FIXME("(%p)->(%p,%p,%s,%p): stub\n",This,pbc,pmkToLeft,debugstr_guid(riid), + ppvResult); + + return E_NOTIMPL; +} + +typedef struct { + enum {OnProgress, OnDataAvailable} callback; +} URLMON_CallbackData; + + +#if 0 +static LRESULT CALLBACK URLMON_WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + return DefWindowProcA(hwnd, msg, wparam, lparam); +} + +static void PostOnProgress(URLMonikerImpl *This, UINT progress, UINT maxprogress, DWORD status, LPCWSTR *str) +{ +} + +static void CALLBACK URLMON_InternetCallback(HINTERNET hinet, /*DWORD_PTR*/ DWORD context, DWORD status, + void *status_info, DWORD status_info_len) +{ + URLMonikerImpl *This = (URLMonikerImpl *)context; + TRACE("handle %p this %p status %08lx\n", hinet, This, status); + + if(This->filesize == -1) { + switch(status) { + case INTERNET_STATUS_RESOLVING_NAME: + PostOnProgess(This, 0, 0, BINDSTATUS_FINDINGRESOURCE, status_info); + break; + case INTERNET_STATUS_CONNECTING_TO_SERVER: + PostOnProgress(This, 0, 0, BINDSTATUS_CONNECTING, NULL); + break; + case INTERNET_STATUS_SENDING_REQUEST: + PostOnProgress(This, 0, 0, BINDSTATUS_SENDINGREQUEST, NULL); + break; + case INTERNET_REQUEST_COMPLETE: + { + DWORD len, lensz = sizeof(len); + + HttpQueryInfoW(hrequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &len, &lensz, NULL); + TRACE("res = %ld gle = %08lx url len = %ld\n", hres, GetLastError(), len); + This->filesize = len; + break; + } + } + } + + return; +} +#endif +/****************************************************************************** + * URLMoniker_BindToStorage + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_BindToStorage(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + REFIID riid, + VOID** ppvObject) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + HRESULT hres; + IBindStatusCallback *pbscb; + BINDINFO bi; + DWORD bindf; + + FIXME("(%p)->(%p,%p,%s,%p): stub\n",This,pbc,pmkToLeft,debugstr_guid(riid),ppvObject); + if(pmkToLeft) { + FIXME("pmkToLeft != NULL\n"); + return E_NOTIMPL; + } + if(!IsEqualIID(&IID_IStream, riid)) { + FIXME("unsupported iid\n"); + return E_NOTIMPL; + } + + /* FIXME This is a bad hack (tm). We should clearly download to a temporary file. + We also need to implement IStream ourselves so that IStream_Read can return + E_PENDING */ + + hres = CreateStreamOnHGlobal(0, TRUE, (IStream**)ppvObject); + + + if(SUCCEEDED(hres)) { + TRACE("Created dummy stream...\n"); + + hres = IBindCtx_GetObjectParam(pbc, (LPOLESTR)BSCBHolder, (IUnknown**)&pbscb); + if(SUCCEEDED(hres)) { + TRACE("Got IBindStatusCallback...\n"); + + memset(&bi, 0, sizeof(bi)); + bi.cbSize = sizeof(bi); + bindf = 0; + hres = IBindStatusCallback_GetBindInfo(pbscb, &bindf, &bi); + if(SUCCEEDED(hres)) { + URL_COMPONENTSW url; + WCHAR *host, *path; + DWORD len, lensz = sizeof(len), total_read = 0; + LARGE_INTEGER last_read_pos; + FORMATETC fmt; + STGMEDIUM stg; + + TRACE("got bindinfo. bindf = %08lx extrainfo = %s bindinfof = %08lx bindverb = %08lx iid %s\n", + bindf, debugstr_w(bi.szExtraInfo), bi.grfBindInfoF, bi.dwBindVerb, debugstr_guid(&bi.iid)); + hres = IBindStatusCallback_OnStartBinding(pbscb, 0, (IBinding*)&This->lpvtbl2); + TRACE("OnStartBinding rets %08lx\n", hres); + +#if 0 + if(!registered_wndclass) { + WNDCLASSA urlmon_wndclass = {0, URLMON_WndProc,0, 0, URLMON_hInstance, 0, 0, 0, NULL, "URLMON_Callback_Window_Class"}; + RegisterClassA(&urlmon_wndclass); + registered_wndclass = TRUE; + } + + This->hwndCallback = CreateWindowA("URLMON_Callback_Window_Class", NULL, 0, 0, 0, 0, 0, 0, 0, + URLMON_hInstance, NULL); + +#endif + memset(&url, 0, sizeof(url)); + url.dwStructSize = sizeof(url); + url.dwSchemeLength = url.dwHostNameLength = url.dwUrlPathLength = 1; + InternetCrackUrlW(This->URLName, 0, 0, &url); + host = HeapAlloc(GetProcessHeap(), 0, (url.dwHostNameLength + 1) * sizeof(WCHAR)); + memcpy(host, url.lpszHostName, url.dwHostNameLength * sizeof(WCHAR)); + host[url.dwHostNameLength] = '\0'; + path = HeapAlloc(GetProcessHeap(), 0, (url.dwUrlPathLength + 1) * sizeof(WCHAR)); + memcpy(path, url.lpszUrlPath, url.dwUrlPathLength * sizeof(WCHAR)); + path[url.dwUrlPathLength] = '\0'; + + This->hinternet = InternetOpenA("User Agent", 0, NULL, NULL, 0 /*INTERNET_FLAG_ASYNC*/); +/* InternetSetStatusCallback(This->hinternet, URLMON_InternetCallback);*/ + + This->hconnect = InternetConnectW(This->hinternet, host, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, + INTERNET_SERVICE_HTTP, 0, (DWORD)This); + This->hrequest = HttpOpenRequestW(This->hconnect, NULL, path, NULL, NULL, NULL, 0, (DWORD)This); + + hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, 0x22, NULL); + hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_FINDINGRESOURCE, NULL); + hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_CONNECTING, NULL); + hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_SENDINGREQUEST, NULL); + hres = E_OUTOFMEMORY; /* FIXME */ + if(HttpSendRequestW(This->hrequest, NULL, 0, NULL, 0)) { + + len = 0; + HttpQueryInfoW(This->hrequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &len, &lensz, NULL); + + TRACE("res = %ld gle = %08lx url len = %ld\n", hres, GetLastError(), len); + + last_read_pos.u.LowPart = last_read_pos.u.HighPart = 0; + fmt.cfFormat = 0; + fmt.ptd = NULL; + fmt.dwAspect = 0; + fmt.lindex = -1; + fmt.tymed = TYMED_ISTREAM; + stg.tymed = TYMED_ISTREAM; + stg.u.pstm = *(IStream**)ppvObject; + stg.pUnkForRelease = NULL; + + while(1) { + char buf[4096]; + DWORD bufread; + DWORD written; + if(InternetReadFile(This->hrequest, buf, sizeof(buf), &bufread)) { + TRACE("read %ld bytes %s...\n", bufread, debugstr_an(buf, 10)); + if(bufread == 0) break; + IStream_Write(*(IStream**)ppvObject, buf, bufread, &written); + total_read += bufread; + IStream_Seek(*(IStream**)ppvObject, last_read_pos, STREAM_SEEK_SET, NULL); + hres = IBindStatusCallback_OnProgress(pbscb, total_read, len, (total_read == bufread) ? + BINDSTATUS_BEGINDOWNLOADDATA : + BINDSTATUS_DOWNLOADINGDATA, NULL); + hres = IBindStatusCallback_OnDataAvailable(pbscb, + (total_read == bufread) ? BSCF_FIRSTDATANOTIFICATION : + BSCF_INTERMEDIATEDATANOTIFICATION, + total_read, &fmt, &stg); + last_read_pos.u.LowPart += bufread; /* FIXME */ + } else + break; + } + hres = IBindStatusCallback_OnProgress(pbscb, total_read, len, BINDSTATUS_ENDDOWNLOADDATA, NULL); + hres = IBindStatusCallback_OnDataAvailable(pbscb, BSCF_LASTDATANOTIFICATION, total_read, &fmt, &stg); + TRACE("OnDataAvail rets %08lx\n", hres); + hres = IBindStatusCallback_OnStopBinding(pbscb, S_OK, NULL); + TRACE("OnStop rets %08lx\n", hres); + hres = S_OK; + } + InternetCloseHandle(This->hrequest); + InternetCloseHandle(This->hconnect); + InternetCloseHandle(This->hinternet); + } + } + } + return hres; +} + +/****************************************************************************** + * URLMoniker_Reduce + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_Reduce(IMoniker* iface, + IBindCtx* pbc, + DWORD dwReduceHowFar, + IMoniker** ppmkToLeft, + IMoniker** ppmkReduced) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + + TRACE("(%p,%p,%ld,%p,%p)\n",This,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced); + + if(!ppmkReduced) + return E_INVALIDARG; + + URLMonikerImpl_AddRef(iface); + *ppmkReduced = iface; + return MK_S_REDUCED_TO_SELF; +} + +/****************************************************************************** + * URLMoniker_ComposeWith + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_ComposeWith(IMoniker* iface, + IMoniker* pmkRight, + BOOL fOnlyIfNotGeneric, + IMoniker** ppmkComposite) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + FIXME("(%p)->(%p,%d,%p): stub\n",This,pmkRight,fOnlyIfNotGeneric,ppmkComposite); + + return E_NOTIMPL; +} + +/****************************************************************************** + * URLMoniker_Enum + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + TRACE("(%p,%d,%p)\n",This,fForward,ppenumMoniker); + + if(!ppenumMoniker) + return E_INVALIDARG; + + /* Does not support sub-monikers */ + *ppenumMoniker = NULL; + return S_OK; +} + +/****************************************************************************** + * URLMoniker_IsEqual + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + CLSID clsid; + LPOLESTR urlPath; + IBindCtx* bind; + HRESULT res; + + TRACE("(%p,%p)\n",This,pmkOtherMoniker); + + if(pmkOtherMoniker==NULL) + return E_INVALIDARG; + + IMoniker_GetClassID(pmkOtherMoniker,&clsid); + + if(!IsEqualCLSID(&clsid,&CLSID_StdURLMoniker)) + return S_FALSE; + + res = CreateBindCtx(0,&bind); + if(FAILED(res)) + return res; + + res = S_FALSE; + if(SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&urlPath))) { + int result = lstrcmpiW(urlPath, This->URLName); + CoTaskMemFree(urlPath); + if(result == 0) + res = S_OK; + } + IUnknown_Release(bind); + return res; +} + + +/****************************************************************************** + * URLMoniker_Hash + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + + int h = 0,i,skip,len; + int off = 0; + LPOLESTR val; + + TRACE("(%p,%p)\n",This,pdwHash); + + if(!pdwHash) + return E_INVALIDARG; + + val = This->URLName; + len = lstrlenW(val); + + if(len < 16) { + for(i = len ; i > 0; i--) { + h = (h * 37) + val[off++]; + } + } + else { + /* only sample some characters */ + skip = len / 8; + for(i = len; i > 0; i -= skip, off += skip) { + h = (h * 39) + val[off]; + } + } + *pdwHash = h; + return S_OK; +} + +/****************************************************************************** + * URLMoniker_IsRunning + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_IsRunning(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + IMoniker* pmkNewlyRunning) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + FIXME("(%p)->(%p,%p,%p): stub\n",This,pbc,pmkToLeft,pmkNewlyRunning); + + return E_NOTIMPL; +} + +/****************************************************************************** + * URLMoniker_GetTimeOfLastChange + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_GetTimeOfLastChange(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + FILETIME* pFileTime) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + FIXME("(%p)->(%p,%p,%p): stub\n",This,pbc,pmkToLeft,pFileTime); + + return E_NOTIMPL; +} + +/****************************************************************************** + * URLMoniker_Inverse + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + TRACE("(%p,%p)\n",This,ppmk); + + return MK_E_NOINVERSE; +} + +/****************************************************************************** + * URLMoniker_CommonPrefixWith + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + FIXME("(%p)->(%p,%p): stub\n",This,pmkOther,ppmkPrefix); + + return E_NOTIMPL; +} + +/****************************************************************************** + * URLMoniker_RelativePathTo + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + FIXME("(%p)->(%p,%p): stub\n",This,pmOther,ppmkRelPath); + + return E_NOTIMPL; +} + +/****************************************************************************** + * URLMoniker_GetDisplayName + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_GetDisplayName(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + LPOLESTR *ppszDisplayName) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + + int len; + + TRACE("(%p,%p,%p,%p)\n",This,pbc,pmkToLeft,ppszDisplayName); + + if(!ppszDisplayName) + return E_INVALIDARG; + + /* FIXME: If this is a partial URL, try and get a URL moniker from SZ_URLCONTEXT in the bind context, + then look at pmkToLeft to try and complete the URL + */ + len = lstrlenW(This->URLName)+1; + *ppszDisplayName = CoTaskMemAlloc(len*sizeof(WCHAR)); + if(!*ppszDisplayName) + return E_OUTOFMEMORY; + lstrcpyW(*ppszDisplayName, This->URLName); + return S_OK; +} + +/****************************************************************************** + * URLMoniker_ParseDisplayName + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_ParseDisplayName(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + LPOLESTR pszDisplayName, + ULONG* pchEaten, + IMoniker** ppmkOut) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + FIXME("(%p)->(%p,%p,%p,%p,%p): stub\n",This,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut); + + return E_NOTIMPL; +} + +/****************************************************************************** + * URLMoniker_IsSystemMoniker + ******************************************************************************/ +static HRESULT WINAPI URLMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) +{ + URLMonikerImpl *This = (URLMonikerImpl *)iface; + TRACE("(%p,%p)\n",This,pwdMksys); + + if(!pwdMksys) + return E_INVALIDARG; + + *pwdMksys = MKSYS_URLMONIKER; + return S_OK; +} + +static HRESULT WINAPI URLMonikerImpl_IBinding_QueryInterface(IBinding* iface,REFIID riid,void** ppvObject) +{ + ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface); + + TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject); + + /* Perform a sanity check on the parameters.*/ + if ( (This==0) || (ppvObject==0) ) + return E_INVALIDARG; + + /* Initialize the return parameter */ + *ppvObject = 0; + + /* Compare the riid with the interface IDs implemented by this object.*/ + if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IBinding, riid)) + *ppvObject = iface; + + /* Check that we obtained an interface.*/ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* Query Interface always increases the reference count by one when it is successful */ + IBinding_AddRef(iface); + + return S_OK; + +} + +static ULONG WINAPI URLMonikerImpl_IBinding_AddRef(IBinding* iface) +{ + ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface); + TRACE("(%p)\n",This); + + return URLMonikerImpl_AddRef((IMoniker*)This); +} + +static ULONG WINAPI URLMonikerImpl_IBinding_Release(IBinding* iface) +{ + ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface); + TRACE("(%p)\n",This); + + return URLMonikerImpl_Release((IMoniker*)This); +} + +static HRESULT WINAPI URLMonikerImpl_IBinding_Abort(IBinding* iface) +{ + ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface); + FIXME("(%p): stub\n", This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI URLMonikerImpl_IBinding_GetBindResult(IBinding* iface, CLSID* pclsidProtocol, DWORD* pdwResult, LPOLESTR* pszResult, DWORD* pdwReserved) +{ + ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface); + FIXME("(%p)->(%s, %p, %p, %p): stub\n", This, debugstr_guid(pclsidProtocol), pdwResult, pszResult, pdwReserved); + + return E_NOTIMPL; +} + +static HRESULT WINAPI URLMonikerImpl_IBinding_GetPriority(IBinding* iface, LONG* pnPriority) +{ + ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface); + FIXME("(%p)->(%p): stub\n", This, pnPriority); + + return E_NOTIMPL; +} + +static HRESULT WINAPI URLMonikerImpl_IBinding_Resume(IBinding* iface) +{ + ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface); + FIXME("(%p): stub\n", This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI URLMonikerImpl_IBinding_SetPriority(IBinding* iface, LONG nPriority) +{ + ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface); + FIXME("(%p)->(%ld): stub\n", This, nPriority); + + return E_NOTIMPL; +} + +static HRESULT WINAPI URLMonikerImpl_IBinding_Suspend(IBinding* iface) +{ + ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface); + FIXME("(%p): stub\n", This); + + return E_NOTIMPL; +} + +/********************************************************************************/ +/* Virtual function table for the URLMonikerImpl class which include IPersist,*/ +/* IPersistStream and IMoniker functions. */ +static IMonikerVtbl VT_URLMonikerImpl = +{ + URLMonikerImpl_QueryInterface, + URLMonikerImpl_AddRef, + URLMonikerImpl_Release, + URLMonikerImpl_GetClassID, + URLMonikerImpl_IsDirty, + URLMonikerImpl_Load, + URLMonikerImpl_Save, + URLMonikerImpl_GetSizeMax, + URLMonikerImpl_BindToObject, + URLMonikerImpl_BindToStorage, + URLMonikerImpl_Reduce, + URLMonikerImpl_ComposeWith, + URLMonikerImpl_Enum, + URLMonikerImpl_IsEqual, + URLMonikerImpl_Hash, + URLMonikerImpl_IsRunning, + URLMonikerImpl_GetTimeOfLastChange, + URLMonikerImpl_Inverse, + URLMonikerImpl_CommonPrefixWith, + URLMonikerImpl_RelativePathTo, + URLMonikerImpl_GetDisplayName, + URLMonikerImpl_ParseDisplayName, + URLMonikerImpl_IsSystemMoniker +}; + +static IBindingVtbl VTBinding_URLMonikerImpl = +{ + URLMonikerImpl_IBinding_QueryInterface, + URLMonikerImpl_IBinding_AddRef, + URLMonikerImpl_IBinding_Release, + URLMonikerImpl_IBinding_Abort, + URLMonikerImpl_IBinding_Suspend, + URLMonikerImpl_IBinding_Resume, + URLMonikerImpl_IBinding_SetPriority, + URLMonikerImpl_IBinding_GetPriority, + URLMonikerImpl_IBinding_GetBindResult +}; + +/****************************************************************************** + * URLMoniker_Construct (local function) + *******************************************************************************/ +static HRESULT URLMonikerImpl_Construct(URLMonikerImpl* This, LPCOLESTR lpszLeftURLName, LPCOLESTR lpszURLName) +{ + HRESULT hres; + DWORD sizeStr; + + TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszLeftURLName),debugstr_w(lpszURLName)); + memset(This, 0, sizeof(*This)); + + /* Initialize the virtual function table. */ + This->lpvtbl1 = &VT_URLMonikerImpl; + This->lpvtbl2 = &VTBinding_URLMonikerImpl; + This->ref = 0; + + if(lpszLeftURLName) { + hres = UrlCombineW(lpszLeftURLName, lpszURLName, NULL, &sizeStr, 0); + if(FAILED(hres)) { + return hres; + } + sizeStr++; + } + else + sizeStr = lstrlenW(lpszURLName)+1; + + This->URLName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr)); + + if (This->URLName==NULL) + return E_OUTOFMEMORY; + + if(lpszLeftURLName) { + hres = UrlCombineW(lpszLeftURLName, lpszURLName, This->URLName, &sizeStr, 0); + if(FAILED(hres)) { + HeapFree(GetProcessHeap(), 0, This->URLName); + return hres; + } + } + else + strcpyW(This->URLName,lpszURLName); + + return S_OK; +} + +/*********************************************************************** + * CreateAsyncBindCtx (URLMON.@) + */ +HRESULT WINAPI CreateAsyncBindCtx(DWORD reserved, IBindStatusCallback *callback, + IEnumFORMATETC *format, IBindCtx **pbind) +{ + FIXME("stub.\n"); + return E_INVALIDARG; +} +/*********************************************************************** + * CreateAsyncBindCtxEx (URLMON.@) + * + * Create an asynchronous bind context. + * + * FIXME + * Not implemented. + */ +HRESULT WINAPI CreateAsyncBindCtxEx(IBindCtx *ibind, DWORD options, + IBindStatusCallback *callback, IEnumFORMATETC *format, IBindCtx** pbind, + DWORD reserved) +{ + FIXME("stub, returns failure\n"); + return E_INVALIDARG; +} + + +/*********************************************************************** + * CreateURLMoniker (URLMON.@) + * + * Create a url moniker. + * + * PARAMS + * pmkContext [I] Context + * szURL [I] Url to create the moniker for + * ppmk [O] Destination for created moniker. + * + * RETURNS + * Success: S_OK. ppmk contains the created IMoniker object. + * Failure: MK_E_SYNTAX if szURL is not a valid url, or + * E_OUTOFMEMORY if memory allocation fails. + */ +HRESULT WINAPI CreateURLMoniker(IMoniker *pmkContext, LPCWSTR szURL, IMoniker **ppmk) +{ + URLMonikerImpl *obj; + HRESULT hres; + IID iid = IID_IMoniker; + LPOLESTR lefturl = NULL; + + TRACE("(%p, %s, %p)\n", pmkContext, debugstr_w(szURL), ppmk); + + if(!(obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj)))) + return E_OUTOFMEMORY; + + if(pmkContext) { + CLSID clsid; + IBindCtx* bind; + IMoniker_GetClassID(pmkContext, &clsid); + if(IsEqualCLSID(&clsid, &CLSID_StdURLMoniker) && SUCCEEDED(CreateBindCtx(0, &bind))) { + URLMonikerImpl_GetDisplayName(pmkContext, bind, NULL, &lefturl); + IBindCtx_Release(bind); + } + } + + hres = URLMonikerImpl_Construct(obj, lefturl, szURL); + CoTaskMemFree(lefturl); + if(SUCCEEDED(hres)) + hres = URLMonikerImpl_QueryInterface((IMoniker*)obj, &iid, (void**)ppmk); + else + HeapFree(GetProcessHeap(), 0, obj); + return hres; +} + + +/*********************************************************************** + * CoInternetGetSession (URLMON.@) + * + * Create a new internet session and return an IInternetSession interface + * representing it. + * + * PARAMS + * dwSessionMode [I] Mode for the internet session + * ppIInternetSession [O] Destination for creates IInternetSession object + * dwReserved [I] Reserved, must be 0. + * + * RETURNS + * Success: S_OK. ppIInternetSession contains the IInternetSession interface. + * Failure: E_INVALIDARG, if any argument is invalid, or + * E_OUTOFMEMORY if memory allocation fails. + */ +HRESULT WINAPI CoInternetGetSession(DWORD dwSessionMode, IInternetSession **ppIInternetSession, DWORD dwReserved) +{ + FIXME("(%ld, %p, %ld): stub\n", dwSessionMode, ppIInternetSession, dwReserved); + + if(dwSessionMode) { + ERR("dwSessionMode: %ld, must be zero\n", dwSessionMode); + } + + if(dwReserved) { + ERR("dwReserved: %ld, must be zero\n", dwReserved); + } + + *ppIInternetSession=NULL; + return E_OUTOFMEMORY; +} + +/*********************************************************************** + * CoInternetQueryInfo (URLMON.@) + * + * Retrieves information relevant to a specified URL + * + * RETURNS + * S_OK success + * S_FALSE buffer too small + * INET_E_QUERYOPTIONUNKNOWN invalid option + * + */ +HRESULT WINAPI CoInternetQueryInfo(LPCWSTR pwzUrl, QUERYOPTION QueryOption, + DWORD dwQueryFlags, LPVOID pvBuffer, DWORD cbBuffer, DWORD * pcbBuffer, + DWORD dwReserved) +{ + FIXME("(%s, %x, %lx, %p, %lx, %p, %lx): stub\n", debugstr_w(pwzUrl), + QueryOption, dwQueryFlags, pvBuffer, cbBuffer, pcbBuffer, dwReserved); + return S_OK; +} + +static BOOL URLMON_IsBinary(LPVOID pBuffer, DWORD cbSize) +{ + unsigned int i, binarycount = 0; + unsigned char *buff = pBuffer; + for(i=0; i (cbSize-binarycount); +} + +/*********************************************************************** + * FindMimeFromData (URLMON.@) + * + * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided. + * + * NOTE + * See http://msdn.microsoft.com/workshop/networking/moniker/overview/appendix_a.asp + */ +HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer, + DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags, + LPWSTR* ppwzMimeOut, DWORD dwReserved) +{ + static const WCHAR szBinaryMime[] = {'a','p','p','l','i','c','a','t','i','o','n','/','o','c','t','e','t','-','s','t','r','e','a','m','\0'}; + static const WCHAR szTextMime[] = {'t','e','x','t','/','p','l','a','i','n','\0'}; + static const WCHAR szContentType[] = {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'}; + WCHAR szTmpMime[256]; + LPCWSTR mimeType = NULL; + HKEY hKey = NULL; + + TRACE("(%p,%s,%p,%ld,%s,0x%lx,%p,0x%lx)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize, + debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved); + + if((!pwzUrl && (!pBuffer || cbSize <= 0)) || !ppwzMimeOut) + return E_INVALIDARG; + + if(pwzMimeProposed) + mimeType = pwzMimeProposed; + else { + /* Try and find the mime type in the registry */ + if(pwzUrl) { + LPWSTR ext = strrchrW(pwzUrl, '.'); + if(ext) { + DWORD dwSize; + if(!RegOpenKeyExW(HKEY_CLASSES_ROOT, ext, 0, 0, &hKey)) { + if(!RegQueryValueExW(hKey, szContentType, NULL, NULL, (LPBYTE)szTmpMime, &dwSize)) { + mimeType = szTmpMime; + } + RegCloseKey(hKey); + } + } + } + } + if(!mimeType && pBuffer && cbSize > 0) + mimeType = URLMON_IsBinary(pBuffer, cbSize)?szBinaryMime:szTextMime; + + TRACE("Using %s\n", debugstr_w(mimeType)); + *ppwzMimeOut = CoTaskMemAlloc((lstrlenW(mimeType)+1)*sizeof(WCHAR)); + if(!*ppwzMimeOut) return E_OUTOFMEMORY; + lstrcpyW(*ppwzMimeOut, mimeType); + return S_OK; +} + +/*********************************************************************** + * IsAsyncMoniker (URLMON.@) + */ +HRESULT WINAPI IsAsyncMoniker(IMoniker *pmk) +{ + IUnknown *am; + + TRACE("(%p)\n", pmk); + if(!pmk) + return E_INVALIDARG; + if(SUCCEEDED(IMoniker_QueryInterface(pmk, &IID_IAsyncMoniker, (void**)&am))) { + IUnknown_Release(am); + return S_OK; + } + return S_FALSE; +} + +/*********************************************************************** + * RegisterBindStatusCallback (URLMON.@) + * + * Register a bind status callback. + * + * PARAMS + * pbc [I] Binding context + * pbsc [I] Callback to register + * ppbscPrevious [O] Destination for previous callback + * dwReserved [I] Reserved, must be 0. + * + * RETURNS + * Success: S_OK. + * Failure: E_INVALIDARG, if any argument is invalid, or + * E_OUTOFMEMORY if memory allocation fails. + */ +HRESULT WINAPI RegisterBindStatusCallback( + IBindCtx *pbc, + IBindStatusCallback *pbsc, + IBindStatusCallback **ppbscPrevious, + DWORD dwReserved) +{ + IBindStatusCallback *prev; + + TRACE("(%p,%p,%p,%lu)\n", pbc, pbsc, ppbscPrevious, dwReserved); + + if (pbc == NULL || pbsc == NULL) + return E_INVALIDARG; + + if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, (LPOLESTR)BSCBHolder, (IUnknown **)&prev))) + { + IBindCtx_RevokeObjectParam(pbc, (LPOLESTR)BSCBHolder); + if (ppbscPrevious) + *ppbscPrevious = prev; + else + IBindStatusCallback_Release(prev); + } + + return IBindCtx_RegisterObjectParam(pbc, (LPOLESTR)BSCBHolder, (IUnknown *)pbsc); +} + +/*********************************************************************** + * RevokeBindStatusCallback (URLMON.@) + * + * Unregister a bind status callback. + * + * pbc [I] Binding context + * pbsc [I] Callback to unregister + * + * RETURNS + * Success: S_OK. + * Failure: E_INVALIDARG, if any argument is invalid, or + * E_FAIL if pbsc wasn't registered with pbc. + */ +HRESULT WINAPI RevokeBindStatusCallback( + IBindCtx *pbc, + IBindStatusCallback *pbsc) +{ + IBindStatusCallback *callback; + HRESULT hr = E_FAIL; + + TRACE("(%p,%p)\n", pbc, pbsc); + + if (pbc == NULL || pbsc == NULL) + return E_INVALIDARG; + + if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, (LPOLESTR)BSCBHolder, (IUnknown **)&callback))) + { + if (callback == pbsc) + { + IBindCtx_RevokeObjectParam(pbc, (LPOLESTR)BSCBHolder); + hr = S_OK; + } + IBindStatusCallback_Release(pbsc); + } + + return hr; +} + +/*********************************************************************** + * ReleaseBindInfo (URLMON.@) + * + * Release the resources used by the specified BINDINFO structure. + * + * PARAMS + * pbindinfo [I] BINDINFO to release. + * + * RETURNS + * Nothing. + */ +void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo) +{ + FIXME("(%p)stub!\n", pbindinfo); +} + +/*********************************************************************** + * URLDownloadToFileA (URLMON.@) + * + * Downloads URL szURL to rile szFileName and call lpfnCB callback to + * report progress. + * + * PARAMS + * pCaller [I] controlling IUnknown interface. + * szURL [I] URL of the file to download + * szFileName [I] file name to store the content of the URL + * dwReserved [I] reserved - set to 0 + * lpfnCB [I] callback for progress report + * + * RETURNS + * S_OK on success + * E_OUTOFMEMORY when going out of memory + */ +HRESULT WINAPI URLDownloadToFileA(LPUNKNOWN pCaller, + LPCSTR szURL, + LPCSTR szFileName, + DWORD dwReserved, + LPBINDSTATUSCALLBACK lpfnCB) +{ + UNICODE_STRING szURL_w, szFileName_w; + + if ((szURL == NULL) || (szFileName == NULL)) { + FIXME("(%p,%s,%s,%08lx,%p) cannot accept NULL strings !\n", pCaller, debugstr_a(szURL), debugstr_a(szFileName), dwReserved, lpfnCB); + return E_INVALIDARG; /* The error code is not specified in this case... */ + } + + if (RtlCreateUnicodeStringFromAsciiz(&szURL_w, szURL)) { + if (RtlCreateUnicodeStringFromAsciiz(&szFileName_w, szFileName)) { + HRESULT ret = URLDownloadToFileW(pCaller, szURL_w.Buffer, szFileName_w.Buffer, dwReserved, lpfnCB); + + RtlFreeUnicodeString(&szURL_w); + RtlFreeUnicodeString(&szFileName_w); + + return ret; + } else { + RtlFreeUnicodeString(&szURL_w); + } + } + + FIXME("(%p,%s,%s,%08lx,%p) could not allocate W strings !\n", pCaller, szURL, szFileName, dwReserved, lpfnCB); + return E_OUTOFMEMORY; +} + +/*********************************************************************** + * URLDownloadToFileW (URLMON.@) + * + * Downloads URL szURL to rile szFileName and call lpfnCB callback to + * report progress. + * + * PARAMS + * pCaller [I] controlling IUnknown interface. + * szURL [I] URL of the file to download + * szFileName [I] file name to store the content of the URL + * dwReserved [I] reserved - set to 0 + * lpfnCB [I] callback for progress report + * + * RETURNS + * S_OK on success + * E_OUTOFMEMORY when going out of memory + */ +HRESULT WINAPI URLDownloadToFileW(LPUNKNOWN pCaller, + LPCWSTR szURL, + LPCWSTR szFileName, + DWORD dwReserved, + LPBINDSTATUSCALLBACK lpfnCB) +{ + HINTERNET hinternet, hcon, hreq; + BOOL r; + CHAR buffer[0x1000]; + DWORD sz, total, written; + DWORD total_size = 0xFFFFFFFF, arg_size = sizeof(total_size); + URL_COMPONENTSW url; + WCHAR host[0x80], path[0x100]; + HANDLE hfile; + static const WCHAR wszAppName[]={'u','r','l','m','o','n','.','d','l','l',0}; + + /* Note: all error codes would need to be checked agains real Windows behaviour... */ + TRACE("(%p,%s,%s,%08lx,%p) stub!\n", pCaller, debugstr_w(szURL), debugstr_w(szFileName), dwReserved, lpfnCB); + + if ((szURL == NULL) || (szFileName == NULL)) { + FIXME(" cannot accept NULL strings !\n"); + return E_INVALIDARG; + } + + /* Would be better to use the application name here rather than 'urlmon' :-/ */ + hinternet = InternetOpenW(wszAppName, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + if (hinternet == NULL) { + return E_OUTOFMEMORY; + } + + memset(&url, 0, sizeof(url)); + url.dwStructSize = sizeof(url); + url.lpszHostName = host; + url.dwHostNameLength = sizeof(host); + url.lpszUrlPath = path; + url.dwUrlPathLength = sizeof(path); + + if (!InternetCrackUrlW(szURL, 0, 0, &url)) { + InternetCloseHandle(hinternet); + return E_OUTOFMEMORY; + } + + if (lpfnCB) { + if (IBindStatusCallback_OnProgress(lpfnCB, 0, 0, BINDSTATUS_CONNECTING, url.lpszHostName) == E_ABORT) { + InternetCloseHandle(hinternet); + return S_OK; + } + } + + hcon = InternetConnectW(hinternet, url.lpszHostName, url.nPort, + url.lpszUserName, url.lpszPassword, + INTERNET_SERVICE_HTTP, 0, 0); + if (!hcon) { + InternetCloseHandle(hinternet); + return E_OUTOFMEMORY; + } + + hreq = HttpOpenRequestW(hcon, NULL, url.lpszUrlPath, NULL, NULL, NULL, 0, 0); + if (!hreq) { + InternetCloseHandle(hinternet); + InternetCloseHandle(hcon); + return E_OUTOFMEMORY; + } + + if (!HttpSendRequestW(hreq, NULL, 0, NULL, 0)) { + InternetCloseHandle(hinternet); + InternetCloseHandle(hcon); + InternetCloseHandle(hreq); + return E_OUTOFMEMORY; + } + + if (HttpQueryInfoW(hreq, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, + &total_size, &arg_size, NULL)) { + TRACE(" total size : %ld\n", total_size); + } + + hfile = CreateFileW(szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL ); + if (hfile == INVALID_HANDLE_VALUE) { + return E_ACCESSDENIED; + } + + if (lpfnCB) { + if (IBindStatusCallback_OnProgress(lpfnCB, 0, total_size != 0xFFFFFFFF ? total_size : 0, + BINDSTATUS_BEGINDOWNLOADDATA, szURL) == E_ABORT) { + InternetCloseHandle(hreq); + InternetCloseHandle(hcon); + InternetCloseHandle(hinternet); + CloseHandle(hfile); + return S_OK; + } + } + + total = 0; + while (1) { + r = InternetReadFile(hreq, buffer, sizeof(buffer), &sz); + if (!r) { + InternetCloseHandle(hreq); + InternetCloseHandle(hcon); + InternetCloseHandle(hinternet); + + CloseHandle(hfile); + return E_OUTOFMEMORY; + } + if (!sz) + break; + + total += sz; + + if (lpfnCB) { + if (IBindStatusCallback_OnProgress(lpfnCB, total, total_size != 0xFFFFFFFF ? total_size : 0, + BINDSTATUS_DOWNLOADINGDATA, szURL) == E_ABORT) { + InternetCloseHandle(hreq); + InternetCloseHandle(hcon); + InternetCloseHandle(hinternet); + CloseHandle(hfile); + return S_OK; + } + } + + if (!WriteFile(hfile, buffer, sz, &written, NULL)) { + InternetCloseHandle(hreq); + InternetCloseHandle(hcon); + InternetCloseHandle(hinternet); + + CloseHandle(hfile); + return E_OUTOFMEMORY; + } + } + + if (lpfnCB) { + if (IBindStatusCallback_OnProgress(lpfnCB, total, total_size != 0xFFFFFFFF ? total_size : 0, + BINDSTATUS_ENDDOWNLOADDATA, szURL) == E_ABORT) { + InternetCloseHandle(hreq); + InternetCloseHandle(hcon); + InternetCloseHandle(hinternet); + CloseHandle(hfile); + return S_OK; + } + } + + InternetCloseHandle(hreq); + InternetCloseHandle(hcon); + InternetCloseHandle(hinternet); + + CloseHandle(hfile); + + return S_OK; +} + +/*********************************************************************** + * HlinkSimpleNavigateToString (URLMON.@) + */ +HRESULT WINAPI HlinkSimpleNavigateToString( LPCWSTR szTarget, + LPCWSTR szLocation, LPCWSTR szTargetFrameName, IUnknown *pUnk, + IBindCtx *pbc, IBindStatusCallback *pbsc, DWORD grfHLNF, DWORD dwReserved) +{ + FIXME("%s\n", debugstr_w( szTarget ) ); + return E_NOTIMPL; +} + +/*********************************************************************** + * HlinkNavigateString (URLMON.@) + */ +HRESULT WINAPI HlinkNavigateString( IUnknown *pUnk, LPCWSTR szTarget ) +{ + TRACE("%p %s\n", pUnk, debugstr_w( szTarget ) ); + return HlinkSimpleNavigateToString( + szTarget, NULL, NULL, pUnk, NULL, NULL, 0, 0 ); +} diff --git a/reactos/lib/urlmon/urlmon.spec b/reactos/lib/urlmon/urlmon.spec new file mode 100644 index 00000000000..056a2e45e10 --- /dev/null +++ b/reactos/lib/urlmon/urlmon.spec @@ -0,0 +1,77 @@ +1 stub CDLGetLongPathNameA +2 stub CDLGetLongPathNameW +@ stub AsyncGetClassBits +@ stub AsyncInstallDistributionUnit +@ stub BindAsyncMoniker +@ stub CoGetClassObjectFromURL +@ stub CoInstall +@ stdcall CoInternetCombineUrl(wstr wstr long wstr long ptr long) +@ stdcall CoInternetCompareUrl(wstr wstr long) +@ stdcall CoInternetCreateSecurityManager(ptr ptr long) +@ stdcall CoInternetCreateZoneManager(ptr ptr long) +@ stub CoInternetGetProtocolFlags +@ stub CoInternetGetSecurityUrl +@ stdcall CoInternetGetSession(long ptr long) +@ stub CoInternetParseUrl +@ stdcall CoInternetQueryInfo(ptr long long ptr long ptr long) +@ stub CompareSecurityIds +@ stub CopyBindInfo +@ stub CopyStgMedium +@ stdcall CreateAsyncBindCtx(long ptr ptr ptr) +@ stdcall CreateAsyncBindCtxEx(ptr long ptr ptr ptr long) +@ stub CreateFormatEnumerator +@ stdcall CreateURLMoniker(ptr wstr ptr) +@ stdcall -private DllCanUnloadNow() URLMON_DllCanUnloadNow +@ stdcall -private DllGetClassObject(ptr ptr ptr) URLMON_DllGetClassObject +@ stdcall DllInstall(long ptr) URLMON_DllInstall +@ stdcall -private DllRegisterServer() URLMON_DllRegisterServer +@ stdcall -private DllRegisterServerEx() URLMON_DllRegisterServerEx +@ stdcall -private DllUnregisterServer() URLMON_DllUnregisterServer +@ stdcall Extract(long ptr) cabinet.Extract +@ stub FaultInIEFeature +@ stub FindMediaType +@ stub FindMediaTypeClass +@ stdcall FindMimeFromData(long ptr ptr long ptr long ptr long) +@ stub GetClassFileOrMime +@ stub GetClassURL +@ stub GetComponentIDFromCLSSPEC +@ stub GetMarkOfTheWeb +@ stub GetSoftwareUpdateInfo +@ stub HlinkGoBack +@ stub HlinkGoForward +@ stub HlinkNavigateMoniker +@ stdcall HlinkNavigateString(ptr wstr) +@ stub HlinkSimpleNavigateToMoniker +@ stdcall HlinkSimpleNavigateToString(wstr wstr wstr ptr ptr ptr long long) +@ stdcall IsAsyncMoniker(ptr) +@ stub IsLoggingEnabledA +@ stub IsLoggingEnabledW +@ stdcall IsValidURL(ptr wstr long) +@ stdcall MkParseDisplayNameEx(ptr ptr ptr ptr) ole32.MkParseDisplayName +@ stdcall ObtainUserAgentString(long str ptr) +@ stub PrivateCoInstall +@ stdcall RegisterBindStatusCallback(ptr ptr ptr long) +@ stub RegisterFormatEnumerator +@ stub RegisterMediaTypeClass +@ stub RegisterMediaTypes +@ stdcall ReleaseBindInfo(ptr) +@ stdcall RevokeBindStatusCallback(ptr ptr) +@ stub RevokeFormatEnumerator +@ stub SetSoftwareUpdateAdvertisementState +@ stub URLDownloadA +@ stub URLDownloadToCacheFileA +@ stub URLDownloadToCacheFileW +@ stdcall URLDownloadToFileA(ptr str str long ptr) +@ stdcall URLDownloadToFileW(ptr wstr wstr long ptr) +@ stub URLDownloadW +@ stub URLOpenBlockingStreamA +@ stub URLOpenBlockingStreamW +@ stub URLOpenPullStreamA +@ stub URLOpenPullStreamW +@ stub URLOpenStreamA +@ stub URLOpenStreamW +@ stub UrlMkBuildVersion +@ stdcall UrlMkGetSessionOption(long ptr long ptr long) +@ stdcall UrlMkSetSessionOption(long ptr long long) +@ stub WriteHitLogging +@ stub ZonesReInit diff --git a/reactos/lib/urlmon/urlmon_main.c b/reactos/lib/urlmon/urlmon_main.c new file mode 100644 index 00000000000..839882fbb1e --- /dev/null +++ b/reactos/lib/urlmon/urlmon_main.c @@ -0,0 +1,322 @@ +/* + * UrlMon + * + * Copyright (c) 2000 Patrik Stridvall + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "wtypes.h" +#define NO_SHLWAPI_REG +#include "shlwapi.h" + +#include "wine/debug.h" + +#include "winuser.h" +#include "urlmon.h" +#include "urlmon_main.h" + +WINE_DEFAULT_DEBUG_CHANNEL(urlmon); + +HINSTANCE URLMON_hInstance = 0; + +/*********************************************************************** + * DllMain (URLMON.init) + */ +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) +{ + TRACE("%p 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad); + + switch(fdwReason) { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + URLMON_hInstance = hinstDLL; + break; + + case DLL_PROCESS_DETACH: + URLMON_hInstance = 0; + break; + } + return TRUE; +} + + +/*********************************************************************** + * DllInstall (URLMON.@) + */ +HRESULT WINAPI URLMON_DllInstall(BOOL bInstall, LPCWSTR cmdline) +{ + FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE", + debugstr_w(cmdline)); + + return S_OK; +} + +/*********************************************************************** + * DllCanUnloadNow (URLMON.@) + */ +HRESULT WINAPI URLMON_DllCanUnloadNow(void) +{ + FIXME("(void): stub\n"); + + return S_FALSE; +} + + + +/****************************************************************************** + * Urlmon ClassFactory + */ +typedef struct { + IClassFactory ITF_IClassFactory; + + DWORD ref; + HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj); +} IClassFactoryImpl; + +struct object_creation_info +{ + const CLSID *clsid; + HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj); +}; + +static const struct object_creation_info object_creation[] = +{ + { &CLSID_InternetSecurityManager, &SecManagerImpl_Construct }, + { &CLSID_InternetZoneManager, ZoneMgrImpl_Construct } +}; + +static HRESULT WINAPI +CF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IClassFactory)) + { + IClassFactory_AddRef(iface); + *ppobj = This; + return S_OK; + } + + WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj); + return E_NOINTERFACE; +} + +static ULONG WINAPI CF_AddRef(LPCLASSFACTORY iface) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI CF_Release(LPCLASSFACTORY iface) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + + ULONG ref = InterlockedDecrement(&This->ref); + + if (ref == 0) + HeapFree(GetProcessHeap(), 0, This); + + return ref; +} + + +static HRESULT WINAPI CF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, + REFIID riid, LPVOID *ppobj) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + HRESULT hres; + LPUNKNOWN punk; + + TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); + + *ppobj = NULL; + if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) { + hres = IUnknown_QueryInterface(punk, riid, ppobj); + IUnknown_Release(punk); + } + return hres; +} + +static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + FIXME("(%p)->(%d),stub!\n",This,dolock); + return S_OK; +} + +static IClassFactoryVtbl CF_Vtbl = +{ + CF_QueryInterface, + CF_AddRef, + CF_Release, + CF_CreateInstance, + CF_LockServer +}; + +/******************************************************************************* + * DllGetClassObject [URLMON.@] + * Retrieves class object from a DLL object + * + * NOTES + * Docs say returns STDAPI + * + * PARAMS + * rclsid [I] CLSID for the class object + * riid [I] Reference to identifier of interface for class object + * ppv [O] Address of variable to receive interface pointer for riid + * + * RETURNS + * Success: S_OK + * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG, + * E_UNEXPECTED + */ + +DWORD WINAPI URLMON_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) +{ + int i; + IClassFactoryImpl *factory; + + TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); + + if ( !IsEqualGUID( &IID_IClassFactory, riid ) + && ! IsEqualGUID( &IID_IUnknown, riid) ) + return E_NOINTERFACE; + + for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) + { + if (IsEqualGUID(object_creation[i].clsid, rclsid)) + break; + } + + if (i == sizeof(object_creation)/sizeof(object_creation[0])) + { + FIXME("%s: no class found.\n", debugstr_guid(rclsid)); + return CLASS_E_CLASSNOTAVAILABLE; + } + + factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory)); + if (factory == NULL) return E_OUTOFMEMORY; + + factory->ITF_IClassFactory.lpVtbl = &CF_Vtbl; + factory->ref = 1; + + factory->pfnCreateInstance = object_creation[i].pfnCreateInstance; + + *ppv = &(factory->ITF_IClassFactory); + return S_OK; +} + + +/*********************************************************************** + * DllRegisterServerEx (URLMON.@) + */ +HRESULT WINAPI URLMON_DllRegisterServerEx(void) +{ + FIXME("(void): stub\n"); + + return E_FAIL; +} + +/************************************************************************** + * UrlMkSetSessionOption (URLMON.@) + */ +HRESULT WINAPI UrlMkSetSessionOption(DWORD dwOption, LPVOID *pBuffer, DWORD dwBufferLength, + DWORD Reserved) +{ + FIXME("(%#lx, %p, %#lx): stub\n", dwOption, pBuffer, dwBufferLength); + + return S_OK; +} + +/************************************************************************** + * UrlMkGetSessionOption (URLMON.@) + */ +HRESULT WINAPI UrlMkGetSessionOption(DWORD dwOption, LPVOID *pBuffer, DWORD dwBufferLength, + DWORD* pdwBufferLength, DWORD dwReserved) +{ + FIXME("(%#lx, %p, %#lx, %p): stub\n", dwOption, pBuffer, dwBufferLength, pdwBufferLength); + + return S_OK; +} + +/************************************************************************** + * ObtainUserAgentString (URLMON.@) + */ +HRESULT WINAPI ObtainUserAgentString(DWORD dwOption, LPCSTR pcszUAOut, DWORD *cbSize) +{ + FIXME("(%ld, %p, %p): stub\n", dwOption, pcszUAOut, cbSize); + + if(dwOption) { + ERR("dwOption: %ld, must be zero\n", dwOption); + } + + return S_OK; +} + +HRESULT WINAPI CoInternetCombineUrl(LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, + LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved) +{ + HRESULT hres; + DWORD size = cchResult; + + TRACE("(%s,%s,0x%08lx,%p,%ld,%p,%ld)\n", debugstr_w(pwzBaseUrl), debugstr_w(pwzRelativeUrl), dwCombineFlags, + pwzResult, cchResult, pcchResult, dwReserved); + hres = UrlCombineW(pwzBaseUrl, pwzRelativeUrl, pwzResult, &size, dwCombineFlags); + if(pcchResult) *pcchResult = size; + return hres; +} + +HRESULT WINAPI CoInternetCompareUrl(LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags) +{ + TRACE("(%s,%s,%08lx)\n", debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags); + return UrlCompareW(pwzUrl1, pwzUrl2, dwCompareFlags)==0?S_OK:S_FALSE; +} + +/************************************************************************** + * IsValidURL (URLMON.@) + * + * Determines if a specified string is a valid URL. + * + * PARAMS + * pBC [I] ignored, must be NULL. + * szURL [I] string that represents the URL in question. + * dwReserved [I] reserved and must be zero. + * + * RETURNS + * Success: S_OK. + * Failure: S_FALSE. + * returns E_INVALIDARG if one or more of the args is invalid. + * + * TODO: + * test functionality against windows to see what a valid URL is. + */ +HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved) +{ + FIXME("(%p, %s, %ld): stub\n", pBC, debugstr_w(szURL), dwReserved); + + if (pBC != NULL || dwReserved != 0) + return E_INVALIDARG; + + return S_OK; +} diff --git a/reactos/lib/urlmon/urlmon_main.h b/reactos/lib/urlmon/urlmon_main.h new file mode 100644 index 00000000000..7bd3b06b54d --- /dev/null +++ b/reactos/lib/urlmon/urlmon_main.h @@ -0,0 +1,33 @@ +/* + * Copyright 2002 Huw D M Davies 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_URLMON_MAIN_H +#define __WINE_URLMON_MAIN_H + +#include + +#include "windef.h" +#include "winbase.h" + +extern HINSTANCE URLMON_hInstance; +extern HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj); +extern HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj); + +#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field)) + +#endif /* __WINE_URLMON_MAIN_H */