Re: URLDownloadToFile patch

Marius Grigoriu <[email protected]>
Newsgroups gmane.comp.emulators.winex.devel
Message-ID <[email protected]>
Oops, didn't check the reply to address. Here is a copy of the new patch 
to the list serv.

David Hammerton wrote:
> Hi Marius,
> 
> That looks good to me, except for one issue.
> 
> You seem to duplicate code between the A and the W versions of the  
> function. The W is just the wide char version of the function, so what  
> we would normally do is something like this:
> 
> Implement the W version of the function, as you have done,
> 
> Implement the A version of the function as a wrapper around the W  
> version, converting all the strings, as necessary, to WCHAR*'s.  There  
> are plenty of examples all throughout the WineX source code of how to  
> do this.
> 
> So if you want to make these changes, I'll apply your patch.
> 
> Let me know if you need any assistance with those fixes.
> 
> Thanks very much, and good work!
> 
> David
> 
> On 15-Jan-04, at 2:14 PM, Marius Grigoriu wrote:
> 
>> This is my first encounter with the Wine(X) code so it might not be  
>> done The Righ Way. I implemented the URLDownloadToFile functions in  
>> urlmon.dll. With this code, I was able to get the Anarchy Online  
>> downloader to obtain the installation files and install the game. Let  
>> me know what I can do to improve my future submissions.
>> Index: dlls/urlmon/umon.c
>> ===================================================================
>> RCS file: /cvsroot/winex/dlls/urlmon/umon.c,v
>> retrieving revision 1.5
>> diff -u -r1.5 umon.c
>> --- dlls/urlmon/umon.c    25 Jul 2003 21:45:20 -0000    1.5
>> +++ dlls/urlmon/umon.c    15 Jan 2004 19:00:37 -0000
>> @@ -1002,3 +1002,163 @@
>>      return hr;
>>  }
>>
>> +/ 
>> *********************************************************************** 
>> *******
>> + * URLDownloadToFileA    (URLMON.@)
>> + *
>> + * Given a URL, download the data and save it to the specified file
>> + *
>> + * Bugs
>> + *     Total file size is unknown and not reported to the callback  
>> causing some
>> + *     issues with progress bars using the data.
>> + *     Original specification calls for return values of S_OK and  
>> E_OUTOFMEMORY
>> + *
>> + * Returns
>> + *     S_OK        success
>> + *     E_FAIL    error
>> + */
>> +HRESULT WINAPI URLDownloadToFileA(
>> +    LPUNKNOWN pCaller,           /*address of calling COM component*/
>> +    LPCSTR szURL,                 /*url to download*/
>> +    LPCSTR szFileName,           /*file to save to*/
>> +    DWORD dwReserved,            /*must be 0*/
>> +    LPBINDSTATUSCALLBACK lpfnCB  /*address of IBindStatusCallback*/
>> +    )
>> +{
>> +    HINTERNET hInternet, hResource;
>> +    HRESULT hRes = S_OK;
>> +
>> +    TRACE("urlmon:(%p, %s, %s, %li, %p): stub\n", pCaller, szURL,  
>> szFileName, dwReserved, lpfnCB);
>> +
>> +    /* If the callback returns E_ABORT, we cancel the download */
>> +  if(lpfnCB && IBindStatusCallback_OnProgress(lpfnCB, 0, 0,  
>> BINDSTATUS_CONNECTING, NULL) == E_ABORT)
>> +        return S_OK;
>> +
>> +    hInternet = InternetOpenA("User Agent", 0, NULL, NULL, 0);
>> +    if(!hInternet){
>> +        ERR("URLDownloadToFileA: InternetOpen error: %li", 
>> GetLastError());
>> +        return E_FAIL;
>> +    }
>> +
>> +    hResource = InternetOpenUrlA(hInternet, szURL, NULL, -1, 0, 0);
>> +    if(!hResource){
>> +        ERR("URLDownloadToFileA: InternetOpenUrl error:%li",  
>> GetLastError());
>> +        return E_FAIL;
>> +    }
>> +   
>> +
>> +    if(lpfnCB && IBindStatusCallback_OnProgress(lpfnCB, 0, 0,  
>> BINDSTATUS_DOWNLOADINGDATA, NULL) != E_ABORT){
>> +        char buf[4096];
>> +        DWORD bytesRead, totalRead = 0;
>> +       
>> +        HANDLE hFile = CreateFileA(szFileName, GENERIC_WRITE, 0, NULL,
>> +                CREATE_ALWAYS, 0, 0);
>> +        if(hFile == INVALID_HANDLE_VALUE){
>> +            ERR("URLDownloadToFileA: Unable to open file for write: 
>> %li",  GetLastError());
>> +            hRes = E_FAIL;
>> +        }
>> +        else while(InternetReadFile(hResource, buf, 4096, &bytesRead)){
>> +            if(!bytesRead) break;
>> +            if(!WriteFile(hFile, buf, bytesRead, NULL, NULL)){
>> +                ERR("URLDownloadToFileA: Error writing to file %s: 
>> %li",  szFileName,
>> +                        GetLastError());
>> +                hRes = E_FAIL;
>> +            }
>> +            totalRead += bytesRead;
>> +            if(lpfnCB && IBindStatusCallback_OnProgress(lpfnCB, 
>> totalRead, 0,  BINDSTATUS_DOWNLOADINGDATA, NULL) == E_ABORT) break;
>> +        }
>> +
>> +        if(!CloseHandle(hFile))
>> +            WARN("URLDownloadToFileA: CloseHandle failed: %li",  
>> GetLastError());
>> +               
>> +    }
>> +   
>> +    if(!InternetCloseHandle(hResource) ||  
>> !InternetCloseHandle(hInternet)){
>> +        WARN("URLDownloadToFileA: %li", GetLastError());
>> +    }
>> +
>> +    return hRes;
>> +}
>> +
>> +/ 
>> *********************************************************************** 
>> *******
>> + * URLDownloadToFileW    (URLMON.@)
>> + *
>> + * Given a URL, download the data and save it to the specified file
>> + *
>> + * Bugs
>> + *     Total file size is unknown and not reported to the callback  
>> causing some
>> + *     issues with progress bars using the data.
>> + *     Original specification calls for return values of S_OK and  
>> E_OUTOFMEMORY
>> + *
>> + * Returns
>> + *     S_OK        success
>> + *     E_FAIL    error
>> + */
>> +HRESULT WINAPI URLDownloadToFileW(
>> +    LPUNKNOWN pCaller,           /*address of calling COM component*/
>> +    LPCWSTR szURL,                 /*url to download*/
>> +    LPCWSTR szFileName,          /*file to save to*/
>> +    DWORD dwReserved,            /*must be 0*/
>> +    LPBINDSTATUSCALLBACK lpfnCB  /*address of IBindStatusCallback*/
>> +    )
>> +{
>> +    HINTERNET hInternet, hResource;
>> +    HRESULT hRes = S_OK;
>> +
>> +    TRACE("urlmon:(%p, %s, %s, %li, %p): stub\n",
>> +            pCaller, debugstr_w(szURL), debugstr_w(szFileName), 
>> dwReserved,
>> +            lpfnCB);
>> +
>> +    /* If the callback returns E_ABORT, we cancel the download */
>> +    if(lpfnCB && IBindStatusCallback_OnProgress(
>> +              lpfnCB, 0, 0, BINDSTATUS_CONNECTING, NULL) == 
>> E_ABORT)return  S_OK;
>> +
>> +    hInternet = InternetOpenA("User Agent", 0, NULL, NULL, 0);
>> +    if(!hInternet){
>> +        ERR("URLDownloadToFileW: InternetOpen error: %li", 
>> GetLastError());
>> +        return E_FAIL;
>> +    }
>> +
>> +    hResource = InternetOpenUrlW(hInternet, szURL, NULL, -1, 0, 0);
>> +    if(!hResource){
>> +        ERR("URLDownloadToFileW: InternetOpenUrl error:%li",  
>> GetLastError());
>> +        return E_FAIL;
>> +    }
>> +   
>> +
>> +    if(lpfnCB && IBindStatusCallback_OnProgress(
>> +                lpfnCB, 0, 0, BINDSTATUS_DOWNLOADINGDATA, NULL) != 
>> E_ABORT){
>> +        char buf[4096];
>> +        DWORD bytesRead, totalRead = 0;
>> +       
>> +        HANDLE hFile = CreateFileW(szFileName, GENERIC_WRITE, 0, NULL,
>> +                CREATE_ALWAYS, 0, 0);
>> +        if(hFile == INVALID_HANDLE_VALUE){
>> +            ERR("URLDownloadToFileW: Unable to open file for write: 
>> %li",
>> +                    GetLastError());
>> +            hRes = E_FAIL;
>> +        }
>> +        else while(InternetReadFile(hResource, buf, 4096, &bytesRead)){
>> +            if(!bytesRead) break;
>> +            if(!WriteFile(hFile, buf, bytesRead, NULL, NULL)){
>> +                ERR("URLDownloadToFileW: Error writing to file %s: %li",
>> +                        debugstr_w(szFileName), GetLastError());
>> +                hRes = E_FAIL;
>> +            }
>> +            totalRead += bytesRead;
>> +        /* Report how much we downloaded, but the total file size is  
>> unknown */
>> +            if(lpfnCB && IBindStatusCallback_OnProgress(
>> +            lpfnCB, totalRead, 0, BINDSTATUS_DOWNLOADINGDATA, NULL) 
>> == E_ABORT)
>> +                break;
>> +        }
>> +
>> +        if(!CloseHandle(hFile))
>> +            WARN("URLDownloadToFileW: CloseHandle failed: %li",  
>> GetLastError());
>> +               
>> +    }
>> +   
>> +    if(!InternetCloseHandle(hResource) ||  
>> !InternetCloseHandle(hInternet)){
>> +        WARN("URLDownloadToFileW: %li", GetLastError());
>> +    }
>> +
>> +    return hRes;
>> +}
>> Index: dlls/urlmon/urlmon.spec
>> ===================================================================
>> RCS file: /cvsroot/winex/dlls/urlmon/urlmon.spec,v
>> retrieving revision 1.3
>> diff -u -r1.3 urlmon.spec
>> --- dlls/urlmon/urlmon.spec    23 Dec 2002 19:39:20 -0000    1.3
>> +++ dlls/urlmon/urlmon.spec    15 Jan 2004 19:00:37 -0000
>> @@ -72,8 +72,8 @@
>>  @ stub URLDownloadA
>>  @ stub URLDownloadToCacheFileA
>>  @ stub URLDownloadToCacheFileW
>> -@ stub URLDownloadToFileA
>> -@ stub URLDownloadToFileW
>> +@ stdcall URLDownloadToFileA(ptr str str long ptr) URLDownloadToFileA
>> +@ stdcall URLDownloadToFileW(ptr wstr wstr long ptr)  URLDownloadToFileW
>>  @ stub URLDownloadW
>>  @ stub URLOpenBlockingStreamA
>>  @ stub URLOpenBlockingStreamW
>> Index: include/urlmon.h
>> ===================================================================
>> RCS file: /cvsroot/winex/include/urlmon.h,v
>> retrieving revision 1.1.1.5
>> diff -u -r1.1.1.5 urlmon.h
>> --- include/urlmon.h    17 Feb 2003 02:46:04 -0000    1.1.1.5
>> +++ include/urlmon.h    15 Jan 2004 19:00:37 -0000
>> @@ -275,7 +275,9 @@
>>
>>  HRESULT WINAPI CreateURLMoniker(IMoniker *pmkContext, LPCWSTR szURL,  
>> IMoniker **ppmk);
>>  HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc,  
>> IBindStatusCallback *pbsc, IBindStatusCallback **ppbsc, DWORD  
>> dwReserved);
>> -
>> +#define    URLDownloadToFile WINELIB_NAME_AW(URLDownloadToFile)
>> +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) */
>> _______________________________________________
>> winex-devel mailing list
>> [email protected]
>> http://lists.transgaming.org/cgi-bin/mailman/listinfo/winex-devel
>>
> -- 
> David Hammerton
> WineX developer
> TransGaming Technologies
> Bus: +1 416 979 9900 x329
> Fax: +1 416 979 9908
> [email protected]
> http://www.transgaming.com
> *Let the Games Begin*

_______________________________________________
winex-devel mailing list
[email protected]
http://lists.transgaming.org/cgi-bin/mailman/listinfo/winex-devel
URLDownloadToFile.patch (text/plain, 5.4 KB)
Index: dlls/urlmon/umon.c
===================================================================
RCS file: /cvsroot/winex/dlls/urlmon/umon.c,v
retrieving revision 1.5
diff -u -r1.5 umon.c
--- dlls/urlmon/umon.c	25 Jul 2003 21:45:20 -0000	1.5
+++ dlls/urlmon/umon.c	15 Jan 2004 20:14:07 -0000
@@ -35,6 +35,7 @@
 #include "urlmon.h"
 #include "wininet.h"
 #include "urlmon_main.h"
+#include "heap.h"
 
 
 DEFAULT_DEBUG_CHANNEL(urlmon);
@@ -1002,3 +1003,110 @@
     return hr;
 }
 
+/******************************************************************************
+ * URLDownloadToFileW	(URLMON.@)
+ *
+ * Given a URL, download the data and save it to the specified file
+ *
+ * Bugs
+ * 	Total file size is unknown and not reported to the callback causing some
+ * 	issues with progress bars using the data.
+ * 	Original specification calls for return values of S_OK and E_OUTOFMEMORY
+ *
+ * Returns
+ * 	S_OK	success
+ * 	E_FAIL	error
+ */
+HRESULT WINAPI URLDownloadToFileW(
+    LPUNKNOWN pCaller,           /*address of calling COM component*/
+    LPCWSTR szURL,	             /*url to download*/
+    LPCWSTR szFileName,          /*file to save to*/
+    DWORD dwReserved,            /*must be 0*/
+    LPBINDSTATUSCALLBACK lpfnCB  /*address of IBindStatusCallback*/
+    )
+{
+	HINTERNET hInternet, hResource;
+	HRESULT hRes = S_OK;
+
+	TRACE("urlmon:(%p, %s, %s, %li, %p): stub\n", 
+			pCaller, debugstr_w(szURL), debugstr_w(szFileName), dwReserved, 
+			lpfnCB);
+
+	/* If the callback returns E_ABORT, we cancel the download */
+	if(lpfnCB && IBindStatusCallback_OnProgress(
+			  lpfnCB, 0, 0, BINDSTATUS_CONNECTING, NULL) == E_ABORT)return S_OK;
+
+	hInternet = InternetOpenA("User Agent", 0, NULL, NULL, 0);
+	if(!hInternet){
+		ERR("URLDownloadToFileW: InternetOpen error: %li", GetLastError());
+		return E_FAIL;
+	}
+
+	hResource = InternetOpenUrlW(hInternet, szURL, NULL, -1, 0, 0);
+	if(!hResource){
+		ERR("URLDownloadToFileW: InternetOpenUrl error:%li", GetLastError());
+		return E_FAIL;
+	}
+	
+
+	if(lpfnCB && IBindStatusCallback_OnProgress(
+				lpfnCB, 0, 0, BINDSTATUS_DOWNLOADINGDATA, NULL) != E_ABORT){
+		char buf[4096];
+		DWORD bytesRead, totalRead = 0;
+		
+		HANDLE hFile = CreateFileW(szFileName, GENERIC_WRITE, 0, NULL, 
+				CREATE_ALWAYS, 0, 0);
+		if(hFile == INVALID_HANDLE_VALUE){
+			ERR("URLDownloadToFileW: Unable to open file for write: %li", 
+					GetLastError());
+			hRes = E_FAIL;
+		}
+		else while(InternetReadFile(hResource, buf, 4096, &bytesRead)){
+			if(!bytesRead) break;
+			if(!WriteFile(hFile, buf, bytesRead, NULL, NULL)){
+				ERR("URLDownloadToFileW: Error writing to file %s: %li", 
+						debugstr_w(szFileName), GetLastError());
+				hRes = E_FAIL;
+			}
+			totalRead += bytesRead;
+		/* Report how much we downloaded, but the total file size is unknown */
+			if(lpfnCB && IBindStatusCallback_OnProgress(
+			lpfnCB, totalRead, 0, BINDSTATUS_DOWNLOADINGDATA, NULL) == E_ABORT)
+				break;
+		}
+
+		if(!CloseHandle(hFile))
+			WARN("URLDownloadToFileW: CloseHandle failed: %li", GetLastError());
+				
+	}
+	
+	if(!InternetCloseHandle(hResource) || !InternetCloseHandle(hInternet)){
+		WARN("URLDownloadToFileW: %li", GetLastError());
+	}
+
+	return hRes;
+}
+
+HRESULT WINAPI URLDownloadToFileA(
+    LPUNKNOWN pCaller,           /*address of calling COM component*/
+    LPCSTR szURL,	             /*url to download*/
+    LPCSTR szFileName,           /*file to save to*/
+    DWORD dwReserved,            /*must be 0*/
+    LPBINDSTATUSCALLBACK lpfnCB  /*address of IBindStatusCallback*/
+	)
+{
+	HRESULT hRes;
+	LPWSTR szURLW, szFileNameW;
+
+	szURLW = HEAP_strdupAtoW(GetProcessHeap(), 0, szURL);
+	szFileNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, szFileName);
+
+	hRes = URLDownloadToFileW(pCaller, szURLW, szFileNameW, dwReserved, lpfnCB);
+
+	HeapFree(GetProcessHeap(), 0, szURLW);
+	HeapFree(GetProcessHeap(), 0, szFileNameW);
+
+	return hRes;
+}
+
+
Index: dlls/urlmon/urlmon.spec
===================================================================
RCS file: /cvsroot/winex/dlls/urlmon/urlmon.spec,v
retrieving revision 1.3
diff -u -r1.3 urlmon.spec
--- dlls/urlmon/urlmon.spec	23 Dec 2002 19:39:20 -0000	1.3
+++ dlls/urlmon/urlmon.spec	15 Jan 2004 20:14:07 -0000
@@ -72,8 +72,8 @@
 @ stub URLDownloadA
 @ stub URLDownloadToCacheFileA
 @ stub URLDownloadToCacheFileW
-@ stub URLDownloadToFileA
-@ stub URLDownloadToFileW
+@ stdcall URLDownloadToFileA(ptr str str long ptr) URLDownloadToFileA
+@ stdcall URLDownloadToFileW(ptr wstr wstr long ptr) URLDownloadToFileW
 @ stub URLDownloadW
 @ stub URLOpenBlockingStreamA
 @ stub URLOpenBlockingStreamW
Index: include/urlmon.h
===================================================================
RCS file: /cvsroot/winex/include/urlmon.h,v
retrieving revision 1.1.1.5
diff -u -r1.1.1.5 urlmon.h
--- include/urlmon.h	17 Feb 2003 02:46:04 -0000	1.1.1.5
+++ include/urlmon.h	15 Jan 2004 20:14:09 -0000
@@ -275,7 +275,9 @@
 
 HRESULT WINAPI CreateURLMoniker(IMoniker *pmkContext, LPCWSTR szURL, IMoniker **ppmk);
 HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc, IBindStatusCallback **ppbsc, DWORD dwReserved);
-
+#define	URLDownloadToFile WINELIB_NAME_AW(URLDownloadToFile)
+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) */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.