Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

641 lines
13 KiB

  1. /************************************************************************
  2. Copyright (c) 2000 - 2000 Microsoft Corporation
  3. Module Name :
  4. progressivedl.h
  5. Abstract :
  6. Main header file for downloader.
  7. Author :
  8. Revision History :
  9. ***********************************************************************/
  10. #pragma once
  11. #define MIN(a, b) (a>b ? b:a)
  12. #define MAX(a, b) (a>b ? a:b)
  13. #define MAX_REPLY_DATA (2 * INTERNET_MAX_URL_LENGTH)
  14. #define E_RETRY HRESULT_FROM_WIN32( ERROR_RETRY )
  15. #define BG_E_HEADER_NOT_FOUND HRESULT_FROM_WIN32( ERROR_HTTP_HEADER_NOT_FOUND )
  16. //
  17. // valid in HTTP 1.1, but not defined in the Windows-XP version of wininet.h
  18. //
  19. #define HTTP_STATUS_RANGE_NOT_SATISFIABLE 416
  20. //----------------------------------------------------------------------
  21. typedef HRESULT (*QMCALLBACK)(DWORD, DWORD, LPBYTE, DWORD);
  22. #define MAX_VIA_HEADER_LENGTH 300
  23. #define FILE_DATA_BUFFER_LEN 63000
  24. extern BYTE g_FileDataBuffer[];
  25. //--------------------------------------------
  26. struct URL_INFO
  27. {
  28. HINTERNET hInternet;
  29. HINTERNET hConnect;
  30. FILETIME UrlModificationTime;
  31. FILETIME FileCreationTime;
  32. UINT64 FileSize;
  33. DWORD dwFlags;
  34. bool bHttp11;
  35. bool bRange;
  36. bool fProxy;
  37. //
  38. // Most of these could be stack variables, but they are too big.
  39. //
  40. TCHAR HostName[INTERNET_MAX_URL_LENGTH + 1];
  41. // host-relative URL
  42. //
  43. TCHAR UrlPath[INTERNET_MAX_URL_LENGTH + 1];
  44. INTERNET_PORT Port;
  45. // a copy of <UrlPath> with range information appended as parameters
  46. //
  47. TCHAR BlockUrl[INTERNET_MAX_URL_LENGTH + 1];
  48. TCHAR UserName[UNLEN + 1];
  49. TCHAR Password[UNLEN + 1];
  50. PROXY_SETTINGS_CONTAINER * ProxySettings;
  51. CAutoString ProxyHost;
  52. TCHAR ViaHeader[ MAX_VIA_HEADER_LENGTH + 1];
  53. const CCredentialsContainer * Credentials;
  54. //--------
  55. URL_INFO(
  56. LPCTSTR a_Url,
  57. const PROXY_SETTINGS * a_ProxySettings,
  58. const CCredentialsContainer * a_Credentials,
  59. LPCTSTR HostId = NULL
  60. );
  61. ~URL_INFO();
  62. void Cleanup();
  63. QMErrInfo Connect();
  64. void Disconnect();
  65. BOOL
  66. GetProxyUsage(
  67. HINTERNET hRequest,
  68. QMErrInfo *pQMErrInfo
  69. );
  70. };
  71. //---------------------------------------------
  72. class CUploadJob;
  73. class CJobManager;
  74. class ITransferCallback
  75. {
  76. public:
  77. virtual bool
  78. DownloaderProgress(
  79. UINT64 BytesTransferred,
  80. UINT64 BytesTotal
  81. ) = 0;
  82. virtual bool
  83. PollAbort() = 0;
  84. virtual bool
  85. UploaderProgress(
  86. UINT64 BytesTransferred
  87. ) = 0;
  88. };
  89. class Downloader
  90. {
  91. public:
  92. virtual HRESULT Download( LPCTSTR szURL,
  93. LPCTSTR szDest,
  94. UINT64 Offset,
  95. ITransferCallback *CallBack,
  96. QMErrInfo *pErrInfo,
  97. HANDLE hToken,
  98. BOOL bThrottle,
  99. const PROXY_SETTINGS * pProxySettings, // optional
  100. const CCredentialsContainer * Credentials,
  101. const StringHandle HostId = StringHandle() // optional
  102. ) = 0;
  103. virtual HRESULT GetRemoteFileInformation(
  104. HANDLE hToken,
  105. LPCTSTR szURL,
  106. UINT64 * pFileSize,
  107. FILETIME *pFileTime,
  108. QMErrInfo *pErrInfo,
  109. const PROXY_SETTINGS * pProxySettings, //optional
  110. const CCredentialsContainer * Credentials, // optional
  111. const StringHandle HostId = StringHandle() // optional
  112. ) = 0;
  113. virtual ~Downloader() {}
  114. protected:
  115. };
  116. HRESULT CreateHttpDownloader( Downloader **ppDownloader, QMErrInfo *pErrInfo );
  117. void DeleteHttpDownloader( Downloader * pDownloader );
  118. extern DWORD g_dwDownloadThread;
  119. extern HWND ghPDWnd;
  120. //
  121. // conversion factor to go from time in milliseconds to time in 100-nanoseconds.
  122. //
  123. #define ONE_MSEC_IN_100_NSEC (10 * 1000)
  124. class CPeriodicTimer
  125. {
  126. public:
  127. CPeriodicTimer(
  128. LPSECURITY_ATTRIBUTES Security = NULL,
  129. BOOL ManualReset = FALSE,
  130. LPCTSTR Name = NULL
  131. )
  132. {
  133. m_handle = CreateWaitableTimer( Security, ManualReset, Name );
  134. if (!m_handle)
  135. {
  136. ThrowLastError();
  137. }
  138. }
  139. ~CPeriodicTimer()
  140. {
  141. if (m_handle)
  142. {
  143. CloseHandle( m_handle );
  144. }
  145. }
  146. BOOL Start(
  147. LONG Period,
  148. BOOL fResume = FALSE,
  149. PTIMERAPCROUTINE fn = NULL,
  150. LPVOID arg = NULL
  151. )
  152. {
  153. LARGE_INTEGER Time;
  154. //
  155. // negative values are relative; positive values are absolute.
  156. // The period is in milliseconds, but the start time is in units of 100-nanoseconds,
  157. //
  158. Time.QuadPart = -1 * Period * ONE_MSEC_IN_100_NSEC;
  159. return SetWaitableTimer( m_handle, &Time, Period, fn, arg, fResume );
  160. }
  161. BOOL Stop()
  162. {
  163. return CancelWaitableTimer( m_handle );
  164. }
  165. BOOL Wait(
  166. LONG msec = INFINITE
  167. )
  168. {
  169. if (WAIT_OBJECT_0 != WaitForSingleObject( m_handle, msec ))
  170. {
  171. return FALSE;
  172. }
  173. return TRUE;
  174. }
  175. private:
  176. HANDLE m_handle;
  177. };
  178. //
  179. // Network rate is in bytes per second.
  180. //
  181. typedef float NETWORK_RATE;
  182. class CNetworkInterface
  183. {
  184. public:
  185. //
  186. // snapshot indices
  187. //
  188. enum
  189. {
  190. BLOCK_START = 0,
  191. BLOCK_END,
  192. BLOCK_INTERVAL_END,
  193. BLOCK_COUNT
  194. };
  195. typedef float SECONDS;
  196. //
  197. // public interface
  198. //
  199. CNetworkInterface();
  200. void Reset();
  201. void SetInterfaceSpeed();
  202. HRESULT
  203. TakeSnapshot(
  204. int SnapshotIndex
  205. );
  206. HRESULT
  207. SetInterfaceIndex(
  208. const TCHAR host[]
  209. );
  210. BOOL
  211. SetTimerInterval(
  212. SECONDS interval
  213. );
  214. NETWORK_RATE GetInterfaceSpeed()
  215. {
  216. return m_ServerSpeed;
  217. }
  218. float GetPercentFree()
  219. {
  220. return m_PercentFree;
  221. }
  222. void ResetInterface()
  223. {
  224. m_InterfaceIndex = -1;
  225. }
  226. void Wait() { m_Timer.Wait(); }
  227. void StopTimer() { m_Timer.Stop(); }
  228. void CalculateIntervalAndBlockSize( UINT64 MaxBlockSize );
  229. DWORD m_BlockSize;
  230. SECONDS m_BlockInterval;
  231. private:
  232. static const NETWORK_RATE DEFAULT_SPEED;
  233. struct NET_SNAPSHOT
  234. {
  235. LARGE_INTEGER TimeStamp;
  236. UINT BytesIn;
  237. UINT BytesOut;
  238. };
  239. //
  240. // index of the interface that Wininet would use to talk to the server.
  241. //
  242. DWORD m_InterfaceIndex;
  243. //
  244. // the "start" and "end" pictures of network activity.
  245. //
  246. NET_SNAPSHOT m_Snapshots[BLOCK_COUNT];
  247. //
  248. // the apparent speed of the connection to our server
  249. //
  250. NETWORK_RATE m_ServerSpeed;
  251. //
  252. // The local interface's apparent speed
  253. //
  254. NETWORK_RATE m_NetcardSpeed;
  255. //
  256. //
  257. //
  258. float m_PercentFree;
  259. //
  260. // Error value from previous snapshots in the current series {BLOCK_START, BLOCK_END, INTERVAL_END}.
  261. //
  262. HRESULT m_SnapshotError;
  263. //
  264. // true if all three snapshots in the current series are valid.
  265. // If so, then it is safe to calculate network speed and server speed.
  266. //
  267. bool m_SnapshotsValid;
  268. MIB_IFROW m_TempRow;
  269. //
  270. // The download thread sends only one packet per timer notification.
  271. // This is the timer.
  272. //
  273. CPeriodicTimer m_Timer;
  274. enum DOWNLOAD_STATE
  275. {
  276. DOWNLOADED_BLOCK = 0x55,
  277. SKIPPED_ONE_BLOCK,
  278. SKIPPED_TWO_BLOCKS
  279. };
  280. enum DOWNLOAD_STATE m_state;
  281. static HRESULT
  282. FindInterfaceIndex(
  283. const TCHAR host[],
  284. DWORD * pIndex
  285. );
  286. float GetTimeDifference( int start, int finish );
  287. //throttle related
  288. DWORD
  289. BlockSizeFromInterval(
  290. SECONDS interval
  291. );
  292. SECONDS
  293. IntervalFromBlockSize(
  294. DWORD BlockSize
  295. );
  296. };
  297. /////////////////////////////////////////////////////////////////////////////
  298. // CProgressiveDL
  299. //
  300. class CProgressiveDL : public Downloader
  301. {
  302. public:
  303. CProgressiveDL( QMErrInfo *pErrInfo );
  304. ~CProgressiveDL();
  305. // pure virtual method from class Downloader
  306. virtual HRESULT
  307. Download( LPCTSTR szURL,
  308. LPCTSTR szDest,
  309. UINT64 Offset,
  310. ITransferCallback * CallBack,
  311. QMErrInfo *pErrInfo,
  312. HANDLE hToken,
  313. BOOL bThrottle,
  314. const PROXY_SETTINGS *pProxySettings,
  315. const CCredentialsContainer * Credentials,
  316. const StringHandle HostId = StringHandle()
  317. );
  318. virtual HRESULT
  319. GetRemoteFileInformation(
  320. HANDLE hToken,
  321. LPCTSTR szURL,
  322. UINT64 * pFileSize,
  323. FILETIME *pFileTime,
  324. QMErrInfo *pErrInfo,
  325. const PROXY_SETTINGS * pProxySettings,
  326. const CCredentialsContainer * Credentials,
  327. const StringHandle HostId = StringHandle()
  328. );
  329. // other methods
  330. private:
  331. //download related
  332. BOOL
  333. OpenLocalDownloadFile( LPCTSTR Path,
  334. UINT64 Offset,
  335. UINT64 Size,
  336. FILETIME UrlModificationTime
  337. );
  338. BOOL CloseLocalFile();
  339. BOOL WriteBlockToCache(LPBYTE lpBuffer, DWORD dwRead);
  340. BOOL SetFileTimes();
  341. HRESULT
  342. DownloadFile(
  343. HANDLE hToken,
  344. const PROXY_SETTINGS * ProxySettings,
  345. const CCredentialsContainer * Credentials,
  346. LPCTSTR Url,
  347. LPCWSTR Path,
  348. UINT64 Offset,
  349. StringHandle HostId
  350. );
  351. HRESULT GetNextBlock( );
  352. BOOL DownloadBlock( void * Buffer, DWORD * pdwRead);
  353. HRESULT OpenConnection();
  354. void CloseHandles();
  355. BOOL IsAbortRequested()
  356. {
  357. return m_Callbacks->PollAbort();
  358. }
  359. BOOL IsFileComplete()
  360. {
  361. if (m_CurrentOffset == m_wupdinfo->FileSize)
  362. {
  363. return TRUE;
  364. }
  365. return FALSE;
  366. }
  367. void ClearError();
  368. void
  369. SetError(
  370. ERROR_SOURCE Source,
  371. ERROR_STYLE Style,
  372. UINT64 Code,
  373. char * comment = 0
  374. );
  375. BOOL IsErrorSet()
  376. {
  377. // If the file was aborted, the error wont
  378. // be set.
  379. if (QM_FILE_ABORTED == m_pQMInfo->result)
  380. {
  381. return TRUE;
  382. }
  383. if (QM_SERVER_FILE_CHANGED == m_pQMInfo->result )
  384. {
  385. return TRUE;
  386. }
  387. if (m_pQMInfo->Style != 0)
  388. {
  389. return TRUE;
  390. }
  391. return FALSE;
  392. }
  393. BOOL
  394. GetRemoteResourceInformation(
  395. URL_INFO * Info,
  396. QMErrInfo * pQMErrInfo
  397. );
  398. //
  399. // These are static so they they don't mess with member data accidentally
  400. //
  401. static bool
  402. DoesErrorIndicateNoISAPI(
  403. DWORD dwHttpError
  404. );
  405. HRESULT CreateBlockUrl( LPTSTR lpszNewUrl, DWORD Length);
  406. HRESULT StartEncodedRangeRequest( DWORD Length );
  407. HRESULT StartRangeRequest( DWORD Length );
  408. //--------------------------------------------------------------------
  409. HANDLE m_hFile;
  410. //download related
  411. URL_INFO * m_wupdinfo;
  412. UINT64 m_CurrentOffset;
  413. HINTERNET m_hOpenRequest;
  414. QMErrInfo *m_pQMInfo;
  415. ITransferCallback * m_Callbacks;
  416. BOOL m_bThrottle;
  417. HRESULT DownloadForegroundFile();
  418. public:
  419. //
  420. // Tracks network statistics.
  421. //
  422. CNetworkInterface m_Network;
  423. };
  424. extern CACHED_AUTOPROXY * g_ProxyCache;
  425. HRESULT
  426. SendRequest(
  427. HINTERNET hRequest,
  428. URL_INFO * Info
  429. );
  430. HRESULT
  431. SetRequestCredentials(
  432. HINTERNET hRequest,
  433. const CCredentialsContainer & Container
  434. );
  435. HRESULT
  436. SetRequestProxy(
  437. HINTERNET hRequest,
  438. PROXY_SETTINGS_CONTAINER * ProxySettings
  439. );
  440. HRESULT
  441. OpenHttpRequest(
  442. LPCTSTR Verb,
  443. LPCTSTR Protocol,
  444. URL_INFO & Info,
  445. HINTERNET * phRequest
  446. );
  447. URL_INFO *
  448. ConnectToUrl(
  449. LPCTSTR Url,
  450. const PROXY_SETTINGS * ProxySettings,
  451. const CCredentialsContainer * Credentials,
  452. LPCTSTR HostId,
  453. QMErrInfo * pErrInfo
  454. );
  455. HRESULT
  456. GetRequestHeader(
  457. HINTERNET hRequest,
  458. DWORD HeaderIndex,
  459. LPCWSTR HeaderName,
  460. CAutoString & Destination,
  461. size_t MaxChars
  462. );
  463. HRESULT
  464. GetResponseVersion(
  465. HINTERNET hRequest,
  466. unsigned * MajorVersion,
  467. unsigned * MinorVersion
  468. );
  469. HRESULT
  470. AddRangeHeader(
  471. HINTERNET hRequest,
  472. UINT64 Start,
  473. UINT64 End
  474. );
  475. HRESULT
  476. AddIf_Unmodified_SinceHeader(
  477. HINTERNET hRequest,
  478. const FILETIME &Time
  479. );