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.

1642 lines
44 KiB

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