00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 #include "camtypes.h"
00099 #include <fstream.h>
00100 #include <io.h>
00101 #include <stdlib.h>
00102 #include <direct.h>
00103 #include <stdio.h>
00104 #include <errno.h>
00105 #include <string.h>
00106 #include <process.h>
00107 #include "sglcart.h"
00108 #include "pathnmex.h"
00109 #include "camnet.h"
00110 #include "sgliboil.h"
00111
00112
00113 #include "registry.h"
00114
00115
00116
00117
00118
00119
00120 using namespace InetUtils;
00121
00122 CC_IMPLEMENT_DYNAMIC(AsynchDownload, CCObject);
00123 CC_IMPLEMENT_MEMDUMP(DownloadQueue, CCObject);
00124 CC_IMPLEMENT_MEMDUMP(DownloadCache, CCObject);
00125 CC_IMPLEMENT_MEMDUMP(InternetManager, CCObject);
00126
00127 #define new CAM_DEBUG_NEW
00128
00129 #define MAX_ATTEMPTS 5 // maximum no. of attempts made to download a file
00130 #define ICON_ANIMATION 101 // timer event for icon animation
00131 #define ICON_UPDATE_INTERVAL 300
00132
00133
00134
00135 CTypedPtrMap<CMapPtrToPtr, HWND, AsynchDownload::AsynchBindStatusCallback*> AsynchDownload::AsynchBindStatusCallback::m_CallbackTable;
00136 HWND AsynchDownload::AsynchBindStatusCallback::m_hNormalPriorityProgressDlg = NULL;
00137 UINT32 AsynchDownload::AsynchBindStatusCallback::m_nNormalPriorityIconID = _R(IDI_DOWNLOADING);
00138 INT32 AsynchDownload::m_nNormalPriorityInstanceCount = 0;
00139 INT32 AsynchDownload::m_nHighPriorityInstanceCount = 0;
00140 HICON AsynchDownload::AsynchBindStatusCallback::m_hiconProgress = 0;
00141
00142
00143 typedef BOOL (WINAPI *P_GDFSE)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
00144
00145
00147
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 AsynchDownload::AsynchDownload(DOWNLOAD_HANDLE hDownload, LPDOWNLOADINFO pDownloadInfo)
00167 {
00168 m_Handle = hDownload;
00169 m_bSuccess = FALSE;
00170 m_ulFileSize = 0;
00171 m_ulDownloaded = 0;
00172 m_nPercentageDownloaded = 0;
00173 m_bAbort = FALSE;
00174 m_pMoniker = NULL;
00175 m_pBindContext = NULL;
00176 m_pCallback = NULL;
00177 m_strTargetURL = pDownloadInfo->strURL;
00178 m_strLocalFilePath = pDownloadInfo->strLocalFile;
00179 m_nFileType = (FileType) pDownloadInfo->nFileType;
00180 m_nAttempts = 0;
00181 m_Priority = (Priority) pDownloadInfo->nPriority;
00182 m_bHasProgressDlg = pDownloadInfo->bHasProgressDlg;
00183 if (m_bHasProgressDlg = pDownloadInfo->bHasProgressDlg)
00184 m_strDescription = pDownloadInfo->strDescription;
00185 if (m_Priority == PRIORITY_NORMAL)
00186 m_nNormalPriorityInstanceCount++;
00187 else if (m_Priority == PRIORITY_HIGH)
00188 m_nHighPriorityInstanceCount++;
00189
00190 m_hwndNotifyWindow = pDownloadInfo->hwndNotifyWindow;
00191 m_lNotifyToken = pDownloadInfo->lNotifyToken;
00192
00193 AfxOleLockApp();
00194 }
00195
00196 AsynchDownload::~AsynchDownload()
00197 {
00198
00199 Cleanup();
00200 if (m_Priority == PRIORITY_NORMAL)
00201 m_nNormalPriorityInstanceCount--;
00202 else if (m_Priority == PRIORITY_HIGH)
00203 m_nHighPriorityInstanceCount--;
00204 AfxOleUnlockApp();
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 HRESULT AsynchDownload::DoBind()
00228 {
00229 if (m_strTargetURL.IsEmpty() || m_strLocalFilePath.IsEmpty())
00230 {
00231 ERROR3("Invalid (empty) URL or file path");
00232 return E_FAIL;
00233 }
00234 #ifdef _DEBUG
00235 String_256 strErrorMsg(m_strTargetURL);
00236 #endif
00237 WCHAR wchURL[INTERNET_MAX_PATH_LENGTH];
00238 MultiByteToWideChar(CP_ACP, 0, (TCHAR*) m_strTargetURL, -1, wchURL, INTERNET_MAX_PATH_LENGTH);
00239 if (IsValidURL(NULL, wchURL, 0) == S_FALSE)
00240 {
00241 #ifdef _DEBUG
00242 strErrorMsg += _T(" is not a valid URL");
00243 ERROR3(strErrorMsg);
00244 #endif
00245 return E_FAIL;
00246 }
00247 IStream* pStream = NULL;
00248 m_pCallback = new AsynchBindStatusCallback(this);
00249 if (!m_pCallback)
00250 {
00251 ERROR3("Memory allocation error");
00252 return E_OUTOFMEMORY;
00253 }
00254 HRESULT hr = CreateURLMoniker(NULL, wchURL, &m_pMoniker);
00255 if (FAILED(hr))
00256 {
00257 ERROR3("Could not create URL Moniker");
00258 Cleanup();
00259 return hr;
00260 }
00261 hr = CreateBindCtx(0, &m_pBindContext);
00262 if (FAILED(hr))
00263 {
00264 ERROR3("Could not create bind context");
00265 Cleanup();
00266 return hr;
00267 }
00268 hr = RegisterBindStatusCallback(m_pBindContext, m_pCallback, 0, 0L);
00269 if (FAILED(hr))
00270 {
00271 ERROR3("Failed to register callback object");
00272 Cleanup();
00273 return hr;
00274 }
00275 hr = m_pMoniker->BindToStorage(m_pBindContext, 0, IID_IStream, (void**)&pStream);
00276 m_nAttempts++;
00277 return hr;
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 void AsynchDownload::Cleanup()
00294 {
00295 if (m_pCallback)
00296 {
00297 m_pCallback->Release();
00298 m_pCallback = NULL;
00299 }
00300 if (m_pMoniker)
00301 {
00302 m_pMoniker->Release();
00303 m_pMoniker = NULL;
00304 }
00305 if (m_pBindContext)
00306 {
00307 m_pBindContext->Release();
00308 m_pBindContext = NULL;
00309 }
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 HRESULT AsynchDownload::Retry()
00324 {
00325 if (m_nAttempts <= MAX_ATTEMPTS)
00326 {
00327 TRACEUSER( "adrian", _T("\n\nRetrying the %d time to download %s\n\n"), m_nAttempts, (TCHAR*) m_strTargetURL);
00328 Cleanup();
00329 DoBind();
00330 }
00331 else
00332 {
00333 TRACEUSER( "adrian", _T("\n\nGiving up on %s\n\n"), (TCHAR*) m_strTargetURL);
00334 InternetManager::OnDownloadComplete(this);
00335 }
00336 return S_OK;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 HRESULT AsynchDownload::AbortDownload()
00357 {
00358 if (m_bAbort)
00359 return S_FALSE;
00360 else
00361 m_bAbort = TRUE;
00362 if (m_pCallback)
00363 {
00364 if (m_pCallback->m_pBinding)
00365 return m_pCallback->m_pBinding->Abort();
00366 else
00367 return E_FAIL;
00368 }
00369 return E_FAIL;
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 void AsynchDownload::Release()
00388 {
00389 if (m_pCallback && m_pCallback->m_pBinding)
00390 m_pCallback->m_pBinding->Abort();
00391 else
00392 delete this;
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 AsynchDownload::AsynchBindStatusCallback::AsynchBindStatusCallback(AsynchDownload* pDownload)
00410 {
00411 m_dwRef = 1;
00412 m_pDownload = pDownload;
00413 m_pBinding = NULL;
00414 m_hProgressDlg = NULL;
00415 m_nIconID = _R(IDI_DOWNLOADING);
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 AsynchDownload::AsynchBindStatusCallback::~AsynchBindStatusCallback()
00431 {
00432 if (m_pBinding)
00433 {
00434
00435 ERROR3("AsynchDownload deleted while still in progress");
00436 }
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 HRESULT _stdcall AsynchDownload::AsynchBindStatusCallback::QueryInterface(REFIID riid,void ** ppv)
00451 {
00452 *ppv = NULL;
00453
00454 if (riid==IID_IUnknown || riid==IID_IBindStatusCallback)
00455 {
00456 *ppv = this;
00457 AddRef();
00458 return S_OK;
00459 }
00460 else if (riid == IID_IAuthenticate)
00461 {
00462 *ppv = (IAuthenticate *)this;
00463 AddRef();
00464 return S_OK;
00465 }
00466
00467 return E_NOINTERFACE;
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 HRESULT _stdcall AsynchDownload::AsynchBindStatusCallback::OnStartBinding(DWORD dwReserved, IBinding* pbinding)
00482 {
00483 m_pDownload->m_ulFileSize = 0;
00484 m_pDownload->m_ulDownloaded = 0;
00485
00486 m_pBinding = pbinding;
00487 if (m_pBinding != NULL)
00488 m_pBinding->AddRef();
00489
00490 if (m_pDownload->m_bHasProgressDlg)
00491 {
00492 HWND hProgressDlg;
00493 BOOL bNeedsPositioning = (m_pDownload->m_Priority != PRIORITY_NORMAL) ||
00494 (m_pDownload->m_Priority == PRIORITY_NORMAL && !m_hNormalPriorityProgressDlg);
00495 if (!AttachProgressDlg())
00496 {
00497 ERROR3("Could not create progress dialog");
00498 goto END;
00499 }
00500 if (m_pDownload->m_Priority == PRIORITY_NORMAL)
00501 hProgressDlg = m_hNormalPriorityProgressDlg;
00502 else
00503 hProgressDlg = m_hProgressDlg;
00504 if (hProgressDlg)
00505 {
00506 HWND hProgressBar = GetDlgItem(hProgressDlg, _R(IDC_PROGRESSBAR));
00507 HWND hPercentage = GetDlgItem(hProgressDlg, _R(IDC_PERCENTAGE));
00508 ERROR3IF(!(hProgressBar && hPercentage), "Cannot find control");
00509
00510 ::SendMessage(hProgressBar, PBM_SETPOS, (WPARAM) 0, 0);
00511
00512 String_256 strPercentage = _T("0%");
00513
00514 String_256 strURL = m_pDownload->m_strTargetURL;
00515 strtok(strURL, _T(":/"));
00516 String_256 strCaption;
00517 strCaption.MakeMsg(_R(IDS_CONTACTING_HOST), strtok(NULL, _T(":/")));
00518 ::SetWindowText(hProgressDlg, (TCHAR*) strCaption);
00519 ::SetWindowText(hPercentage, (TCHAR*) strPercentage);
00520
00521 if (bNeedsPositioning)
00522 {
00523 CRect rcDialog;
00524 ::GetWindowRect(hProgressDlg, &rcDialog);
00525
00526 ::SetWindowPos(hProgressDlg, HWND_TOPMOST, ::GetSystemMetrics(SM_CXSCREEN) - rcDialog.Width(), 0,
00527 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
00528 }
00529 else
00530 ::SetWindowPos(hProgressDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
00531
00532 ::UpdateWindow(hProgressBar);
00533 ::UpdateWindow(hPercentage);
00534 ::UpdateWindow(hProgressDlg);
00535 }
00536 }
00537 END:
00538 return S_OK;
00539 }
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 HRESULT _stdcall AsynchDownload::AsynchBindStatusCallback::OnProgress(UINT32 ulProgress, UINT32 ulProgressMax, UINT32 ulStateCode,
00557 LPCWSTR pwzStateText)
00558 {
00559 if (m_pDownload->m_bAbort)
00560 {
00561 return E_ABORT;
00562 }
00563 TCHAR sz[256];
00564 if(pwzStateText != NULL)
00565 WideCharToMultiByte(CP_ACP, 0, pwzStateText, -1, sz, sizeof(sz)/sizeof(TCHAR), 0, 0);
00566
00567
00568
00569 m_pDownload->m_ulFileSize = (ulProgress > ulProgressMax) ? ulProgress : ulProgressMax;
00570 m_pDownload->m_ulDownloaded = ulProgress;
00571 INT32 nPercentage = (ulProgress && ulProgressMax) ? (100 * ulProgress/ulProgressMax) : 0;
00572
00573 if (nPercentage!=m_pDownload->m_nPercentageDownloaded)
00574 {
00575
00576 InternetManager::SetState(m_pDownload->m_Handle, AsynchDownload::STATE_PENDING);
00577 }
00578
00579 m_pDownload->m_nPercentageDownloaded = nPercentage;
00580 if (m_pDownload->m_bHasProgressDlg)
00581 {
00582 HWND hProgressDlg;
00583 if (m_pDownload->m_Priority == PRIORITY_NORMAL)
00584 hProgressDlg = m_hNormalPriorityProgressDlg;
00585 else
00586 hProgressDlg = m_hProgressDlg;
00587
00588 if (hProgressDlg && ::IsWindow(hProgressDlg))
00589 {
00590 HWND hPercentage = GetDlgItem(hProgressDlg, _R(IDC_PERCENTAGE));
00591 HWND hProgressBar = GetDlgItem(hProgressDlg, _R(IDC_PROGRESSBAR));
00592 if (!(hPercentage && hProgressBar))
00593 {
00594 ERROR3("Cannot find control");
00595 }
00596 else
00597 {
00598 String_256 strCaption, strPercentage;
00599 switch (ulStateCode)
00600 {
00601 case BINDSTATUS_FINDINGRESOURCE:
00602 case BINDSTATUS_CONNECTING:
00603 case BINDSTATUS_SENDINGREQUEST:
00604 break;
00605
00606 case BINDSTATUS_DOWNLOADINGDATA:
00607 {
00608 strCaption = String_256(_R(IDS_DOWNLOAD));
00609 if (m_pDownload->m_strDescription.IsEmpty())
00610 {
00611 strCaption+= _T("'");
00612 strCaption += strrchr(m_pDownload->m_strTargetURL, _T('/')) + 1;
00613 strCaption+= _T("'");
00614 }
00615 else
00616 {
00617 strCaption += m_pDownload->m_strDescription;
00618 }
00619 if (!ulProgressMax)
00620 {
00621 strPercentage = "N/A";
00622 m_pDownload->m_nPercentageDownloaded = 0;
00623 }
00624 else
00625 {
00626 wsprintf(strPercentage, "%d%%", nPercentage);
00627 ::SendMessage(hProgressBar, PBM_SETPOS, (WPARAM) nPercentage, 0);
00628
00629 ::UpdateWindow(hProgressBar);
00630 }
00631 }
00632 break;
00633 case BINDSTATUS_ENDDOWNLOADDATA:
00634 strPercentage = _T("100%");
00635 ::SendMessage(hProgressBar, PBM_SETPOS, (WPARAM) 100, 0);
00636
00637 ::UpdateWindow(hProgressBar);
00638 strCaption = String_256(_R(IDS_ENDDOWNLOAD));
00639 break;
00640 }
00641
00642
00643 TCHAR tchBuff[96];
00644 ::GetWindowText(hPercentage, tchBuff, sizeof(tchBuff)/sizeof(TCHAR));
00645 if (strPercentage != String_256(tchBuff))
00646 {
00647 ::SetWindowText(hPercentage, (TCHAR*) strPercentage);
00648 ::UpdateWindow(hPercentage);
00649 }
00650 ::GetWindowText(hProgressDlg, tchBuff, sizeof(tchBuff)/sizeof(TCHAR));
00651 if (strCaption.Length() && strCaption != String_256(tchBuff))
00652 {
00653 ::SetWindowText(hProgressDlg, (TCHAR*) strCaption);
00654 ::UpdateWindow(hProgressDlg);
00655 }
00656 }
00657 }
00658 }
00659
00660 if (ulStateCode == BINDSTATUS_CACHEFILENAMEAVAILABLE)
00661 m_pDownload->m_strCacheFileName = sz;
00662
00663 return (NOERROR);
00664 }
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 HRESULT _stdcall AsynchDownload::AsynchBindStatusCallback::OnStopBinding(HRESULT hrState, LPCWSTR szError)
00680 {
00681 #ifdef _DEBUG
00682 if (hrState)
00683 {
00684 TCHAR szErrorMsg[256];
00685 if (hrState == 0x800C0006)
00686 wsprintf(szErrorMsg, "%s %s\n", (TCHAR*) (String_256) m_pDownload->m_strTargetURL, _T("not found on the server"));
00687 else
00688 wsprintf(szErrorMsg, "%s %s\n", _T("Got network error (possibly host not found) downloading"), (TCHAR*) (String_256) m_pDownload->m_strTargetURL);
00689 if (hrState != 0x80004004)
00690 TRACE(szErrorMsg);
00691
00692
00693 String_256 strAppDataPath;
00694 GetAppDataPath(&strAppDataPath);
00695 PathName logPath(strAppDataPath);
00696 String_256 strLogName("errlog.txt");
00697 logPath.SetFileNameAndType(strLogName);
00698 static BOOL bShouldOverwrite = TRUE;
00699 INT32 iFlags = bShouldOverwrite ? ios::out | ios::trunc : ios::out | ios::app;
00700 bShouldOverwrite = FALSE;
00701 ofstream logFile((TCHAR*) (String_256) logPath.GetPath(), iFlags);
00702 if (!logFile.bad())
00703 logFile << szErrorMsg;
00704 logFile.close();
00705 }
00706 #endif
00707
00708
00709 if (m_pBinding)
00710 {
00711 m_pBinding->Release();
00712 m_pBinding = NULL;
00713 }
00714 if (m_pDownload->m_bHasProgressDlg)
00715 DetachProgressDlg();
00716
00717 if (!hrState && !m_pDownload->m_bAbort)
00718 {
00719
00720 PathNameEx path(m_pDownload->m_strLocalFilePath);
00721 BOOL bIsCacheFile = DownloadCache::IsCachePath(m_pDownload->m_strLocalFilePath);
00722 if (!path.CreateLocation())
00723 {
00724 InformError(_R(IDS_DIRCREATEFAIL), _R(IDS_OK));
00725 m_pDownload->m_bSuccess = FALSE;
00726 goto COMPLETE;
00727 }
00728 ifstream stmCache((TCHAR*) m_pDownload->m_strCacheFileName, ios::in | ios::nocreate | ios::binary);
00729
00730 DownloadCache::RemoveFile(m_pDownload->m_strLocalFilePath);
00731 if (bIsCacheFile)
00732 DownloadCache::m_CacheMonitor.IgnoreEvents(1);
00733 ofstream stmFile((TCHAR*) m_pDownload->m_strLocalFilePath, ios::out | ios::binary | ios::trunc);
00734 if (stmCache.bad() || stmFile.bad())
00735 {
00736 String_256 strTemp;
00737 PathName path(m_pDownload->m_strLocalFilePath);
00738 strTemp.MakeMsg(_R(IDS_FILEIOERROR), (TCHAR*) String_256(path.GetFileName()));
00739 Error::SetError(0, strTemp, 0);
00740 InformError();
00741 stmFile.close();
00742 stmCache.close();
00743 goto COMPLETE;
00744 }
00745 stmFile << stmCache.rdbuf();
00746 if (stmFile.bad() || stmCache.bad())
00747 {
00748 String_256 strTemp;
00749 PathName path(m_pDownload->m_strLocalFilePath);
00750 strTemp.MakeMsg(_R(IDS_FILEIOERROR), (TCHAR*) String_256(path.GetFileName()));
00751 Error::SetError(0,strTemp, 0);
00752 InformError();
00753 }
00754 else
00755 m_pDownload->m_bSuccess = TRUE;
00756 stmFile.close();
00757 stmCache.close();
00758 }
00759 else if (hrState == 0x800C0007)
00760 {
00761 return m_pDownload->Retry();
00762 }
00763
00764 COMPLETE:
00765 InternetManager::OnDownloadComplete(m_pDownload);
00766 return S_OK;
00767 }
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780 HRESULT _stdcall AsynchDownload::AsynchBindStatusCallback::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindInfo)
00781 {
00782 *pgrfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_GETNEWESTVERSION;
00783 pbindInfo->cbSize = sizeof(BINDINFO);
00784 pbindInfo->szExtraInfo = NULL;
00785 memset(&pbindInfo->stgmedData, 0, sizeof(STGMEDIUM));
00786 pbindInfo->grfBindInfoF = 0;
00787 pbindInfo->dwBindVerb = BINDVERB_GET;
00788 pbindInfo->szCustomVerb = NULL;
00789 return S_OK;
00790 }
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806 HRESULT _stdcall AsynchDownload::AsynchBindStatusCallback::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pfmtetc,
00807 STGMEDIUM* pstgmed)
00808 {
00809
00810 return S_OK;
00811 }
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 STDMETHODIMP AsynchDownload::AsynchBindStatusCallback::Authenticate(HWND *phwnd, LPWSTR *pszUserName, LPWSTR *pszPassword)
00824 {
00825 *phwnd = AfxGetMainWnd()->m_hWnd;
00826 *pszUserName = 0;
00827 *pszPassword = 0;
00828
00829 return S_OK;
00830 }
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847 BOOL CALLBACK AsynchDownload::AsynchBindStatusCallback::DialogProc(HWND hDlg, UINT32 message, WPARAM wParam, LPARAM lParam)
00848 {
00849 switch (message)
00850 {
00851 case WM_TIMER:
00852 {
00853 if (wParam == ICON_ANIMATION)
00854 {
00855 UINT32* pIconID = NULL;
00856 if (hDlg == m_hNormalPriorityProgressDlg)
00857 pIconID = &m_nNormalPriorityIconID;
00858 else
00859 {
00860 AsynchBindStatusCallback* pCallback = NULL;
00861 if (!m_CallbackTable.Lookup(hDlg, pCallback))
00862 {
00863 ERROR3("Callback not found in the lookup table");
00864 }
00865 else if (pCallback)
00866 pIconID = &pCallback->m_nIconID;
00867 }
00868 if (*pIconID == _R(IDI_DOWNLOADING6))
00869 *pIconID = _R(IDI_DOWNLOADING);
00870 else
00871 (*pIconID)++;
00872
00873 HICON hiconPrev = m_hiconProgress;
00874 m_hiconProgress = (HICON)::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(*pIconID), IMAGE_ICON, 16, 16, 0);
00875 ::SendMessage(hDlg, WM_SETICON, (WPARAM) FALSE, (LPARAM) m_hiconProgress );
00876 ::DestroyIcon(hiconPrev);
00877 return TRUE;
00878 }
00879 }
00880 break;
00881 case WM_COMMAND:
00882 {
00883 switch (LOWORD(wParam))
00884 {
00885 case IDCANCEL:
00886 {
00887 CANCEL:
00888 if (m_hiconProgress)
00889 {
00890 ::DestroyIcon(m_hiconProgress);
00891 m_hiconProgress = 0;
00892 }
00893
00894
00895 if (hDlg == m_hNormalPriorityProgressDlg)
00896 {
00897 AsynchDownload* pDownload = InternetManager::GetCurrentNormalPriorityDownload();
00898 if (pDownload)
00899 pDownload->AbortDownload();
00900 return TRUE;
00901 }
00902 AsynchBindStatusCallback* pCallback = NULL;
00903 if (!m_CallbackTable.Lookup(hDlg, pCallback))
00904 {
00905 ERROR3("Callback not found in the lookup table");
00906 }
00907 else
00908 {
00909 if (pCallback && pCallback->m_pDownload)
00910 {
00911
00912
00913
00914
00915
00916
00917 HRESULT result = pCallback->m_pDownload->AbortDownload();
00918 ERROR3IF(result == E_FAIL, "Could not abort download");
00919 }
00920 }
00921 return TRUE;
00922 }
00923 break;
00924 }
00925 }
00926 break;
00927 case WM_CLOSE:
00928 goto CANCEL;
00929 }
00930 return FALSE;
00931 }
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946 BOOL AsynchDownload::AsynchBindStatusCallback::AttachProgressDlg()
00947 {
00948 static BOOL bShouldRegisterClass = TRUE;
00949 if (bShouldRegisterClass)
00950 {
00951 WNDCLASSEX wndClass;
00952 static char szClassName[] = "DownloadProgressDlg";
00953 if (!::GetClassInfoEx(NULL, MAKEINTRESOURCE(32770), &wndClass))
00954 {
00955 ERROR3("Failed to get class info");
00956 }
00957 wndClass.lpszClassName = szClassName;
00958 wndClass.hInstance = AfxGetResourceHandle();
00959 wndClass.hIcon = NULL;
00960 wndClass.hIconSm = (HICON) ::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(_R(IDI_DOWNLOADING)), IMAGE_ICON, 16, 16, 0);
00961 wndClass.cbSize = sizeof(wndClass);
00962 ERROR3IF(!wndClass.hIconSm, "Failed to load icon");
00963 if (!::RegisterClassEx(&wndClass))
00964 {
00965 ERROR3("Failed to register progress dlg class");
00966 }
00967 else
00968 bShouldRegisterClass = FALSE;
00969 }
00970 if (m_pDownload->m_Priority == PRIORITY_HIGH)
00971 {
00972 m_hProgressDlg = ::CreateDialogParam(AfxGetResourceHandle(), MAKEINTRESOURCE(_R(IDD_PROGRESS)),
00973 HWND_DESKTOP, (DLGPROC) &DialogProc, NULL);
00974 if (!m_hProgressDlg)
00975 {
00976 ERROR3("Could not create progress dialog");
00977 return FALSE;
00978 }
00979 else
00980 {
00981
00982 m_CallbackTable[m_hProgressDlg] = this;
00983 ::SetTimer(m_hProgressDlg, ICON_ANIMATION, ICON_UPDATE_INTERVAL, NULL);
00984 }
00985 }
00986 else if (!m_hNormalPriorityProgressDlg)
00987 {
00988 m_hNormalPriorityProgressDlg = ::CreateDialogParam(AfxGetResourceHandle(), MAKEINTRESOURCE(_R(IDD_PROGRESS)),
00989 HWND_DESKTOP, (DLGPROC) &DialogProc, NULL);
00990 if (!m_hNormalPriorityProgressDlg)
00991 {
00992 ERROR3("Could not create progress dialog");
00993 return FALSE;
00994 }
00995 else
00996 ::SetTimer(m_hNormalPriorityProgressDlg, ICON_ANIMATION, ICON_UPDATE_INTERVAL, NULL);
00997 }
00998 return TRUE;
00999 }
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014 void AsynchDownload::AsynchBindStatusCallback::DetachProgressDlg()
01015 {
01016 if (m_hProgressDlg && m_pDownload->m_Priority == PRIORITY_HIGH)
01017 {
01018 BOOL bDestroyed = FALSE;
01019
01020 bDestroyed = ::KillTimer(m_hProgressDlg, ICON_ANIMATION);
01021 ERROR3IF(!bDestroyed, "Warning: timer not destroyed");
01022
01023 if (::IsWindow(m_hProgressDlg))
01024 bDestroyed = ::DestroyWindow(m_hProgressDlg);
01025 ERROR3IF(!bDestroyed, "Warning: progress dialog not destroyed");
01026
01027
01028 m_CallbackTable[m_hProgressDlg] = NULL;
01029 m_hProgressDlg = NULL;
01030 }
01031 else if (m_hNormalPriorityProgressDlg && m_pDownload->m_Priority == PRIORITY_NORMAL)
01032 {
01033 if (m_pDownload->m_nNormalPriorityInstanceCount == 1)
01034 {
01035
01036 BOOL bDestroyed = ::KillTimer(m_hNormalPriorityProgressDlg, ICON_ANIMATION);
01037 ERROR3IF(!bDestroyed, "Warning: timer not destroyed");
01038 ::DestroyWindow(m_hNormalPriorityProgressDlg);
01039 m_hNormalPriorityProgressDlg = NULL;
01040 }
01041 }
01042 }
01043
01044
01045
01047
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061 DownloadQueue::~DownloadQueue()
01062 {
01063 if (!IsEmpty())
01064 Flush();
01065 }
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080 BOOL DownloadQueue::Queue(AsynchDownload* pDownload)
01081 {
01082 if (!pDownload)
01083 {
01084 ERROR3("Unexpected NULL pointer");
01085 return FALSE;
01086 }
01087 if (m_enType != LIFO && m_enType != FIFO)
01088 {
01089 ERROR3("Invalid queue type");
01090 return FALSE;
01091 }
01092 try
01093 {
01094 if (m_enType == FIFO)
01095 m_List.AddTail(pDownload);
01096 else
01097 m_List.AddHead(pDownload);
01098 }
01099 catch (CMemoryException* pxMem)
01100 {
01101 pxMem->Delete();
01102 ERROR2(FALSE, "Could not queue download - memory problems");
01103 }
01104 return TRUE;
01105 }
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119 BOOL DownloadQueue::Remove(AsynchDownload* pDownload)
01120 {
01121 if (!pDownload)
01122 {
01123 ERROR3("Unexpected NULL pointer");
01124 return FALSE;
01125 }
01126 POSITION pos = m_Lis