[URLMON] Implement URLDownloadToFileA/W
Lionel Ulmer
lionel.ulmer at free.fr
Sun Jul 13 16:30:24 CDT 2003
This is needed by Anarchy Online's web downloader tool. Thanks to Mike to
have given me some Win32 code of his which did about what I needed, I just
had to tidy it up, add the QueryInfo call and the callbacks.
Lionel
Changelog:
Mike McCormack <mike at codeweavers.com>
Lionel Ulmer <lionel.ulmer at free.fr>
- implement URLDownloadToFileA/W
--
Lionel Ulmer - http://www.bbrox.org/
-------------- next part --------------
Index: include/urlmon.h
===================================================================
RCS file: /home/wine/wine/include/urlmon.h,v
retrieving revision 1.17
diff -u -r1.17 urlmon.h
--- include/urlmon.h 13 Jun 2003 16:29:36 -0000 1.17
+++ include/urlmon.h 13 Jul 2003 21:27:07 -0000
@@ -312,6 +312,10 @@
HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc, IBindStatusCallback **ppbsc, DWORD dwReserved);
HRESULT WINAPI CompareSecurityIds(BYTE*,DWORD,BYTE*,DWORD,DWORD);
+HRESULT WINAPI URLDownloadToFileA(LPUNKNOWN pCaller, LPCSTR szURL, LPCSTR szFileName, DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB);
+HRESULT WINAPI URLDownloadToFileW(LPUNKNOWN pCaller, LPCWSTR szURL, LPCWSTR szFileName, DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB);
+
+
#ifdef __cplusplus
} /* extern "C" */
#endif /* defined(__cplusplus) */
Index: dlls/urlmon/umon.c
===================================================================
RCS file: /home/wine/wine/dlls/urlmon/umon.c,v
retrieving revision 1.22
diff -u -r1.22 umon.c
--- dlls/urlmon/umon.c 31 Mar 2003 23:58:27 -0000 1.22
+++ dlls/urlmon/umon.c 13 Jul 2003 21:27:08 -0000
@@ -26,6 +26,7 @@
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
+#include "winternl.h"
#include "winuser.h"
#include "objbase.h"
#include "wine/debug.h"
@@ -1013,4 +1014,218 @@
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;
+ 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;
}
Index: dlls/urlmon/urlmon.spec
===================================================================
RCS file: /home/wine/wine/dlls/urlmon/urlmon.spec,v
retrieving revision 1.24
diff -u -r1.24 urlmon.spec
--- dlls/urlmon/urlmon.spec 13 Jun 2003 16:29:36 -0000 1.24
+++ dlls/urlmon/urlmon.spec 13 Jul 2003 21:27:08 -0000
@@ -61,8 +61,8 @@
@ stub URLDownloadA
@ stub URLDownloadToCacheFileA
@ stub URLDownloadToCacheFileW
-@ stub URLDownloadToFileA
-@ stub URLDownloadToFileW
+@ stdcall URLDownloadToFileA(ptr str str long ptr)
+@ stdcall URLDownloadToFileW(ptr wstr wstr long ptr)
@ stub URLDownloadW
@ stub URLOpenBlockingStreamA
@ stub URLOpenBlockingStreamW
More information about the wine-patches
mailing list