ReactOS 0.4.16-dev-1170-ge326b06
dwnl.c
Go to the documentation of this file.
1#define COBJMACROS
2#include <urlmon.h>
3#include <wininet.h>
4#include <wchar.h>
5#include <strsafe.h>
6#include <conutils.h>
7
8#include "resource.h"
9
10/* FIXME: add correct definitions to urlmon.idl */
11#ifdef UNICODE
12#define URLDownloadToFile URLDownloadToFileW
13#else
14#define URLDownloadToFile URLDownloadToFileA
15#endif
16
17#define DWNL_E_LASTERROR 0
18#define DWNL_E_NEEDTARGETFILENAME -1
19#define DWNL_E_UNSUPPORTEDSCHEME -2
20
21typedef struct
22{
23 const IBindStatusCallbackVtbl* lpIBindStatusCallbackVtbl;
26 WCHAR szMimeType[128];
34
35#define impl_to_interface(impl,iface) (struct iface *)(&(impl)->lp##iface##Vtbl)
36#define interface_to_impl(instance,iface) ((CBindStatusCallback*)((ULONG_PTR)instance - FIELD_OFFSET(CBindStatusCallback,lp##iface##Vtbl)))
37
38static void
40{
41 return;
42}
43
44static void
46{
48 WCHAR szTxt[128];
50
51 va_start(args, lpFmt);
52 StringCbVPrintfW(szTxt, sizeof(szTxt), lpFmt, args);
53 va_end(args);
54
56 {
57 ConPrintf(StdOut, L"\r%*.*s", -(csbi.dwSize.X - 1), csbi.dwSize.X - 1, szTxt);
58 }
59 else
60 {
61 ConPuts(StdOut, szTxt);
62 }
63}
64
65static void
67{
68 WCHAR szMessage[MAX_PATH];
69
70 /* FIXME: better output */
71 if (This->Size != 0)
72 {
73 UINT Percentage;
74
75 Percentage = (UINT)((This->Progress * 100) / This->Size);
76 // If percentage is greater than 99% but sizes don't match, do a failsafe.
77 if ((Percentage > 99) && (This->Progress != This->Size))
78 Percentage = 99;
79
80 LoadStringW(NULL, IDS_BYTES_DOWNLOADED_FULL, szMessage, ARRAYSIZE(szMessage));
81
82 write_status(szMessage, Percentage, This->Progress);
83 }
84 else
85 {
86 LoadStringW(NULL, IDS_BYTES_DOWNLOADED, szMessage, ARRAYSIZE(szMessage));
87
88 /* Unknown size */
89 write_status(szMessage, This->Progress);
90 }
91}
92
95{
97 ULONG ret;
98
100 return ret;
101}
102
105{
107 ULONG ret;
108
110 if (ret == 0)
111 {
113
115 0,
116 This);
117 }
118
119 return ret;
120}
121
124 REFIID iid,
125 PVOID *pvObject)
126{
128
129 *pvObject = NULL;
130
131 if (IsEqualIID(iid,
132 &IID_IBindStatusCallback) ||
133 IsEqualIID(iid,
134 &IID_IUnknown))
135 {
137 }
138 else
139 return E_NOINTERFACE;
140
142 return S_OK;
143}
144
148 IBinding* pib)
149{
150 return E_NOTIMPL;
151}
152
155 LONG* pnPriority)
156{
157 return E_NOTIMPL;
158}
159
163{
164 return E_NOTIMPL;
165}
166
169 ULONG ulProgress,
170 ULONG ulProgressMax,
171 ULONG ulStatusCode,
172 LPCWSTR szStatusText)
173{
175
176 switch (ulStatusCode)
177 {
178 case BINDSTATUS_FINDINGRESOURCE:
179 if (!This->bResolving)
180 {
181 wcscpy(This->szHostName, szStatusText);
182 This->bResolving = TRUE;
183
184 ConResPrintf(StdOut, IDS_RESOLVING, This->szHostName);
185 }
186 break;
187
188 case BINDSTATUS_CONNECTING:
189 This->bConnecting = TRUE;
190 This->bSendingReq = FALSE;
191 This->bBeginTransfer = FALSE;
192 This->szMimeType[0] = L'\0';
193 if (This->bResolving)
194 {
196 ConResPrintf(StdOut, IDS_CONNECTING_TO_FULL, This->szHostName, szStatusText);
197 }
198 else
199 {
200 ConResPrintf(StdOut, IDS_CONNECTING_TO, szStatusText);
201 }
202 break;
203
204 case BINDSTATUS_REDIRECTING:
205 This->bResolving = FALSE;
206 This->bConnecting = FALSE;
207 This->bSendingReq = FALSE;
208 This->bBeginTransfer = FALSE;
209 This->szMimeType[0] = L'\0';
210 ConResPrintf(StdOut, IDS_REDIRECTING_TO, szStatusText);
211 break;
212
213 case BINDSTATUS_SENDINGREQUEST:
214 This->bBeginTransfer = FALSE;
215 This->szMimeType[0] = L'\0';
216 if (This->bResolving || This->bConnecting)
218
219 if (!This->bSendingReq)
221
222 This->bSendingReq = TRUE;
223 break;
224
225 case BINDSTATUS_MIMETYPEAVAILABLE:
226 wcscpy(This->szMimeType, szStatusText);
227 break;
228
229 case BINDSTATUS_BEGINDOWNLOADDATA:
230 This->Progress = (UINT64)ulProgress;
231 This->Size = (UINT64)ulProgressMax;
232
233 if (This->bSendingReq)
235
236 if (!This->bBeginTransfer && This->Size != 0)
237 {
238 if (This->szMimeType[0] != L'\0')
239 ConResPrintf(StdOut, IDS_LENGTH_FULL, This->Size, This->szMimeType);
240 else
242 }
243
244 ConPuts(StdOut, L"\n");
245
246 This->bBeginTransfer = TRUE;
247 break;
248
249 case BINDSTATUS_ENDDOWNLOADDATA:
250 /* Since download is completed, update progress one last time to be at 100% */
251 This->Progress = This->Size; // Ensure progress == total size
252 CBindStatusCallback_UpdateProgress(This); // Show 100% progress now
253
255 break;
256
257 case BINDSTATUS_DOWNLOADINGDATA:
258 This->Progress = (UINT64)ulProgress;
259 This->Size = (UINT64)ulProgressMax;
260
262 break;
263 }
264
265 return S_OK;
266}
267
270 HRESULT hresult,
271 LPCWSTR szError)
272{
273 return E_NOTIMPL;
274}
275
278 DWORD* grfBINDF,
279 BINDINFO* pbindinfo)
280{
281 return E_NOTIMPL;
282}
283
286 DWORD grfBSCF,
288 FORMATETC* pformatetc,
289 STGMEDIUM* pstgmed)
290{
291 return E_NOTIMPL;
292}
293
296 REFIID riid,
297 IUnknown* punk)
298{
299 return E_NOTIMPL;
300}
301
302static const struct IBindStatusCallbackVtbl vtblIBindStatusCallback =
303{
315};
316
317static IBindStatusCallback *
319{
321
323 if (This == NULL)
324 return NULL;
325
326 This->lpIBindStatusCallbackVtbl = &vtblIBindStatusCallback;
327 This->ref = 1;
328
330}
331
332
333// ToDo: Show status, get file name from webserver, better error reporting
334
335static int
337 OUT LPWSTR szBuffer,
338 IN PDWORD pdwBufferSize)
339{
340 URL_COMPONENTS urlc;
341
342 /* Hide the password */
343 urlc = *purl;
344 urlc.lpszPassword = NULL;
345 urlc.dwPasswordLength = 0;
346
347 if (!InternetCreateUrl(&urlc, ICU_ESCAPE, szBuffer, pdwBufferSize))
348 return DWNL_E_LASTERROR;
349
350 return 1;
351}
352
353static int
355 IN LPCWSTR pszFile OPTIONAL)
356{
357 WCHAR szScheme[INTERNET_MAX_SCHEME_LENGTH + 1];
358 WCHAR szHostName[INTERNET_MAX_HOST_NAME_LENGTH + 1];
359 WCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH + 1];
360 WCHAR szPassWord[INTERNET_MAX_PASSWORD_LENGTH + 1];
361 WCHAR szUrlPath[INTERNET_MAX_PATH_LENGTH + 1];
362 WCHAR szExtraInfo[INTERNET_MAX_PATH_LENGTH + 1];
364 DWORD dwUrlLen;
365 LPTSTR pszFilePart;
366 URL_COMPONENTS urlc;
368 int iRet;
369 SYSTEMTIME sysTime;
370
371 if (pszFile != NULL && pszFile[0] == L'\0')
372 pszFile = NULL;
373
374 urlc.dwStructSize = sizeof(urlc);
375 urlc.lpszScheme = szScheme;
376 urlc.dwSchemeLength = sizeof(szScheme) / sizeof(szScheme[0]);
377 urlc.lpszHostName = szHostName;
378 urlc.dwHostNameLength = sizeof(szHostName) / sizeof(szHostName[0]);
379 urlc.lpszUserName = szUserName;
380 urlc.dwUserNameLength = sizeof(szUserName) / sizeof(szUserName[0]);
381 urlc.lpszPassword = szPassWord;
382 urlc.dwPasswordLength = sizeof(szPassWord) / sizeof(szPassWord[0]);
383 urlc.lpszUrlPath = szUrlPath;
384 urlc.dwUrlPathLength = sizeof(szUrlPath) / sizeof(szUrlPath[0]);
385 urlc.lpszExtraInfo = szExtraInfo;
386 urlc.dwExtraInfoLength = sizeof(szExtraInfo) / sizeof(szExtraInfo[0]);
387 if (!InternetCrackUrl(pszUrl, wcslen(pszUrl), ICU_ESCAPE, &urlc))
388 return DWNL_E_LASTERROR;
389
390 if (urlc.nScheme != INTERNET_SCHEME_FTP &&
394 {
396 }
397
398 if (urlc.nScheme == INTERNET_SCHEME_FTP && urlc.dwUserNameLength == 0 && urlc.dwPasswordLength == 0)
399 {
400 wcscpy(szUserName, L"anonymous");
401 urlc.dwUserNameLength = wcslen(szUserName);
402 }
403
404 /* FIXME: Get file name from server */
405 if (urlc.dwUrlPathLength == 0 && pszFile == NULL)
407
408 pszFilePart = wcsrchr(szUrlPath, L'/');
409 if (pszFilePart != NULL)
410 pszFilePart++;
411
412 if (pszFilePart == NULL && pszFile == NULL)
414
415 if (pszFile == NULL)
416 pszFile = pszFilePart;
417
418 if (urlc.dwUserNameLength == 0)
419 urlc.lpszUserName = NULL;
420
421 if (urlc.dwPasswordLength == 0)
422 urlc.lpszPassword = NULL;
423
424 /* Generate the URL to be displayed (without a password) */
425 dwUrlLen = sizeof(szUrl) / sizeof(szUrl[0]);
426 iRet = get_display_url(&urlc, szUrl, &dwUrlLen);
427 if (iRet <= 0)
428 return iRet;
429
430 GetLocalTime(&sysTime);
431
432 ConPrintf(StdOut, L"--%d-%02d-%02d %02d:%02d:%02d-- %s\n\t=> %s\n",
433 sysTime.wYear, sysTime.wMonth, sysTime.wDay,
434 sysTime.wHour, sysTime.wMinute, sysTime.wSecond,
435 szUrl, pszFile);
436
437 /* Generate the URL to download */
438 dwUrlLen = sizeof(szUrl) / sizeof(szUrl[0]);
439 if (!InternetCreateUrl(&urlc, ICU_ESCAPE, szUrl, &dwUrlLen))
440 return DWNL_E_LASTERROR;
441
443 if (pbsc == NULL)
444 return DWNL_E_LASTERROR;
445
446 if(!SUCCEEDED(URLDownloadToFile(NULL, szUrl, pszFile, 0, pbsc)))
447 {
448 IBindStatusCallback_Release(pbsc);
449 return DWNL_E_LASTERROR; /* FIXME */
450 }
451
452 IBindStatusCallback_Release(pbsc);
453 return 1;
454}
455
456static int
457print_err(int iErr)
458{
459 write_status(L"");
460
461 if (iErr == DWNL_E_LASTERROR)
462 {
464 {
465 /* File not found */
467 }
468 else
469 {
470 /* Display last error code */
472 }
473 }
474 else
475 {
476 switch (iErr)
477 {
480 break;
481
484 break;
485 }
486 }
487
488 return 1;
489}
490
491int wmain(int argc, WCHAR **argv)
492{
493 int iErr, iRet = 0;
494
495 /* Initialize the Console Standard Streams */
497
498 if(argc != 2 && argc != 3)
499 {
501 return 2;
502 }
503
504 iErr = download_file(argv[1], argc == 3 ? argv[2] : NULL);
505 if (iErr <= 0)
506 iRet = print_err(iErr);
507
508 return iRet;
509}
unsigned long long UINT64
static int argc
Definition: ServiceArgs.c:12
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define IDS_USAGE
Definition: resource.h:3
void ConPuts(FILE *fp, LPCWSTR psz)
Definition: fc.c:16
#define ConInitStdStreams()
Definition: fc.c:13
void ConPrintf(FILE *fp, LPCWSTR psz,...)
Definition: fc.c:20
#define StdOut
Definition: fc.c:14
void ConResPrintf(FILE *fp, UINT nID,...)
Definition: fc.c:33
#define StdErr
Definition: fc.c:15
#define IDS_CONNECTING_TO_FULL
Definition: resource.h:10
#define IDS_REDIRECTING_TO
Definition: resource.h:12
#define IDS_LENGTH
Definition: resource.h:8
#define IDS_BYTES_DOWNLOADED_FULL
Definition: resource.h:15
#define IDS_BYTES_DOWNLOADED
Definition: resource.h:14
#define IDS_RESOLVING
Definition: resource.h:5
#define IDS_DONE
Definition: resource.h:6
#define IDS_ERROR_DOWNLOAD
Definition: resource.h:17
#define IDS_LENGTH_FULL
Definition: resource.h:7
#define IDS_ERROR_PROTOCOL
Definition: resource.h:20
#define IDS_SEND_REQUEST
Definition: resource.h:13
#define IDS_ERROR_CODE
Definition: resource.h:18
#define IDS_CONNECTING_TO
Definition: resource.h:11
#define IDS_ERROR_FILENAME
Definition: resource.h:19
#define IDS_FILE_SAVED
Definition: resource.h:9
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
BOOL WINAPI GetConsoleScreenBufferInfo(IN HANDLE hConsoleOutput, OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
Definition: console.c:595
const GUID IID_IUnknown
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
wcscpy
#define E_NOTIMPL
Definition: ddrawi.h:99
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define GetProcessHeap()
Definition: compat.h:736
#define wcsrchr
Definition: compat.h:16
#define HeapAlloc
Definition: compat.h:733
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
VOID WINAPI GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:286
#define INTERNET_MAX_URL_LENGTH
Definition: session.c:1418
r reserved
Definition: btrfs.c:3006
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
Definition: dwnl.c:154
static int download_file(IN LPCWSTR pszUrl, IN LPCWSTR pszFile OPTIONAL)
Definition: dwnl.c:354
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
Definition: dwnl.c:295
static ULONG STDMETHODCALLTYPE CBindStatusCallback_AddRef(IBindStatusCallback *iface)
Definition: dwnl.c:94
#define DWNL_E_NEEDTARGETFILENAME
Definition: dwnl.c:18
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
Definition: dwnl.c:285
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
Definition: dwnl.c:161
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
Definition: dwnl.c:277
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved, IBinding *pib)
Definition: dwnl.c:146
#define DWNL_E_LASTERROR
Definition: dwnl.c:17
#define DWNL_E_UNSUPPORTEDSCHEME
Definition: dwnl.c:19
static void CBindStatusCallback_Destroy(CBindStatusCallback *This)
Definition: dwnl.c:39
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
Definition: dwnl.c:269
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
Definition: dwnl.c:168
static int print_err(int iErr)
Definition: dwnl.c:457
static const struct IBindStatusCallbackVtbl vtblIBindStatusCallback
Definition: dwnl.c:302
#define impl_to_interface(impl, iface)
Definition: dwnl.c:35
#define URLDownloadToFile
Definition: dwnl.c:14
static void CBindStatusCallback_UpdateProgress(CBindStatusCallback *This)
Definition: dwnl.c:66
static void write_status(LPCWSTR lpFmt,...)
Definition: dwnl.c:45
static ULONG STDMETHODCALLTYPE CBindStatusCallback_Release(IBindStatusCallback *iface)
Definition: dwnl.c:104
#define interface_to_impl(instance, iface)
Definition: dwnl.c:36
static IBindStatusCallback * CreateBindStatusCallback(void)
Definition: dwnl.c:318
static int get_display_url(IN LPURL_COMPONENTS purl, OUT LPWSTR szBuffer, IN PDWORD pdwBufferSize)
Definition: dwnl.c:336
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID iid, PVOID *pvObject)
Definition: dwnl.c:123
unsigned long DWORD
Definition: ntddk_ex.h:95
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
#define argv
Definition: mplay32.c:18
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED _In_opt_ LPTRANSMIT_FILE_BUFFERS _In_ DWORD dwReserved
Definition: mswsock.h:95
unsigned int UINT
Definition: ndis.h:50
#define L(x)
Definition: ntvdm.h:50
DWORD * PDWORD
Definition: pedump.c:68
long LONG
Definition: pedump.c:60
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
int wmain()
#define args
Definition: format.c:66
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
STRSAFEAPI StringCbVPrintfW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszFormat, va_list argList)
Definition: strsafe.h:507
const IBindStatusCallbackVtbl * lpIBindStatusCallbackVtbl
Definition: dwnl.c:23
UINT bSendingReq
Definition: dwnl.c:31
UINT bConnecting
Definition: dwnl.c:30
UINT bBeginTransfer
Definition: dwnl.c:32
UINT bResolving
Definition: dwnl.c:29
UINT64 Size
Definition: dwnl.c:27
UINT64 Progress
Definition: dwnl.c:28
LPWSTR lpszScheme
Definition: winhttp.h:466
LPWSTR lpszUserName
Definition: winhttp.h:472
LPWSTR lpszExtraInfo
Definition: winhttp.h:478
DWORD dwPasswordLength
Definition: winhttp.h:475
LPWSTR lpszUrlPath
Definition: winhttp.h:476
DWORD dwHostNameLength
Definition: winhttp.h:470
DWORD dwExtraInfoLength
Definition: winhttp.h:479
DWORD dwUrlPathLength
Definition: winhttp.h:477
LPWSTR lpszHostName
Definition: winhttp.h:469
LPWSTR lpszPassword
Definition: winhttp.h:474
INTERNET_SCHEME nScheme
Definition: winhttp.h:468
DWORD dwStructSize
Definition: winhttp.h:465
DWORD dwUserNameLength
Definition: winhttp.h:473
DWORD dwSchemeLength
Definition: winhttp.h:467
WORD wYear
Definition: winbase.h:937
WORD wMonth
Definition: winbase.h:938
WORD wHour
Definition: winbase.h:941
WORD wSecond
Definition: winbase.h:943
WORD wMinute
Definition: winbase.h:942
WORD wDay
Definition: winbase.h:940
Definition: match.c:390
SHORT X
Definition: blue.h:26
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
int ret
#define STD_OUTPUT_HANDLE
Definition: winbase.h:295
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define E_NOINTERFACE
Definition: winerror.h:2364
#define INTERNET_SCHEME_FTP
Definition: winhttp.h:44
#define INTERNET_SCHEME_HTTP
Definition: winhttp.h:42
#define INTERNET_SCHEME_HTTPS
Definition: winhttp.h:43
#define ICU_ESCAPE
Definition: winhttp.h:48
#define INTERNET_MAX_PASSWORD_LENGTH
Definition: wininet.h:46
#define INTERNET_MAX_HOST_NAME_LENGTH
Definition: wininet.h:44
#define InternetCreateUrl
Definition: wininet.h:454
#define INTERNET_MAX_USER_NAME_LENGTH
Definition: wininet.h:45
@ INTERNET_SCHEME_GOPHER
Definition: wininet.h:140
#define INTERNET_MAX_PATH_LENGTH
Definition: wininet.h:49
#define INTERNET_MAX_SCHEME_LENGTH
Definition: wininet.h:50
#define InternetCrackUrl
Definition: wininet.h:438
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
CHAR * LPTSTR
Definition: xmlstorage.h:192
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185