Leaked source code of windows server 2003
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.

1639 lines
46 KiB

  1. /*----------------------------------------------------------------------------
  2. download.cpp
  3. Download handling for Signup
  4. Copyright (C) 1995 Microsoft Corporation
  5. All rights reserved.
  6. Authors:
  7. ArulM
  8. --------------------------------------------------------------------------*/
  9. #include "pch.hpp"
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <stdarg.h>
  13. #include <shellapi.h>
  14. #include <shlobj.h>
  15. #include <intshcut.h>
  16. #include <wininet.h>
  17. #include "icwdl.h"
  18. // 12/4/96 jmazner Normandy #12193
  19. // path to icwconn1.exe registry key from HKEY_LOCAL_MACHINE
  20. #define ICWCONN1PATHKEY TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\CONNWIZ.EXE")
  21. #define PATHKEYNAME TEXT("Path")
  22. #include <winreg.h>
  23. // Cabbing up.
  24. extern HRESULT HandleCab(LPTSTR pszPath);
  25. extern void CleanupCabHandler();
  26. // all global data is static shared, read-only
  27. // (written only during DLL-load)
  28. HANDLE g_hDLLHeap; // private Win32 heap
  29. HINSTANCE g_hInst; // our DLL hInstance
  30. HWND g_hWndMain; // hwnd of icwconn1 parent window
  31. #define DllExport extern "C" __declspec(dllexport)
  32. #define MAX_RES_LEN 255 // max length of string resources
  33. #define SMALL_BUF_LEN 48 // convenient size for small text buffers
  34. LPTSTR LoadSz(UINT idString,LPTSTR lpszBuf,UINT cbBuf);
  35. //+---------------------------------------------------------------------------
  36. //
  37. // Function: MyGetTempPath()
  38. //
  39. // Synopsis: Gets the path to temporary directory
  40. // - Use GetTempFileName to get a file name
  41. // and strips off the filename portion to get the temp path
  42. //
  43. // Arguments: [uiLength - Length of buffer to contain the temp path]
  44. // [szPath - Buffer in which temp path will be returned]
  45. //
  46. // Returns: Length of temp path if successful
  47. // 0 otherwise
  48. //
  49. // History: 7/6/96 VetriV Created
  50. // 8/23/96 VetriV Delete the temp file
  51. // 12/4/96 jmazner Modified to serve as a wrapper of sorts;
  52. // if TMP or TEMP don't exist, setEnv our own
  53. // vars that point to conn1's installed path
  54. // (Normandy #12193)
  55. //
  56. //----------------------------------------------------------------------------
  57. DWORD MyGetTempPath(UINT uiLength, LPTSTR szPath)
  58. {
  59. TCHAR szEnvVarName[SMALL_BUF_LEN + 1] = TEXT("\0unitialized szEnvVarName\0");
  60. DWORD dwFileAttr = 0;
  61. lstrcpyn( szPath, TEXT("\0unitialized szPath\0"), 20 );
  62. // is the TMP variable set?
  63. LoadSz(IDS_TMPVAR,szEnvVarName,sizeof(szEnvVarName));
  64. if( GetEnvironmentVariable( szEnvVarName, szPath, uiLength ) )
  65. {
  66. // 1/7/96 jmazner Normandy #12193
  67. // verify validity of directory name
  68. dwFileAttr = GetFileAttributes(szPath);
  69. // if there was any error, this directory isn't valid.
  70. if( 0xFFFFFFFF != dwFileAttr )
  71. {
  72. if( FILE_ATTRIBUTE_DIRECTORY & dwFileAttr )
  73. {
  74. return( lstrlen(szPath) );
  75. }
  76. }
  77. }
  78. lstrcpyn( szEnvVarName, TEXT("\0unitialized again\0"), 19 );
  79. // if not, is the TEMP variable set?
  80. LoadSz(IDS_TEMPVAR,szEnvVarName,sizeof(szEnvVarName));
  81. if( GetEnvironmentVariable( szEnvVarName, szPath, uiLength ) )
  82. {
  83. // 1/7/96 jmazner Normandy #12193
  84. // verify validity of directory name
  85. dwFileAttr = GetFileAttributes(szPath);
  86. if( 0xFFFFFFFF != dwFileAttr )
  87. {
  88. if( FILE_ATTRIBUTE_DIRECTORY & dwFileAttr )
  89. {
  90. return( lstrlen(szPath) );
  91. }
  92. }
  93. }
  94. // neither one is set, so let's use the path to the installed icwconn1.exe
  95. // from the registry SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\ICWCONN1.EXE\Path
  96. HKEY hkey = NULL;
  97. #ifdef UNICODE
  98. uiLength = uiLength*sizeof(TCHAR);
  99. #endif
  100. if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE,ICWCONN1PATHKEY, 0, KEY_QUERY_VALUE, &hkey)) == ERROR_SUCCESS)
  101. RegQueryValueEx(hkey, PATHKEYNAME, NULL, NULL, (BYTE *)szPath, (DWORD *)&uiLength);
  102. if (hkey)
  103. {
  104. RegCloseKey(hkey);
  105. }
  106. //The path variable is supposed to have a semicolon at the end of it.
  107. // if it's there, remove it.
  108. if( ';' == szPath[uiLength - 2] )
  109. szPath[uiLength - 2] = '\0';
  110. MyTrace(("ICWDL: using path "));
  111. MyTrace((szPath));
  112. MyTrace(("\r\n"));
  113. // go ahead and set the TEMP variable for future reference
  114. // (only effects currently running process)
  115. if( szEnvVarName[0] )
  116. {
  117. SetEnvironmentVariable( szEnvVarName, szPath );
  118. }
  119. else
  120. {
  121. lstrcpyn( szPath, TEXT("\0unitialized again\0"), 19 );
  122. return( 0 );
  123. }
  124. return( uiLength );
  125. }
  126. extern "C" BOOL _stdcall DllEntryPoint(HINSTANCE hInstance, DWORD dwReason, LPVOID lbv)
  127. {
  128. switch (dwReason)
  129. {
  130. case DLL_PROCESS_ATTACH:
  131. // Need to use OLE/Com later
  132. if (FAILED(CoInitialize(NULL)))
  133. return(FALSE);
  134. //
  135. // ChrisK Olympus 6373 6/13/97
  136. // Disable thread attach calls in order to avoid race condition
  137. // on Win95 golden
  138. //
  139. DisableThreadLibraryCalls(hInstance);
  140. g_hInst = hInstance;
  141. g_hDLLHeap = HeapCreate(0, 0, 0);
  142. MyAssert(g_hDLLHeap);
  143. if (g_hDLLHeap == NULL)
  144. return FALSE;
  145. break;
  146. case DLL_PROCESS_DETACH:
  147. CoUninitialize();
  148. HeapDestroy(g_hDLLHeap);
  149. // Cleanup the cabbing stuff.
  150. CleanupCabHandler();
  151. break;
  152. }
  153. return TRUE;
  154. }
  155. LPTSTR MyStrDup(LPTSTR pszIn)
  156. {
  157. int len;
  158. LPTSTR pszOut;
  159. MyAssert(pszIn);
  160. len = lstrlen(pszIn);
  161. if(!(pszOut = (LPTSTR)MyAlloc(len+1)))
  162. {
  163. MyAssert(FALSE);
  164. return NULL;
  165. }
  166. lstrcpy(pszOut, pszIn);
  167. pszOut[len] = 0;
  168. return pszOut;
  169. }
  170. #ifdef UNICODE
  171. LPTSTR MyStrDup(LPSTR pszIn)
  172. {
  173. int len;
  174. LPTSTR pszOut;
  175. MyAssert(pszIn);
  176. len = lstrlenA(pszIn);
  177. if(!(pszOut = (LPTSTR)MyAlloc(len+1)))
  178. {
  179. MyAssert(FALSE);
  180. return NULL;
  181. }
  182. mbstowcs(pszOut, pszIn, len);
  183. pszOut[len] = 0;
  184. return pszOut;
  185. }
  186. #endif
  187. int MyAssertProc(LPTSTR pszFile, int nLine, LPTSTR pszExpr)
  188. {
  189. TCHAR szBuf[512];
  190. wsprintf(szBuf, TEXT("Assert failed at line %d in file %s. (%s)\r\n"), nLine, pszFile, pszExpr);
  191. MyDbgSz((szBuf));
  192. return 0;
  193. }
  194. void _cdecl MyDprintf(LPCSTR pcsz, ...)
  195. {
  196. va_list argp;
  197. char szBuf[1024];
  198. if ((NULL == pcsz) || ('\0' == pcsz[0]))
  199. return;
  200. va_start(argp, pcsz);
  201. vsprintf(szBuf, pcsz, argp);
  202. MyDbgSz((szBuf));
  203. va_end(argp);
  204. } // Dprintf()
  205. // ############################################################################
  206. // operator new
  207. //
  208. // This function allocate memory for C++ classes
  209. //
  210. // Created 3/18/96, Chris Kauffman
  211. // ############################################################################
  212. void * MyBaseClass::operator new( size_t cb )
  213. {
  214. return MyAlloc(cb);
  215. }
  216. // ############################################################################
  217. // operator delete
  218. //
  219. // This function frees memory for C++ classes
  220. //
  221. // Created 3/18/96, Chris Kauffman
  222. // ############################################################################
  223. void MyBaseClass::operator delete( void * p )
  224. {
  225. MyFree( p );
  226. }
  227. void CDownLoad::AddToFileList(CFileInfo* pfi)
  228. {
  229. CFileInfo **ppfi;
  230. // must add at tail
  231. for(ppfi=&m_pfiHead; *ppfi; ppfi = &((*ppfi)->m_pfiNext))
  232. ;
  233. *ppfi = pfi;
  234. }
  235. CDownLoad::CDownLoad(LPTSTR psz)
  236. {
  237. TCHAR szUserAgent[128];
  238. OSVERSIONINFO osVer;
  239. LPTSTR pszOS = TEXT("");
  240. memset(this, 0, sizeof(CDownLoad));
  241. if(psz)
  242. m_pszURL = MyStrDup(psz);
  243. memset(&osVer, 0, sizeof(osVer));
  244. osVer.dwOSVersionInfoSize = sizeof(osVer);
  245. GetVersionEx(&osVer);
  246. switch(osVer.dwPlatformId)
  247. {
  248. case VER_PLATFORM_WIN32_WINDOWS:
  249. pszOS = TEXT("Windows95");
  250. break;
  251. case VER_PLATFORM_WIN32_NT:
  252. pszOS = TEXT("WindowsNT");
  253. }
  254. wsprintf(szUserAgent, USERAGENT_FMT, pszOS, osVer.dwMajorVersion,
  255. osVer.dwMinorVersion, GetSystemDefaultLangID());
  256. m_hSession = InternetOpen(szUserAgent, 0, NULL, NULL, 0);
  257. TCHAR szBuf[MAX_PATH+1];
  258. GetWindowsDirectory(szBuf, MAX_PATH);
  259. szBuf[MAX_PATH] = 0;
  260. m_pszWindowsDir = MyStrDup(szBuf);
  261. m_dwWindowsDirLen = lstrlen(m_pszWindowsDir);
  262. GetSystemDirectory(szBuf, MAX_PATH);
  263. szBuf[MAX_PATH] = 0;
  264. m_pszSystemDir = MyStrDup(szBuf);
  265. m_dwSystemDirLen = lstrlen(m_pszSystemDir);
  266. MyGetTempPath(MAX_PATH, szBuf);
  267. szBuf[MAX_PATH] = 0;
  268. m_pszTempDir = MyStrDup(szBuf);
  269. m_dwTempDirLen = lstrlen(m_pszTempDir);
  270. if(m_pszTempDir[m_dwTempDirLen-1]=='\\')
  271. {
  272. m_pszTempDir[m_dwTempDirLen-1]=0;
  273. m_dwTempDirLen--;
  274. }
  275. // form the ICW98 dir. It is basically the CWD
  276. m_pszICW98Dir = MyAlloc(MAX_PATH +1);
  277. GetCurrentDirectory(MAX_PATH, m_pszICW98Dir);
  278. m_dwICW98DirLen = lstrlen(m_pszICW98Dir);
  279. LPTSTR pszCmdLine = GetCommandLine();
  280. LPTSTR pszTemp = NULL, pszTemp2 = NULL;
  281. _tcsncpy(szBuf, pszCmdLine, MAX_PATH);
  282. szBuf[MAX_PATH] = 0;
  283. pszTemp = _tcstok(szBuf, TEXT(" \t\r\n"));
  284. if (NULL != pszTemp)
  285. {
  286. pszTemp2 = _tcschr(pszTemp, TEXT('\\'));
  287. if(!pszTemp2)
  288. pszTemp2 = _tcsrchr(pszTemp, TEXT('/'));
  289. }
  290. if(pszTemp2)
  291. {
  292. *pszTemp2 = 0;
  293. m_pszSignupDir = MyStrDup(pszTemp);
  294. }
  295. else
  296. {
  297. MyAssert(FALSE);
  298. GetCurrentDirectory(MAX_PATH, szBuf);
  299. szBuf[MAX_PATH] = 0;
  300. m_pszSignupDir = MyStrDup(szBuf);
  301. }
  302. m_dwSignupDirLen = lstrlen(m_pszSignupDir);
  303. }
  304. CDownLoad::~CDownLoad(void)
  305. {
  306. MyDprintf("ICWDL: CDownLoad::~CDownLoad called\n", this);
  307. CFileInfo *pfi, *pfiNext;
  308. for(pfi=m_pfiHead; pfi; pfi=pfiNext)
  309. {
  310. pfiNext = pfi->m_pfiNext;
  311. delete pfi;
  312. }
  313. if(m_pszWindowsDir)
  314. MyFree(m_pszWindowsDir);
  315. if(m_pszSystemDir)
  316. MyFree(m_pszSystemDir);
  317. if(m_pszTempDir)
  318. MyFree(m_pszTempDir);
  319. if(m_pszICW98Dir)
  320. MyFree(m_pszICW98Dir);
  321. if(m_pszSignupDir)
  322. MyFree(m_pszSignupDir);
  323. if(m_pszURL)
  324. MyFree(m_pszURL);
  325. if(m_pszBoundary)
  326. MyFree(m_pszBoundary);
  327. if(m_hSession)
  328. InternetSessionCloseHandle(m_hSession);
  329. MyAssert(!m_hRequest);
  330. //
  331. // 5/23/97 jmazner Olympus #4652
  332. // Make sure that any waiting threads are freed up.
  333. //
  334. if( m_hCancelSemaphore )
  335. {
  336. ReleaseSemaphore( m_hCancelSemaphore, 1, NULL );
  337. CloseHandle( m_hCancelSemaphore );
  338. m_hCancelSemaphore = NULL;
  339. }
  340. }
  341. // perform a file name substitution
  342. LPTSTR CDownLoad::FileToPath(LPTSTR pszFile)
  343. {
  344. TCHAR szBuf[MAX_PATH+1];
  345. for(long j=0; *pszFile; pszFile++)
  346. {
  347. if(j>=MAX_PATH)
  348. return NULL;
  349. if(*pszFile=='%')
  350. {
  351. pszFile++;
  352. LPTSTR pszTemp = _tcschr(pszFile, '%');
  353. if(!pszTemp)
  354. return NULL;
  355. *pszTemp = 0;
  356. if(lstrcmpi(pszFile, SIGNUP)==0)
  357. {
  358. lstrcpy(szBuf+j, m_pszSignupDir);
  359. j+= m_dwSignupDirLen;
  360. }
  361. else if(lstrcmpi(pszFile, WINDOWS)==0)
  362. {
  363. lstrcpy(szBuf+j, m_pszWindowsDir);
  364. j+= m_dwWindowsDirLen;
  365. }
  366. else if(lstrcmpi(pszFile, SYSTEM)==0)
  367. {
  368. lstrcpy(szBuf+j, m_pszSystemDir);
  369. j+= m_dwSystemDirLen;
  370. }
  371. else if(lstrcmpi(pszFile, TEMP)==0)
  372. {
  373. lstrcpy(szBuf+j, m_pszTempDir);
  374. j+= m_dwTempDirLen;
  375. }
  376. else if(lstrcmpi(pszFile, ICW98DIR)==0)
  377. {
  378. lstrcpy(szBuf+j, m_pszICW98Dir);
  379. j+= m_dwICW98DirLen;
  380. }
  381. else
  382. return NULL;
  383. pszFile=pszTemp;
  384. }
  385. else
  386. szBuf[j++] = *pszFile;
  387. }
  388. szBuf[j] = 0;
  389. return MyStrDup(szBuf);
  390. }
  391. // Chops input up into CRLF-delimited chunks
  392. // Modifies input
  393. LPSTR GetNextLine(LPSTR pszIn)
  394. {
  395. LPSTR pszNext;
  396. while(*pszIn)
  397. {
  398. pszNext = strchr(pszIn, '\r');
  399. if(!pszNext)
  400. return NULL;
  401. else if(pszNext[1]=='\n')
  402. {
  403. pszNext[0] = pszNext[1] = 0;
  404. return pszNext+2;
  405. }
  406. else
  407. pszIn = pszNext+1;
  408. }
  409. return NULL;
  410. }
  411. // Modifies input. Output is *in-place*
  412. LPSTR FindHeaderParam(LPSTR pszIn, LPSTR pszLook)
  413. {
  414. LPSTR pszEnd = pszIn + lstrlenA(pszIn);
  415. BOOL fFound = FALSE;
  416. LPSTR pszToken = NULL;
  417. while(pszIn<pszEnd)
  418. {
  419. pszToken=strtok(pszIn, " \t;=");
  420. if(fFound || !pszToken)
  421. break;
  422. pszIn = pszToken+lstrlenA(pszToken)+1;
  423. if(lstrcmpiA(pszToken, pszLook)==0)
  424. fFound = TRUE;
  425. }
  426. if(fFound && pszToken)
  427. {
  428. if(pszToken[0]=='"')
  429. pszToken++;
  430. int iLen = lstrlenA(pszToken);
  431. if(pszToken[iLen-1]=='"')
  432. pszToken[iLen-1]=0;
  433. return pszToken;
  434. }
  435. return NULL;
  436. }
  437. // Modifies input!!
  438. LPSTR ParseHeaders(LPSTR pszIn, LPTSTR* ppszBoundary, LPTSTR* ppszFilename, BOOL* pfInline)
  439. {
  440. LPSTR pszNext=NULL, pszCurr=NULL, pszToken=NULL, pszToken2=NULL, pszTemp=NULL;
  441. // int iLen; ChrisK
  442. if(pfInline) *pfInline = FALSE;
  443. if(ppszFilename) *ppszFilename = NULL;
  444. if(ppszBoundary) *ppszBoundary = NULL;
  445. for(pszCurr=pszIn; pszCurr; pszCurr=pszNext)
  446. {
  447. // terminate current line with null & get ptr to next
  448. pszNext = GetNextLine(pszCurr);
  449. // if we have a blank line, done with headers--exit loop
  450. if(*pszCurr==0)
  451. {
  452. pszCurr = pszNext;
  453. break;
  454. }
  455. if(!(pszToken = strtok(pszCurr, " \t:;")))
  456. continue;
  457. pszCurr = pszToken+lstrlenA(pszToken)+1;
  458. if(lstrcmpiA(pszToken, MULTIPART_MIXED)==0)
  459. {
  460. if(ppszBoundary)
  461. {
  462. pszTemp = FindHeaderParam(pszCurr, BOUNDARY);
  463. if(pszTemp)
  464. {
  465. int iLen = lstrlenA(pszTemp);
  466. *ppszBoundary = (LPTSTR)MyAlloc(iLen+2+1);
  467. (*ppszBoundary)[0] = (*ppszBoundary)[1] = '-';
  468. #ifdef UNICODE
  469. mbstowcs(*ppszBoundary+2, pszTemp, lstrlenA(pszTemp)+1);
  470. #else
  471. lstrcpyA(*ppszBoundary+2, pszTemp);
  472. #endif
  473. }
  474. }
  475. }
  476. else if(lstrcmpiA(pszToken, CONTENT_DISPOSITION)==0)
  477. {
  478. if(!(pszToken2 = strtok(pszCurr, " \t:;")))
  479. continue;
  480. pszCurr = pszToken2+lstrlenA(pszToken2)+1;
  481. if(lstrcmpiA(pszToken2, INLINE)==0)
  482. {
  483. if(pfInline)
  484. *pfInline = TRUE;
  485. }
  486. else if(lstrcmpiA(pszToken2, ATTACHMENT)!=0)
  487. continue;
  488. if(ppszFilename)
  489. {
  490. pszTemp = FindHeaderParam(pszCurr, FILENAME);
  491. if(pszTemp)
  492. *ppszFilename = MyStrDup(pszTemp);
  493. }
  494. }
  495. }
  496. return pszCurr;
  497. }
  498. BOOL g_ForceOnlineAttempted = FALSE;
  499. HRESULT CDownLoad::Execute(void)
  500. {
  501. TCHAR szBuf[256];
  502. DWORD dwLen;
  503. HRESULT hr = ERROR_GEN_FAILURE;
  504. if(!m_hSession || !m_pszURL)
  505. return ERROR_INVALID_PARAMETER;
  506. m_hRequest = InternetOpenUrl(m_hSession, m_pszURL, NULL, 0,
  507. (INTERNET_FLAG_RELOAD|INTERNET_FLAG_DONT_CACHE), (DWORD_PTR)this);
  508. if(!m_hRequest)
  509. {
  510. if (!m_hSession)
  511. return GetLastError();
  512. else
  513. {
  514. HRESULT hRes = InternetGetLastError(m_hSession);
  515. if (hRes == INTERNET_STATE_DISCONNECTED)
  516. {
  517. DWORD dwConnectedFlags = 0;
  518. InternetGetConnectedStateEx(&dwConnectedFlags,
  519. NULL,
  520. 0,
  521. 0);
  522. if(dwConnectedFlags & INTERNET_CONNECTION_OFFLINE)
  523. {
  524. if(g_ForceOnlineAttempted)
  525. {
  526. g_ForceOnlineAttempted = FALSE;
  527. hRes = INTERNET_CONNECTION_OFFLINE;
  528. }
  529. else
  530. {
  531. //ack! the user is offline. not good. let's put them back online.
  532. INTERNET_CONNECTED_INFO ci;
  533. memset(&ci, 0, sizeof(ci));
  534. ci.dwConnectedState = INTERNET_STATE_CONNECTED;
  535. InternetSetOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci));
  536. g_ForceOnlineAttempted = TRUE;
  537. //now that we've reset the state let's recurse the call.
  538. //if we fail again, then we'll tell the user they need
  539. //to disable the Offline themseleve
  540. return Execute();
  541. }
  542. }
  543. }
  544. return hRes;
  545. }
  546. }
  547. dwLen = sizeof(szBuf);
  548. if(HttpQueryInfo(m_hRequest, HTTP_QUERY_CONTENT_LENGTH, szBuf, &dwLen, NULL))
  549. {
  550. m_dwContentLength = _ttol(szBuf);
  551. }
  552. else
  553. {
  554. m_dwContentLength = 0;
  555. }
  556. dwLen = sizeof(szBuf);
  557. if(HttpQueryInfo(m_hRequest, HTTP_QUERY_CONTENT_TYPE, szBuf, &dwLen, NULL))
  558. {
  559. #ifdef UNICODE
  560. CHAR szTmp[256];
  561. wcstombs(szTmp, szBuf, lstrlen(szBuf)+1);
  562. ParseHeaders(szTmp, &m_pszBoundary, NULL, NULL);
  563. #else
  564. ParseHeaders(szBuf, &m_pszBoundary, NULL, NULL);
  565. #endif
  566. if(m_pszBoundary)
  567. m_dwBoundaryLen = lstrlen(m_pszBoundary);
  568. else
  569. goto ExecuteExit; // Chrisk, you have to clean up before exiting
  570. hr = ProcessRequest();
  571. }
  572. ExecuteExit:
  573. if (m_hRequest)
  574. InternetRequestCloseHandle(m_hRequest);
  575. m_hRequest = NULL;
  576. return hr;
  577. }
  578. //+----------------------------------------------------------------------------
  579. //
  580. // Function: ShowProgress
  581. //
  582. // Synopsis: update running total & call progress callback
  583. //
  584. // Arguments: dwRead - additional number of bytes read
  585. //
  586. // Returns: none
  587. //
  588. // History: ArulM Created
  589. // 8/896 ChrisK Ported from \\TRANGO
  590. //
  591. //-----------------------------------------------------------------------------
  592. void CDownLoad::ShowProgress(DWORD dwRead)
  593. {
  594. int prc;
  595. m_dwReadLength += dwRead; // running total bytes read
  596. MyAssert(m_dwReadLength <= m_dwContentLength);
  597. if (m_lpfnCB)
  598. {
  599. if (m_dwContentLength)
  600. {
  601. prc = (int)((DWORD)100 * m_dwReadLength / m_dwContentLength);
  602. }
  603. else
  604. {
  605. prc = 0;
  606. }
  607. //
  608. // 5/27/97 jmazner Olympus #4579
  609. // need to pass in a valid pointer to a CDialingDlg!
  610. //
  611. (m_lpfnCB)(m_hRequest,m_lpCDialingDlg,CALLBACK_TYPE_PROGRESS,(LPVOID)&prc,sizeof(prc));
  612. }
  613. }
  614. //+----------------------------------------------------------------------------
  615. //
  616. // Function: FillBuffer
  617. //
  618. // Synopsis: takes a buffer that is partially-filled and reads until it is
  619. // full or until we've reached the end.
  620. //
  621. // Arguments: Buffer pointer, buffer size, count of valid data bytes
  622. //
  623. // Returns: total number of bytes in buf
  624. //
  625. // History: ArulM Created
  626. // 8/8/96 ChrisK Ported from \\TRANGO
  627. //
  628. //-----------------------------------------------------------------------------
  629. DWORD CDownLoad::FillBuffer(LPBYTE pbBuf, DWORD dwLen, DWORD dwRead)
  630. {
  631. DWORD dwTemp;
  632. while(dwRead < dwLen)
  633. {
  634. dwTemp = 0;
  635. if(!InternetReadFile(m_hRequest, pbBuf+dwRead, (dwLen-dwRead), &dwTemp))
  636. break;
  637. if(!dwTemp)
  638. break;
  639. ShowProgress(dwTemp);
  640. dwRead += dwTemp;
  641. }
  642. if(dwLen-dwRead)
  643. memset(pbBuf+dwRead, 0, (size_t)(dwLen-dwRead));
  644. return dwRead;
  645. }
  646. //+----------------------------------------------------------------------------
  647. //
  648. // Function: MoveAndFillBuffer
  649. //
  650. // Synopsis: move remaining contents of buffer from middle of buffer back to
  651. // the beginning & refill buffer.
  652. //
  653. // Arguements: Buffer pointer, Buffer size, count of *total* valid data bytes
  654. // Pointer to start of data to be moved (everything before is nuked)
  655. //
  656. // Returns: total number of bytes in buffer
  657. //
  658. // History: ArulM Created
  659. // 8/8/96 ChrisK Ported from \\TRANGO
  660. //
  661. //-----------------------------------------------------------------------------
  662. DWORD CDownLoad::MoveAndFillBuffer(LPBYTE pbBuf, DWORD dwLen, DWORD dwValid, LPBYTE pbNewStart)
  663. {
  664. MyAssert(pbNewStart >= pbBuf);
  665. MyAssert(pbBuf+dwValid >= pbNewStart);
  666. dwValid -= (DWORD)(pbNewStart-pbBuf);
  667. if(dwValid)
  668. memmove(pbBuf, pbNewStart, (size_t)dwValid);
  669. return FillBuffer(pbBuf, dwLen, dwValid);
  670. }
  671. //+----------------------------------------------------------------------------
  672. //
  673. // Function: HandlwDLFile
  674. //
  675. // Synopsis: Handle filename:
  676. // (1) get full path after macro substituition. (2) Free
  677. // pszFile string.
  678. // (3) save the file path & inline/attach info internally for
  679. // later handling
  680. // (4) Create file on disk & return HANDLE
  681. //
  682. // Aruguments: pszFile - filename
  683. // fInLine - value of inline/attached header from the MIME mutli-part
  684. //
  685. // Returns: phFile - handle of file created
  686. // return - ERROR_SUCCESS == success
  687. //
  688. // History: ArulM Created
  689. // 8/8/96 ChrisK Ported from \\TRANGO
  690. //
  691. //-----------------------------------------------------------------------------
  692. HRESULT CDownLoad::HandleDLFile(LPTSTR pszFile, BOOL fInline, LPHANDLE phFile)
  693. {
  694. TCHAR szdrive[_MAX_DRIVE];
  695. TCHAR szPathName[_MAX_PATH]; // This will be the dir we need to create
  696. TCHAR szdir[_MAX_DIR];
  697. TCHAR szfname[_MAX_FNAME];
  698. TCHAR szext[_MAX_EXT];
  699. MyAssert(phFile);
  700. *phFile = INVALID_HANDLE_VALUE;
  701. LPTSTR pszPath = FileToPath(pszFile);
  702. MyFree(pszFile);
  703. if(!pszPath)
  704. return ERROR_INVALID_DATA;
  705. // Split the provided path to get at the drive and path portion
  706. _tsplitpath( pszPath, szdrive, szdir, szfname, szext );
  707. wsprintf (szPathName, TEXT("%s%s"), szdrive, szdir);
  708. // Create the Directory
  709. CreateDirectory(szPathName, NULL);
  710. // create the file
  711. *phFile = CreateFile(pszPath,
  712. GENERIC_WRITE,
  713. 0,
  714. NULL,
  715. OPEN_ALWAYS,
  716. FILE_ATTRIBUTE_NORMAL,
  717. NULL);
  718. if(*phFile == INVALID_HANDLE_VALUE)
  719. return GetLastError();
  720. CFileInfo* pfi = new CFileInfo(pszPath, fInline);
  721. if(!pfi)
  722. return GetLastError();
  723. AddToFileList(pfi);
  724. return ERROR_SUCCESS;
  725. }
  726. /*******************************************************************
  727. *
  728. * NAME: LoadSz
  729. *
  730. * SYNOPSIS: Loads specified string resource into buffer
  731. *
  732. * EXIT: returns a pointer to the passed-in buffer
  733. *
  734. * NOTES: If this function fails (most likely due to low
  735. * memory), the returned buffer will have a leading NULL
  736. * so it is generally safe to use this without checking for
  737. * failure.
  738. *
  739. ********************************************************************/
  740. LPTSTR LoadSz(UINT idString,LPTSTR lpszBuf,UINT cbBuf)
  741. {
  742. // Clear the buffer and load the string
  743. if ( lpszBuf )
  744. {
  745. *lpszBuf = '\0';
  746. LoadString( g_hInst, idString, lpszBuf, cbBuf );
  747. }
  748. return lpszBuf;
  749. }
  750. HRESULT CDownLoad::ProcessRequest(void)
  751. {
  752. LPBYTE pbData = NULL, pBoundary = NULL;
  753. DWORD dwLen = 0;
  754. HFIND hFindBoundary = NULL;
  755. LPTSTR pszDLFileName = NULL;
  756. HANDLE hOutFile = INVALID_HANDLE_VALUE;
  757. HRESULT hr = E_FAIL;
  758. MyAssert(m_hRequest && m_pszBoundary);
  759. MyAssert(m_pszBoundary[0]=='\r' && m_pszBoundary[1]=='\n');
  760. MyAssert(m_pszBoundary[2]=='-' && m_pszBoundary[3]=='-');
  761. // Buf Size must be greater than larget possible block of headers
  762. // also must be greater than the OVERLAP, which must be greater
  763. // than max size of MIME part boundary (70?)
  764. MyAssert(DEFAULT_DATABUF_SIZE > OVERLAP_LEN);
  765. MyAssert(OVERLAP_LEN > 80);
  766. // init buffer & find-pattern
  767. if(! (pbData = (LPBYTE)MyAlloc(DEFAULT_DATABUF_SIZE+SLOP)))
  768. {
  769. hr = E_OUTOFMEMORY;
  770. goto error;
  771. }
  772. hFindBoundary = SetFindPattern(m_pszBoundary);
  773. // find first boundary. If not in first blob, we have too much
  774. // white-space. Discard & try again (everything before the first
  775. // boundary is discardable)
  776. for(pBoundary=NULL; !pBoundary; )
  777. {
  778. if(!(dwLen = FillBuffer(pbData, DEFAULT_DATABUF_SIZE, 0)))
  779. goto iNetError;
  780. pBoundary = (LPBYTE)Find(hFindBoundary, (LPSTR)pbData, dwLen);
  781. }
  782. for(;;)
  783. {
  784. MyAssert(pBoundary && pbData && dwLen);
  785. MyAssert(pBoundary>=pbData && (pBoundary+m_dwBoundaryLen)<=(pbData+dwLen));
  786. // move remaining data to front of buffer & refill.
  787. if(!(dwLen = MoveAndFillBuffer(pbData, DEFAULT_DATABUF_SIZE, dwLen, pBoundary+m_dwBoundaryLen)))
  788. goto iNetError;
  789. pBoundary = NULL;
  790. // look for trailing -- after boundary to indicate end of last part
  791. if(pbData[0]=='-' && pbData[1]=='-')
  792. break;
  793. // skip leading CRLF (alway one after boundary)
  794. MyAssert(pbData[0]=='\r' && pbData[1]=='\n');
  795. // reads headers and skips everything until doubleCRLF. assumes all
  796. // headers fit in the single buffer. Pass in pbData+2 to skip
  797. // leading CRLF. Return value is ptr to first byte past the dbl crlf
  798. LPTSTR pszFile = NULL;
  799. BOOL fInline = FALSE;
  800. LPBYTE pbNext = (LPBYTE)ParseHeaders((LPSTR)pbData+2, NULL, &pszFile, &fInline);
  801. if(!pszFile || !pbNext)
  802. {
  803. hr = ERROR_INVALID_DATA;
  804. goto error;
  805. }
  806. //
  807. // Make a copy of the file name - will be used
  808. // for displaying error message
  809. //
  810. pszDLFileName = (LPTSTR) MyAlloc(lstrlen(pszFile) + 1);
  811. lstrcpy(pszDLFileName, pszFile);
  812. // Handle filename: (1) get full path after macro substituition.
  813. // (2) Free pszFile string. (3) save the file path & inline/attach info
  814. // internally for later handling (4) Create file on disk &return HANDLE
  815. if(hr = HandleDLFile(pszFile, fInline, &hOutFile))
  816. goto error;
  817. // move remaining data (after headers) to front of buffer & refill.
  818. dwLen = MoveAndFillBuffer(pbData, DEFAULT_DATABUF_SIZE, dwLen, pbNext);
  819. pBoundary = NULL;
  820. MyAssert(dwLen);
  821. while(dwLen)
  822. {
  823. DWORD dwWriteLen = 0;
  824. DWORD dwTemp = 0;
  825. // look for boundary. careful of boundary cut across
  826. // blocks. Overlapping blocks by 100 bytes to cover this case.
  827. if(pBoundary = (LPBYTE)Find(hFindBoundary, (LPSTR)pbData, dwLen))
  828. dwWriteLen = (DWORD)(pBoundary - pbData);
  829. else if(dwLen > OVERLAP_LEN)
  830. dwWriteLen = dwLen-OVERLAP_LEN;
  831. else
  832. dwWriteLen = dwLen;
  833. MyAssert(dwWriteLen <= dwLen);
  834. MyAssert(hOutFile != INVALID_HANDLE_VALUE);
  835. if(dwWriteLen)
  836. {
  837. dwTemp = 0;
  838. if(!WriteFile(hOutFile, pbData, dwWriteLen, &dwTemp, NULL)
  839. || dwTemp!=dwWriteLen)
  840. {
  841. hr = GetLastError();
  842. //
  843. // If we are out of diskspace, get the drive letter
  844. // and display an out of diskspace message
  845. //
  846. goto error;
  847. }
  848. }
  849. if(pBoundary)
  850. break;
  851. // move remaining data (after last byte written) to front of buffer & refill
  852. dwLen = MoveAndFillBuffer(pbData, DEFAULT_DATABUF_SIZE, dwLen, pbData+dwWriteLen);
  853. }
  854. // *truncate* file & close
  855. MyAssert(hOutFile != INVALID_HANDLE_VALUE);
  856. SetEndOfFile(hOutFile);
  857. // close file
  858. CloseHandle(hOutFile);
  859. hOutFile = INVALID_HANDLE_VALUE;
  860. if (NULL != pszDLFileName)
  861. {
  862. MyFree(pszDLFileName);
  863. pszDLFileName = NULL;
  864. }
  865. if(!pBoundary)
  866. {
  867. MyAssert(dwLen==0); // can only get here on dwLen==0 or found boundary
  868. goto iNetError;
  869. }
  870. // at start of loop we'll discard everything upto and including the boundary
  871. // if we loop back with pBoundary==NULL, we'll GPF
  872. }
  873. return ERROR_SUCCESS;
  874. iNetError:
  875. hr = InternetGetLastError(m_hSession);
  876. if(!hr)
  877. hr = ERROR_INVALID_DATA;
  878. // goto error;
  879. // fall through
  880. error:
  881. if(pbData) MyFree(pbData);
  882. if(hFindBoundary) FreeFindPattern(hFindBoundary);
  883. if (NULL != pszDLFileName)
  884. {
  885. MyFree(pszDLFileName);
  886. pszDLFileName = NULL;
  887. }
  888. if (hOutFile != INVALID_HANDLE_VALUE)
  889. {
  890. CloseHandle(hOutFile);
  891. hOutFile = INVALID_HANDLE_VALUE;
  892. }
  893. return hr;
  894. }
  895. HRESULT HandleExe(LPTSTR pszPath, HANDLE hCancelSemaphore)
  896. {
  897. MyAssert( hCancelSemaphore );
  898. STARTUPINFO si;
  899. PROCESS_INFORMATION pi;
  900. memset(&pi, 0, sizeof(pi));
  901. memset(&si, 0, sizeof(si));
  902. if(!CreateProcess(pszPath, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
  903. return GetLastError();
  904. else
  905. {
  906. HANDLE lpHandles[2] = {hCancelSemaphore, pi.hProcess};
  907. DWORD dwRet = 0xDEAF;
  908. MyDprintf("ICWDL: HandleExe about to wait....\n");
  909. //
  910. // 5/23/97 jmazner Olympus #4652
  911. // sit here and wait until either
  912. // 1) the process we launched terminates, or
  913. // 2) the user tells us to cancel
  914. //
  915. dwRet = WaitForMultipleObjects( 2, lpHandles, FALSE, INFINITE );
  916. MyDprintf("ICWDL: ....HandleExe done waiting -- %s was signalled\n",
  917. (0==(dwRet - WAIT_OBJECT_0))?"hCancelSemaphore":"pi.hProcess");
  918. // should we try to kill the process here??
  919. CloseHandle(pi.hThread);
  920. CloseHandle(pi.hProcess);
  921. return NO_ERROR;
  922. }
  923. }
  924. HRESULT HandleReg(LPTSTR pszPath, HANDLE hCancelSemaphore)
  925. {
  926. STARTUPINFO si;
  927. PROCESS_INFORMATION pi;
  928. TCHAR szCmd[MAX_PATH + 1];
  929. MyAssert( pszPath );
  930. MyAssert( hCancelSemaphore );
  931. // 11/20/96 jmazner Normandy #5272
  932. // Wrap quotes around pszPath in a directory or file name includes a space.
  933. lstrcpy(szCmd, REGEDIT_CMD);
  934. if( '\"' != pszPath[0] )
  935. {
  936. // add 2 for two quotes
  937. MyAssert( (lstrlen(REGEDIT_CMD) + lstrlen(pszPath)) < MAX_PATH );
  938. lstrcat(szCmd, TEXT("\""));
  939. lstrcat(szCmd, pszPath);
  940. int i = lstrlen(szCmd);
  941. szCmd[i] = '\"';
  942. szCmd[i+1] = '\0';
  943. }
  944. else
  945. {
  946. MyAssert( (lstrlen(REGEDIT_CMD) + lstrlen(pszPath)) < MAX_PATH );
  947. lstrcat(szCmd, pszPath);
  948. }
  949. memset(&pi, 0, sizeof(pi));
  950. memset(&si, 0, sizeof(si));
  951. si.dwFlags = STARTF_USESHOWWINDOW;
  952. si.wShowWindow = SW_HIDE;
  953. if(!CreateProcess(NULL, szCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
  954. return GetLastError();
  955. else
  956. {
  957. // HRESULT hr = (WaitAndKillRegeditWindow(10) ? NO_ERROR : E_FAIL);
  958. HANDLE lpHandles[2] = {hCancelSemaphore, pi.hProcess};
  959. DWORD dwRet = 0xDEAF;
  960. MyDprintf("ICWDL: HandleReg about to wait....\n");
  961. //
  962. // 5/23/97 jmazner Olympus #4652
  963. // sit here and wait until either
  964. // 1) the process we launched terminates, or
  965. // 2) the user tells us to cancel
  966. //
  967. dwRet = WaitForMultipleObjects( 2, lpHandles, FALSE, INFINITE );
  968. MyDprintf("ICWDL: ....HandleReg done waiting -- %s was signalled\n",
  969. (0==(dwRet - WAIT_OBJECT_0))?"hCancelSemaphore":"pi.hProcess");
  970. // should we try to kill the process here??
  971. CloseHandle(pi.hThread);
  972. CloseHandle(pi.hProcess);
  973. return ERROR_SUCCESS;
  974. }
  975. }
  976. HRESULT HandleInf(LPTSTR pszPath, HANDLE hCancelSemaphore)
  977. {
  978. TCHAR szCmd[MAX_PATH + 1];
  979. MyAssert( pszPath );
  980. MyAssert( hCancelSemaphore );
  981. // add 2 for two quotes,
  982. // subtract 70 for approximate length of string in sprintf
  983. MyAssert( (lstrlen(pszPath) - 70 + 2) < MAX_PATH );
  984. // 11/20/96 jmazner Normandy #5272
  985. // wrap pszPath in quotes in case it includes a space
  986. if( '\"' != pszPath[0] )
  987. {
  988. wsprintf(szCmd, TEXT("rundll setupx.dll,InstallHinfSection DefaultInstall 128 \"%s"), pszPath);
  989. int i = lstrlen(szCmd);
  990. szCmd[i] = '\"';
  991. szCmd[i+1] = '\0';
  992. }
  993. else
  994. {
  995. wsprintf(szCmd, TEXT("rundll setupx.dll,InstallHinfSection DefaultInstall 128 %s"), pszPath);
  996. }
  997. STARTUPINFO si;
  998. PROCESS_INFORMATION pi;
  999. memset(&pi, 0, sizeof(pi));
  1000. memset(&si, 0, sizeof(si));
  1001. si.cb = sizeof(STARTUPINFO);
  1002. si.dwFlags = STARTF_USESHOWWINDOW;
  1003. si.wShowWindow = SW_SHOW;
  1004. if(!CreateProcess(NULL, szCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
  1005. return GetLastError();
  1006. else
  1007. {
  1008. HANDLE lpHandles[2] = {hCancelSemaphore, pi.hProcess};
  1009. DWORD dwRet = 0xDEAF;
  1010. MyDprintf("ICWDL: HandleInf about to wait....\n");
  1011. //
  1012. // 5/23/97 jmazner Olympus #4652
  1013. // sit here and wait until either
  1014. // 1) the process we launched terminates, or
  1015. // 2) the user tells us to cancel
  1016. //
  1017. dwRet = WaitForMultipleObjects( 2, lpHandles, FALSE, INFINITE );
  1018. MyDprintf("ICWDL: ....HandleInf done waiting -- %s was signalled\n",
  1019. (0==(dwRet - WAIT_OBJECT_0))?"hCancelSemaphore":"pi.hProcess");
  1020. // should we try to kill the process here??
  1021. CloseHandle(pi.hThread);
  1022. CloseHandle(pi.hProcess);
  1023. return NO_ERROR;
  1024. }
  1025. }
  1026. #define STR_BSTR 0
  1027. #define STR_OLESTR 1
  1028. #ifdef UNICODE
  1029. #define BSTRFROMANSI(x) (BSTR)(x)
  1030. #define OLESTRFROMANSI(x) (LPCOLESTR)(x)
  1031. #else
  1032. #define BSTRFROMANSI(x) (BSTR)MakeWideStrFromAnsi((LPSTR)(x), STR_BSTR)
  1033. #define OLESTRFROMANSI(x) (LPCOLESTR)MakeWideStrFromAnsi((LPSTR)(x), STR_OLESTR)
  1034. #endif
  1035. #define TO_ASCII(x) (TCHAR)((unsigned char)x + 0x30)
  1036. //=--------------------------------------------------------------------------=
  1037. // MakeWideFromAnsi
  1038. //=--------------------------------------------------------------------------=
  1039. // given a string, make a BSTR out of it.
  1040. //
  1041. // Parameters:
  1042. // LPTSTR - [in]
  1043. // BYTE - [in]
  1044. //
  1045. // Output:
  1046. // LPWSTR - needs to be cast to final desired result
  1047. //
  1048. // Notes:
  1049. //
  1050. LPWSTR MakeWideStrFromAnsi (LPSTR psz, BYTE bType)
  1051. {
  1052. int i;
  1053. LPWSTR pwsz;
  1054. if (!psz)
  1055. return(NULL);
  1056. if ((i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0)) <= 0) // compute the length of the required BSTR
  1057. return NULL;
  1058. switch (bType) { // allocate the widestr, +1 for null
  1059. case STR_BSTR:
  1060. pwsz = (LPWSTR)SysAllocStringLen(NULL, (i - 1)); // SysAllocStringLen adds 1
  1061. break;
  1062. case STR_OLESTR:
  1063. pwsz = (LPWSTR)CoTaskMemAlloc(i * sizeof(WCHAR));
  1064. break;
  1065. default:
  1066. return(NULL);
  1067. }
  1068. if (!pwsz)
  1069. return(NULL);
  1070. MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, i);
  1071. pwsz[i - 1] = 0;
  1072. return(pwsz);
  1073. } /* MakeWideStrFromAnsi() */
  1074. // Get the URL location from the .URL file, and send it to the progress dude
  1075. HRESULT CDownLoad::HandleURL(LPTSTR pszPath)
  1076. {
  1077. MyAssert( pszPath );
  1078. LPTSTR pszURL;
  1079. // Create a IUniformResourceLocator object
  1080. IUniformResourceLocator * pURL;
  1081. if (SUCCEEDED(CoCreateInstance(CLSID_InternetShortcut,
  1082. NULL,
  1083. CLSCTX_INPROC_SERVER,
  1084. IID_IUniformResourceLocator,
  1085. (LPVOID*)&pURL)))
  1086. {
  1087. // Get a persist file interface
  1088. IPersistFile *ppf;
  1089. if (SUCCEEDED(pURL->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf)))
  1090. {
  1091. // Attempt to connect the storage of the IURL to the .URL file we
  1092. // downloaded
  1093. if (SUCCEEDED(ppf->Load(OLESTRFROMANSI(pszPath), STGM_READ)))
  1094. {
  1095. // OK, have the URL object give us the location
  1096. if (SUCCEEDED(pURL->GetURL(&pszURL)) && pszURL)
  1097. {
  1098. // Notify the callback about the URL location
  1099. (m_lpfnCB)(m_hRequest,m_lpCDialingDlg, CALLBACK_TYPE_URL, (LPVOID)pszURL, lstrlen(pszURL));
  1100. // Free the allocated URL, since the callback made a copy of it
  1101. IMalloc* pMalloc;
  1102. HRESULT hres = SHGetMalloc(&pMalloc);
  1103. if (SUCCEEDED(hres))
  1104. {
  1105. pMalloc->Free(pszURL);
  1106. pMalloc->Release();
  1107. }
  1108. }
  1109. }
  1110. // Release the persist file interface
  1111. ppf->Release();
  1112. }
  1113. // release the URL object
  1114. pURL->Release();
  1115. }
  1116. return(NO_ERROR);
  1117. }
  1118. #define PHONEBOOK_LIBRARY TEXT("ICWPHBK.DLL")
  1119. #define PHBK_LOADAPI "PhoneBookLoad"
  1120. #define PHBK_MERGEAPI "PhoneBookMergeChanges"
  1121. #define PHBK_UNLOADAPI "PhoneBookUnload"
  1122. #define PHONEBOOK_SUFFIX TEXT(".PHB")
  1123. typedef HRESULT (CALLBACK* PFNPHONEBOOKLOAD)(LPCTSTR pszISPCode, DWORD *pdwPhoneID);
  1124. typedef HRESULT (CALLBACK* PFNPHONEBOOKMERGE)(DWORD dwPhoneID, LPTSTR pszFileName);
  1125. typedef HRESULT (CALLBACK *PFNPHONEBOOKUNLOAD) (DWORD dwPhoneID);
  1126. HRESULT HandleChg(LPTSTR pszPath)
  1127. {
  1128. TCHAR szPhoneBookPath[MAX_PATH+1];
  1129. TCHAR *p;
  1130. LPTSTR szFilePart;
  1131. HRESULT hr = ERROR_FILE_NOT_FOUND;
  1132. HINSTANCE hPHBKDLL = NULL;
  1133. FARPROC fp;
  1134. DWORD dwPhoneBook;
  1135. lstrcpy(szPhoneBookPath,pszPath);
  1136. if (lstrlen(szPhoneBookPath) > 4)
  1137. {
  1138. p = &(szPhoneBookPath[lstrlen(szPhoneBookPath)-4]);
  1139. } else {
  1140. hr = ERROR_INVALID_PARAMETER;
  1141. goto HandleChgExit;
  1142. }
  1143. lstrcpy(p,PHONEBOOK_SUFFIX);
  1144. while (*p != '\\' && p > &szPhoneBookPath[0])
  1145. p--;
  1146. p++;
  1147. if(!SearchPath(NULL,p,NULL,MAX_PATH,szPhoneBookPath,&szFilePart))
  1148. {
  1149. hr = GetLastError();
  1150. goto HandleChgExit;
  1151. }
  1152. hPHBKDLL = LoadLibrary(PHONEBOOK_LIBRARY);
  1153. if (!hPHBKDLL)
  1154. {
  1155. hr = GetLastError();
  1156. goto HandleChgExit;
  1157. }
  1158. fp = GetProcAddress(hPHBKDLL,PHBK_LOADAPI);
  1159. if (!fp)
  1160. {
  1161. hr = GetLastError();
  1162. goto HandleChgExit;
  1163. }
  1164. hr = ((PFNPHONEBOOKLOAD)fp)(pszPath,&dwPhoneBook);
  1165. if(hr != ERROR_SUCCESS)
  1166. goto HandleChgExit;
  1167. fp = GetProcAddress(hPHBKDLL,PHBK_MERGEAPI);
  1168. if (!fp)
  1169. {
  1170. hr = GetLastError();
  1171. goto HandleChgExit;
  1172. }
  1173. hr = ((PFNPHONEBOOKMERGE)fp)(dwPhoneBook,pszPath);
  1174. fp = GetProcAddress(hPHBKDLL,PHBK_UNLOADAPI);
  1175. if (!fp)
  1176. {
  1177. hr = GetLastError();
  1178. goto HandleChgExit;
  1179. }
  1180. ((PFNPHONEBOOKUNLOAD)fp)(dwPhoneBook);
  1181. HandleChgExit:
  1182. return hr;
  1183. }
  1184. HRESULT HandleOthers(LPTSTR pszPath)
  1185. {
  1186. DWORD_PTR dwErr;
  1187. TCHAR szCmd[MAX_PATH + 1];
  1188. MyAssert( pszPath );
  1189. // 11/20/96 jmazner Normandy #5272
  1190. // Wrap quotes around pszPath in case it includes a space.
  1191. // add 2 for two quotes
  1192. MyAssert( (lstrlen(pszPath) + 2) < MAX_PATH );
  1193. if( '\"' != pszPath[0] )
  1194. {
  1195. lstrcpy(szCmd,TEXT("\""));
  1196. lstrcat(szCmd, pszPath);
  1197. int i = lstrlen(szCmd);
  1198. szCmd[i] = '\"';
  1199. szCmd[i+1] = '\0';
  1200. }
  1201. else
  1202. {
  1203. lstrcpyn(szCmd, pszPath, lstrlen(pszPath));
  1204. }
  1205. if((dwErr=(DWORD_PTR)ShellExecute(NULL, NULL, szCmd, NULL, NULL, SW_SHOWNORMAL)) < 32)
  1206. return (DWORD)dwErr;
  1207. else
  1208. return ERROR_SUCCESS;
  1209. }
  1210. LPTSTR GetExtension(LPTSTR pszPath)
  1211. {
  1212. LPTSTR pszRet = _tcsrchr(pszPath, '.');
  1213. if(pszRet)
  1214. return pszRet+1;
  1215. else
  1216. return NULL;
  1217. }
  1218. // Normandy 12093 - ChrisK 12/3/96
  1219. // return the error code for the first error that occurs while processing a file,
  1220. // but don't stop processing files.
  1221. //
  1222. HRESULT CDownLoad::Process(void)
  1223. {
  1224. HRESULT hr;
  1225. HRESULT hrProcess = ERROR_SUCCESS;
  1226. LPTSTR pszExt;
  1227. CFileInfo *pfi;
  1228. for(pfi=m_pfiHead; pfi; pfi=pfi->m_pfiNext)
  1229. {
  1230. // Normandy 12093 - ChrisK 12/3/96
  1231. hr = ERROR_SUCCESS;
  1232. if(pfi->m_fInline)
  1233. {
  1234. pszExt = GetExtension(pfi->m_pszPath);
  1235. if(!pszExt)
  1236. continue;
  1237. if (lstrcmpi(pszExt, EXT_CAB)==0)
  1238. hr = HandleCab(pfi->m_pszPath);
  1239. else if(lstrcmpi(pszExt, EXT_EXE)==0)
  1240. hr = HandleExe(pfi->m_pszPath, m_hCancelSemaphore);
  1241. else if(lstrcmpi(pszExt, EXT_REG)==0)
  1242. hr = HandleReg(pfi->m_pszPath, m_hCancelSemaphore);
  1243. else if(lstrcmpi(pszExt, EXT_CHG)==0)
  1244. hr = HandleChg(pfi->m_pszPath);
  1245. else if(lstrcmpi(pszExt, EXT_INF)==0)
  1246. hr = HandleInf(pfi->m_pszPath, m_hCancelSemaphore);
  1247. else if(lstrcmpi(pszExt, EXT_URL)==0)
  1248. hr = HandleURL(pfi->m_pszPath);
  1249. else
  1250. hr = HandleOthers(pfi->m_pszPath);
  1251. // Normandy 12093 - ChrisK 12/3/96
  1252. if ((ERROR_SUCCESS == hrProcess) && (ERROR_SUCCESS != hr))
  1253. hrProcess = hr;
  1254. }
  1255. }
  1256. // Normandy 12093 - ChrisK 12/3/96
  1257. return hrProcess;
  1258. }
  1259. HRESULT CDownLoad::SetStatusCallback (INTERNET_STATUS_CALLBACK lpfnCB)
  1260. {
  1261. HRESULT hr;
  1262. hr = ERROR_SUCCESS;
  1263. if (!lpfnCB)
  1264. {
  1265. hr = ERROR_INVALID_PARAMETER;
  1266. } else {
  1267. m_lpfnCB = lpfnCB;
  1268. }
  1269. return hr;
  1270. }
  1271. #ifdef DEBUG
  1272. extern "C" HRESULT WINAPI DLTest(LPTSTR pszURL)
  1273. {
  1274. CDownLoad* pdl = new CDownLoad(pszURL);
  1275. HRESULT hr = pdl->Execute();
  1276. if(hr) goto done;
  1277. hr = pdl->Process();
  1278. done:
  1279. delete pdl;
  1280. return hr;
  1281. }
  1282. #endif //DEBUG
  1283. HRESULT WINAPI DownLoadInit(LPTSTR pszURL, DWORD_PTR FAR *lpCDialingDlg, DWORD_PTR FAR *pdwDownLoad, HWND hWndMain)
  1284. {
  1285. g_hWndMain = hWndMain;
  1286. HRESULT hr = ERROR_NOT_ENOUGH_MEMORY;
  1287. CDownLoad* pdl = new CDownLoad(pszURL);
  1288. if (!pdl) goto DownLoadInitExit;
  1289. *pdwDownLoad = (DWORD_PTR)pdl;
  1290. //
  1291. // 5/27/97 jmazner Olympus #4579
  1292. //
  1293. pdl->m_lpCDialingDlg = (DWORD_PTR)lpCDialingDlg;
  1294. hr = ERROR_SUCCESS;
  1295. //
  1296. // 5/23/97 jmazner Olympus #4652
  1297. // create a semaphore in non-signaled state. If we ever get a downLoadCancel, we
  1298. // should signal the semaphore, and any waiting threads should notice that and bail out.
  1299. //
  1300. pdl->m_hCancelSemaphore = CreateSemaphore( NULL, 0, 1, TEXT("ICWDL DownloadCancel Semaphore") );
  1301. if( !pdl->m_hCancelSemaphore || (ERROR_ALREADY_EXISTS == GetLastError()) )
  1302. {
  1303. MyDprintf("ICWDL: Unable to create CancelSemaphore!!\n");
  1304. hr = ERROR_ALREADY_EXISTS;
  1305. }
  1306. DownLoadInitExit:
  1307. return hr;
  1308. }
  1309. HRESULT WINAPI DownLoadCancel(DWORD_PTR dwDownLoad)
  1310. {
  1311. MyDprintf("ICWDL: DownLoadCancel called\n");
  1312. if (dwDownLoad)
  1313. {
  1314. MyDprintf("ICWDL: DownLoadCancel releasing m_hCancelSemaphore\n");
  1315. MyAssert( ((CDownLoad*)dwDownLoad)->m_hCancelSemaphore );
  1316. ReleaseSemaphore( ((CDownLoad*)dwDownLoad)->m_hCancelSemaphore, 1, NULL );
  1317. ((CDownLoad*)dwDownLoad)->Cancel();
  1318. return ERROR_SUCCESS;
  1319. }
  1320. else
  1321. {
  1322. return ERROR_INVALID_PARAMETER;
  1323. }
  1324. }
  1325. HRESULT WINAPI DownLoadExecute(DWORD_PTR dwDownLoad)
  1326. {
  1327. if (dwDownLoad)
  1328. {
  1329. return ((CDownLoad*)dwDownLoad)->Execute();
  1330. }
  1331. else
  1332. {
  1333. return ERROR_INVALID_PARAMETER;
  1334. }
  1335. }
  1336. HRESULT WINAPI DownLoadClose(DWORD_PTR dwDownLoad)
  1337. {
  1338. MyDprintf("ICWDL: DownLoadClose called \n");
  1339. if (dwDownLoad)
  1340. {
  1341. // be good and cancel any downloads that are in progress
  1342. ((CDownLoad*)dwDownLoad)->Cancel();
  1343. delete ((CDownLoad*)dwDownLoad);
  1344. return ERROR_SUCCESS;
  1345. }
  1346. else
  1347. {
  1348. return ERROR_INVALID_PARAMETER;
  1349. }
  1350. }
  1351. HRESULT WINAPI DownLoadSetStatusCallback
  1352. (
  1353. DWORD_PTR dwDownLoad,
  1354. INTERNET_STATUS_CALLBACK lpfnCB
  1355. )
  1356. {
  1357. if (dwDownLoad)
  1358. {
  1359. return ((CDownLoad*)dwDownLoad)->SetStatusCallback(lpfnCB);
  1360. }
  1361. else
  1362. {
  1363. return ERROR_INVALID_PARAMETER;
  1364. }
  1365. }
  1366. HRESULT WINAPI DownLoadProcess(DWORD_PTR dwDownLoad)
  1367. {
  1368. MyDprintf("ICWDL: DownLoadProcess\n");
  1369. if (dwDownLoad)
  1370. {
  1371. return ((CDownLoad*)dwDownLoad)->Process();
  1372. }
  1373. else
  1374. {
  1375. return ERROR_INVALID_PARAMETER;
  1376. }
  1377. }