ReactOS 0.4.16-dev-311-g9382aa2
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 > 99)
77 Percentage = 99;
78
79 LoadStringW(NULL, IDS_BYTES_DOWNLOADED_FULL, szMessage, ARRAYSIZE(szMessage));
80
81 write_status(szMessage, Percentage, This->Progress);
82 }
83 else
84 {
85 LoadStringW(NULL, IDS_BYTES_DOWNLOADED, szMessage, ARRAYSIZE(szMessage));
86
87 /* Unknown size */
88 write_status(szMessage, This->Progress);
89 }
90}
91
94{
96 ULONG ret;
97
99 return ret;
100}
101
104{
106 ULONG ret;
107
109 if (ret == 0)
110 {
112
114 0,
115 This);
116 }
117
118 return ret;
119}
120
123 REFIID iid,
124 PVOID *pvObject)
125{
127
128 *pvObject = NULL;
129
130 if (IsEqualIID(iid,
131 &IID_IBindStatusCallback) ||
132 IsEqualIID(iid,
133 &IID_IUnknown))
134 {
136 }
137 else
138 return E_NOINTERFACE;
139
141 return S_OK;
142}
143
147 IBinding* pib)
148{
149 return E_NOTIMPL;
150}
151
154 LONG* pnPriority)
155{
156 return E_NOTIMPL;
157}
158
162{
163 return E_NOTIMPL;
164}
165
168 ULONG ulProgress,
169 ULONG ulProgressMax,
170 ULONG ulStatusCode,
171 LPCWSTR szStatusText)
172{
174
175 switch (ulStatusCode)
176 {
177 case BINDSTATUS_FINDINGRESOURCE:
178 if (!This->bResolving)
179 {
180 wcscpy(This->szHostName, szStatusText);
181 This->bResolving = TRUE;
182
183 ConResPrintf(StdOut, IDS_RESOLVING, This->szHostName);
184 }
185 break;
186
187 case BINDSTATUS_CONNECTING:
188 This->bConnecting = TRUE;
189 This->bSendingReq = FALSE;
190 This->bBeginTransfer = FALSE;
191 This->szMimeType[0] = L'\0';
192 if (This->bResolving)
193 {
195 ConResPrintf(StdOut, IDS_CONNECTING_TO_FULL, This->szHostName, szStatusText);
196 }
197 else
198 {
199 ConResPrintf(StdOut, IDS_CONNECTING_TO, szStatusText);
200 }
201 break;
202
203 case BINDSTATUS_REDIRECTING:
204 This->bResolving = FALSE;
205 This->bConnecting = FALSE;
206 This->bSendingReq = FALSE;
207 This->bBeginTransfer = FALSE;
208 This->szMimeType[0] = L'\0';
209 ConResPrintf(StdOut, IDS_REDIRECTING_TO, szStatusText);
210 break;
211
212 case BINDSTATUS_SENDINGREQUEST:
213 This->bBeginTransfer = FALSE;
214 This->szMimeType[0] = L'\0';
215 if (This->bResolving || This->bConnecting)
217
218 if (!This->bSendingReq)
220
221 This->bSendingReq = TRUE;
222 break;
223
224 case BINDSTATUS_MIMETYPEAVAILABLE:
225 wcscpy(This->szMimeType, szStatusText);
226 break;
227
228 case BINDSTATUS_BEGINDOWNLOADDATA:
229 This->Progress = (UINT64)ulProgress;
230 This->Size = (UINT64)ulProgressMax;
231
232 if (This->bSendingReq)
234
235 if (!This->bBeginTransfer && This->Size != 0)
236 {
237 if (This->szMimeType[0] != L'\0')
238 ConResPrintf(StdOut, IDS_LENGTH_FULL, This->Size, This->szMimeType);
239 else
241 }
242
243 ConPuts(StdOut, L"\n");
244
245 This->bBeginTransfer = TRUE;
246 break;
247
248 case BINDSTATUS_ENDDOWNLOADDATA:
250 break;
251
252 case BINDSTATUS_DOWNLOADINGDATA:
253 This->Progress = (UINT64)ulProgress;
254 This->Size = (UINT64)ulProgressMax;
255
257 break;
258 }
259
260 return S_OK;
261}
262
265 HRESULT hresult,
266 LPCWSTR szError)
267{
268 return E_NOTIMPL;
269}
270
273 DWORD* grfBINDF,
274 BINDINFO* pbindinfo)
275{
276 return E_NOTIMPL;
277}
278
281 DWORD grfBSCF,
283 FORMATETC* pformatetc,
284 STGMEDIUM* pstgmed)
285{
286 return E_NOTIMPL;
287}
288
291 REFIID riid,
292 IUnknown* punk)
293{
294 return E_NOTIMPL;
295}
296
297static const struct IBindStatusCallbackVtbl vtblIBindStatusCallback =
298{
310};
311
312static IBindStatusCallback *
314{
316
318 if (This == NULL)
319 return NULL;
320
321 This->lpIBindStatusCallbackVtbl = &vtblIBindStatusCallback;
322 This->ref = 1;
323
325}
326
327
328// ToDo: Show status, get file name from webserver, better error reporting
329
330static int
332 OUT LPWSTR szBuffer,
333 IN PDWORD pdwBufferSize)
334{
335 URL_COMPONENTS urlc;
336
337 /* Hide the password */
338 urlc = *purl;
339 urlc.lpszPassword = NULL;
340 urlc.dwPasswordLength = 0;
341
342 if (!InternetCreateUrl(&urlc, ICU_ESCAPE, szBuffer, pdwBufferSize))
343 return DWNL_E_LASTERROR;
344
345 return 1;
346}
347
348static int
350 IN LPCWSTR pszFile OPTIONAL)
351{
352 WCHAR szScheme[INTERNET_MAX_SCHEME_LENGTH + 1];
353 WCHAR szHostName[INTERNET_MAX_HOST_NAME_LENGTH + 1];
354 WCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH + 1];
355 WCHAR szPassWord[INTERNET_MAX_PASSWORD_LENGTH + 1];
356 WCHAR szUrlPath[INTERNET_MAX_PATH_LENGTH + 1];
357 WCHAR szExtraInfo[INTERNET_MAX_PATH_LENGTH + 1];
359 DWORD dwUrlLen;
360 LPTSTR pszFilePart;
361 URL_COMPONENTS urlc;
363 int iRet;
364 SYSTEMTIME sysTime;
365
366 if (pszFile != NULL && pszFile[0] == L'\0')
367 pszFile = NULL;
368
369 urlc.dwStructSize = sizeof(urlc);
370 urlc.lpszScheme = szScheme;
371 urlc.dwSchemeLength = sizeof(szScheme) / sizeof(szScheme[0]);
372 urlc.lpszHostName = szHostName;
373 urlc.dwHostNameLength = sizeof(szHostName) / sizeof(szHostName[0]);
374 urlc.lpszUserName = szUserName;
375 urlc.dwUserNameLength = sizeof(szUserName) / sizeof(szUserName[0]);
376 urlc.lpszPassword = szPassWord;
377 urlc.dwPasswordLength = sizeof(szPassWord) / sizeof(szPassWord[0]);
378 urlc.lpszUrlPath = szUrlPath;
379 urlc.dwUrlPathLength = sizeof(szUrlPath) / sizeof(szUrlPath[0]);
380 urlc.lpszExtraInfo = szExtraInfo;
381 urlc.dwExtraInfoLength = sizeof(szExtraInfo) / sizeof(szExtraInfo[0]);
382 if (!InternetCrackUrl(pszUrl, wcslen(pszUrl), ICU_ESCAPE, &urlc))
383 return DWNL_E_LASTERROR;
384
385 if (urlc.nScheme != INTERNET_SCHEME_FTP &&
389 {
391 }
392
393 if (urlc.nScheme == INTERNET_SCHEME_FTP && urlc.dwUserNameLength == 0 && urlc.dwPasswordLength == 0)
394 {
395 wcscpy(szUserName, L"anonymous");
396 urlc.dwUserNameLength = wcslen(szUserName);
397 }
398
399 /* FIXME: Get file name from server */
400 if (urlc.dwUrlPathLength == 0 && pszFile == NULL)
402
403 pszFilePart = wcsrchr(szUrlPath, L'/');
404 if (pszFilePart != NULL)
405 pszFilePart++;
406
407 if (pszFilePart == NULL && pszFile == NULL)
409
410 if (pszFile == NULL)
411 pszFile = pszFilePart;
412
413 if (urlc.dwUserNameLength == 0)
414 urlc.lpszUserName = NULL;
415
416 if (urlc.dwPasswordLength == 0)
417 urlc.lpszPassword = NULL;
418
419 /* Generate the URL to be displayed (without a password) */
420 dwUrlLen = sizeof(szUrl) / sizeof(szUrl[0]);
421 iRet = get_display_url(&urlc, szUrl, &dwUrlLen);
422 if (iRet <= 0)
423 return iRet;
424
425 GetLocalTime(&sysTime);
426
427 ConPrintf(StdOut, L"--%d-%02d-%02d %02d:%02d:%02d-- %s\n\t=> %s\n",
428 sysTime.wYear, sysTime.wMonth, sysTime.wDay,
429 sysTime.wHour, sysTime.wMinute, sysTime.wSecond,
430 szUrl, pszFile);
431
432 /* Generate the URL to download */
433 dwUrlLen = sizeof(szUrl) / sizeof(szUrl[0]);
434 if (!InternetCreateUrl(&urlc, ICU_ESCAPE, szUrl, &dwUrlLen))
435 return DWNL_E_LASTERROR;
436
438 if (pbsc == NULL)
439 return DWNL_E_LASTERROR;
440
441 if(!SUCCEEDED(URLDownloadToFile(NULL, szUrl, pszFile, 0, pbsc)))
442 {
443 IBindStatusCallback_Release(pbsc);
444 return DWNL_E_LASTERROR; /* FIXME */
445 }
446
447 IBindStatusCallback_Release(pbsc);
448 return 1;
449}
450
451static int
452print_err(int iErr)
453{
454 write_status(L"");
455
456 if (iErr == DWNL_E_LASTERROR)
457 {
459 {
460 /* File not found */
462 }
463 else
464 {
465 /* Display last error code */
467 }
468 }
469 else
470 {
471 switch (iErr)
472 {
475 break;
476
479 break;
480 }
481 }
482
483 return 1;
484}
485
486int wmain(int argc, WCHAR **argv)
487{
488 int iErr, iRet = 0;
489
490 /* Initialize the Console Standard Streams */
492
493 if(argc != 2 && argc != 3)
494 {
496 return 2;
497 }
498
499 iErr = download_file(argv[1], argc == 3 ? argv[2] : NULL);
500 if (iErr <= 0)
501 iRet = print_err(iErr);
502
503 return iRet;
504}
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
#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:153
static int download_file(IN LPCWSTR pszUrl, IN LPCWSTR pszFile OPTIONAL)
Definition: dwnl.c:349
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
Definition: dwnl.c:290
static ULONG STDMETHODCALLTYPE CBindStatusCallback_AddRef(IBindStatusCallback *iface)
Definition: dwnl.c:93
#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:280
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
Definition: dwnl.c:160
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
Definition: dwnl.c:272
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved, IBinding *pib)
Definition: dwnl.c:145
#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:264
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
Definition: dwnl.c:167
static int print_err(int iErr)
Definition: dwnl.c:452
static const struct IBindStatusCallbackVtbl vtblIBindStatusCallback
Definition: dwnl.c:297
#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:103
#define interface_to_impl(instance, iface)
Definition: dwnl.c:36
static IBindStatusCallback * CreateBindStatusCallback(void)
Definition: dwnl.c:313
static int get_display_url(IN LPURL_COMPONENTS purl, OUT LPWSTR szBuffer, IN PDWORD pdwBufferSize)
Definition: dwnl.c:331
static HRESULT STDMETHODCALLTYPE CBindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID iid, PVOID *pvObject)
Definition: dwnl.c:122
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()
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
#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:930
WORD wMonth
Definition: winbase.h:931
WORD wHour
Definition: winbase.h:934
WORD wSecond
Definition: winbase.h:936
WORD wMinute
Definition: winbase.h:935
WORD wDay
Definition: winbase.h:933
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:294
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