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.

3414 lines
107 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: main.cpp
  4. //
  5. // Module: CMDL32.EXE
  6. //
  7. // Synopsis: Main source for PhoneBook download connect action
  8. //
  9. // Copyright (c) 1996-1999 Microsoft Corporation
  10. //
  11. // Author: nickball Created Header 04/08/98
  12. //
  13. //+----------------------------------------------------------------------------
  14. #include "cmmaster.h"
  15. #include "shlobj.h"
  16. const TCHAR* const c_pszIConnDwnMsg = TEXT("IConnDwn Message"); // for RegisterWindowMessage() for event messages
  17. const TCHAR* const c_pszIConnDwnAgent = TEXT("Microsoft Connection Manager"); // agent for InternetOpen()
  18. const TCHAR* const c_pszIConnDwnContent = TEXT("application/octet-stream"); // content type for HttpOpenRequest()
  19. const TCHAR* const c_pszCmEntryHideDelay = TEXT("HideDelay");
  20. const TCHAR* const c_pszCmEntryDownloadDelay = TEXT("DownLoadDelay");
  21. const TCHAR* const c_pszCmEntryPbUpdateMessage = TEXT("PBUpdateMessage");
  22. #ifdef EXTENDED_CAB_CONTENTS
  23. //
  24. // SPECIAL NOTE:
  25. //
  26. // Be careful here. If you re-enable EXTENDED_CAB_CONTENTS, then you must
  27. // address the possibility that different instances might be doing updates
  28. // simultaneously in which case a common name such as "PBUPDATE.DIR" is not
  29. // appropriate. Because we do not implement this feature, we do not concern
  30. // ourselves with it for the simple PBK case. Thus we copy the .PBK, .PBR,
  31. // etc. directly from the original tmp dir to the profile directory when
  32. // updating.
  33. //
  34. const TCHAR* const c_pszDirName = TEXT("PBUPDATE.DIR"); // directory to expand .CAB into
  35. const TCHAR* const c_pszInfInDir = TEXT("PBUPDATE.DIR\\PBUPDATE.INF");
  36. const TCHAR* const c_pszPbdInDir = TEXT("PBUPDATE.DIR\\PBUPDATE.PBD");
  37. static LPVOID MyAdvPackLoadAndLink(ArgsStruct *pArgs, LPCTSTR pszFunc)
  38. {
  39. LPVOID pvFunc;
  40. if (!pArgs->hAdvPack)
  41. {
  42. pArgs->hAdvPack = LoadLibrary(TEXT("advpack.dll"));
  43. if (!pArgs->hAdvPack)
  44. {
  45. MYDBG(("MyAdvPackLoadAndLink() LoadLibrary() failed, GLE=%u.",GetLastError()));
  46. return (NULL);
  47. }
  48. }
  49. pvFunc = GetProcAddress(pArgs->hAdvPack,pszFunc);
  50. MYDBGTST(!pvFunc,("MyAdvPackLoadAndLink() GetProcAddress(%s) failed, GLE=%u.",pszFunc,GetLastError()));
  51. return (pvFunc);
  52. }
  53. #define RSC_FLAG_INF 1
  54. static HRESULT MyRunSetupCommand(ArgsStruct *pArgs,
  55. HWND hwndParent,
  56. LPCSTR pszCmdName,
  57. LPCSTR pszInfSection,
  58. LPCSTR pszDir,
  59. LPCSTR pszTitle,
  60. HANDLE *phExe,
  61. DWORD dwFlags,
  62. LPVOID pvRsvd)
  63. {
  64. HRESULT (WINAPI *pfn)(HWND,LPCSTR,LPCSTR,LPCSTR,LPCSTR,HANDLE,DWORD,LPVOID);
  65. pfn = (HRESULT (WINAPI *)(HWND,LPCSTR,LPCSTR,LPCSTR,LPCSTR,HANDLE,DWORD,LPVOID)) MyAdvPackLoadAndLink(pArgs,TEXT("RunSetupCommand"));
  66. if (!pfn)
  67. {
  68. return (HRESULT_FROM_WIN32(GetLastError()));
  69. }
  70. return (pfn(hwndParent,pszCmdName,pszInfSection,pszDir,pszTitle,phExe,dwFlags,pvRsvd));
  71. }
  72. static DWORD MyNeedRebootInit(ArgsStruct *pArgs)
  73. {
  74. DWORD (WINAPI *pfn)(VOID);
  75. pfn = (DWORD (WINAPI *)(VOID)) MyAdvPackLoadAndLink(pArgs,TEXT("NeedRebootInit"));
  76. if (!pfn)
  77. {
  78. return (0);
  79. }
  80. return (pfn());
  81. }
  82. static BOOL MyNeedReboot(ArgsStruct *pArgs, DWORD dwCookie)
  83. {
  84. BOOL (WINAPI *pfn)(DWORD);
  85. pfn = (BOOL (WINAPI *)(DWORD)) MyAdvPackLoadAndLink(pArgs,TEXT("NeedReboot"));
  86. if (!pfn)
  87. {
  88. return (FALSE);
  89. }
  90. return (pfn(dwCookie));
  91. }
  92. #endif // EXTENDED_CAB_CONTENTS
  93. //+----------------------------------------------------------------------------
  94. //
  95. // Function: SuppressInetAutoDial
  96. //
  97. // Synopsis: Sets Inet Option to turn off auto-dial for requests made by this
  98. // process. This prevents multiple instances of CM popping up to
  99. // service CMDL initiated requests if the user disconnects CM
  100. // immediately after getting connected.
  101. //
  102. // Arguments: None
  103. //
  104. // Returns: Nothing
  105. //
  106. // History: nickball Created Header 6/3/99
  107. //
  108. //+----------------------------------------------------------------------------
  109. static void SuppressInetAutoDial(HINTERNET hInternet)
  110. {
  111. DWORD dwTurnOff = 1;
  112. //
  113. // The flag only exists for IE5, this call
  114. // will have no effect if IE5 is not present.
  115. //
  116. BOOL bTmp = InternetSetOption(hInternet, INTERNET_OPTION_DISABLE_AUTODIAL, &dwTurnOff, sizeof(DWORD));
  117. MYDBGTST(FALSE == bTmp, ("InternetSetOption() returned %d, GLE=%u.", bTmp, GetLastError()));
  118. }
  119. static BOOL CmFreeIndirect(LPVOID *ppvBuffer)
  120. {
  121. CmFree(*ppvBuffer);
  122. *ppvBuffer = NULL;
  123. return TRUE;
  124. }
  125. static BOOL CmFreeIndirect(LPTSTR *ppszBuffer)
  126. {
  127. return (CmFreeIndirect((LPVOID *) ppszBuffer));
  128. }
  129. static LPURL_COMPONENTS MyInternetCrackUrl(LPTSTR pszUrl, DWORD dwOptions)
  130. {
  131. struct _sRes
  132. {
  133. URL_COMPONENTS sUrl;
  134. TCHAR szScheme[INTERNET_MAX_SCHEME_LENGTH];
  135. TCHAR szHostName[INTERNET_MAX_HOST_NAME_LENGTH+1];
  136. TCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH+1];
  137. TCHAR szPassword[INTERNET_MAX_PASSWORD_LENGTH+1];
  138. TCHAR szUrlPath[INTERNET_MAX_PATH_LENGTH+1];
  139. TCHAR szExtraInfo[INTERNET_MAX_PATH_LENGTH+1];
  140. } *psRes;
  141. BOOL bRes;
  142. UINT nIdx;
  143. UINT nSpaces;
  144. if (!pszUrl)
  145. {
  146. MYDBG(("MyInternetCrackUrl() invalid parameter."));
  147. SetLastError(ERROR_INVALID_PARAMETER);
  148. return (NULL);
  149. }
  150. psRes = (struct _sRes *) CmMalloc(sizeof(*psRes));
  151. if (!psRes)
  152. {
  153. return (NULL);
  154. }
  155. psRes->sUrl.dwStructSize = sizeof(psRes->sUrl);
  156. psRes->sUrl.lpszScheme = psRes->szScheme;
  157. psRes->sUrl.dwSchemeLength = sizeof(psRes->szScheme);
  158. psRes->sUrl.lpszHostName = psRes->szHostName;
  159. psRes->sUrl.dwHostNameLength = sizeof(psRes->szHostName);
  160. psRes->sUrl.lpszUserName = psRes->szUserName;
  161. psRes->sUrl.dwUserNameLength = sizeof(psRes->szUserName);
  162. psRes->sUrl.lpszPassword = psRes->szPassword;
  163. psRes->sUrl.dwPasswordLength = sizeof(psRes->szPassword);
  164. psRes->sUrl.lpszUrlPath = psRes->szUrlPath;
  165. psRes->sUrl.dwUrlPathLength = sizeof(psRes->szUrlPath);
  166. psRes->sUrl.lpszExtraInfo = psRes->szExtraInfo;
  167. psRes->sUrl.dwExtraInfoLength = sizeof(psRes->szExtraInfo);
  168. bRes = InternetCrackUrl(pszUrl,0,dwOptions,&psRes->sUrl);
  169. if (!bRes)
  170. {
  171. MYDBG(("MyInternetCrackUrl() InternetCrackUrl(pszUrl=%s) failed, GLE=%u.",pszUrl,GetLastError()));
  172. CmFree(psRes);
  173. return (NULL);
  174. }
  175. nSpaces = 0;
  176. for (nIdx=0;psRes->szExtraInfo[nIdx];nIdx++)
  177. {
  178. if (psRes->szExtraInfo[nIdx] == ' ')
  179. {
  180. nSpaces++;
  181. }
  182. }
  183. if (nSpaces)
  184. {
  185. TCHAR szQuoted[sizeof(psRes->szExtraInfo)/sizeof(TCHAR)];
  186. if (lstrlen(psRes->szExtraInfo)+nSpaces*2 > sizeof(psRes->szExtraInfo)/sizeof(TCHAR)-1)
  187. {
  188. MYDBG(("MyInternetCrackUrl() quoting spaces will exceed buffer size."));
  189. CmFree(psRes);
  190. return (NULL);
  191. }
  192. ZeroMemory(szQuoted,sizeof(szQuoted));
  193. nSpaces = 0;
  194. for (nIdx=0,nSpaces=0;psRes->szExtraInfo[nIdx];nIdx++,nSpaces++)
  195. {
  196. if (psRes->szExtraInfo[nIdx] == ' ')
  197. {
  198. szQuoted[nSpaces++] = '%';
  199. szQuoted[nSpaces++] = '2';
  200. szQuoted[nSpaces] = '0';
  201. }
  202. else
  203. {
  204. szQuoted[nSpaces] = psRes->szExtraInfo[nIdx];
  205. }
  206. }
  207. lstrcpy(psRes->szExtraInfo,szQuoted);
  208. }
  209. return (&psRes->sUrl);
  210. }
  211. static BOOL DownloadFileFtp(DownloadArgs *pdaArgs, HANDLE hFile)
  212. {
  213. BOOL bRes = FALSE;
  214. WIN32_FIND_DATA wfdData;
  215. LPBYTE pbData = NULL;
  216. LPTSTR pszObject = (LPTSTR) CmMalloc((INTERNET_MAX_PATH_LENGTH*2) + 1);
  217. if (NULL == pszObject)
  218. {
  219. MYDBG(("DownloadFileFtp() aborted."));
  220. goto done;
  221. }
  222. pdaArgs->hInet = InternetOpen(c_pszIConnDwnAgent,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
  223. if (*(pdaArgs->pbAbort))
  224. {
  225. MYDBG(("DownloadFileFtp() aborted."));
  226. goto done;
  227. }
  228. if (!pdaArgs->hInet)
  229. {
  230. MYDBG(("DownloadFileFtp() InternetOpen() failed, GLE=%u.",GetLastError()));
  231. goto done;
  232. }
  233. pdaArgs->hConn = InternetConnect(pdaArgs->hInet,
  234. pdaArgs->psUrl->lpszHostName,
  235. pdaArgs->psUrl->nPort,
  236. pdaArgs->psUrl->lpszUserName&&*pdaArgs->psUrl->lpszUserName?pdaArgs->psUrl->lpszUserName:NULL,
  237. pdaArgs->psUrl->lpszPassword&&*pdaArgs->psUrl->lpszPassword?pdaArgs->psUrl->lpszPassword:NULL,
  238. INTERNET_SERVICE_FTP,
  239. 0,
  240. 0);
  241. if (*(pdaArgs->pbAbort))
  242. {
  243. MYDBG(("DownloadFileFtp() aborted."));
  244. goto done;
  245. }
  246. if (!pdaArgs->hConn)
  247. {
  248. MYDBG(("DownloadFileFtp() InternetConnect(pszHostName=%s) failed, GLE=%u.",pdaArgs->psUrl->lpszHostName,GetLastError()));
  249. goto done;
  250. }
  251. lstrcpy(pszObject,pdaArgs->psUrl->lpszUrlPath);
  252. // lstrcat(pszObject,pdaArgs->psUrl->lpszExtraInfo);
  253. ZeroMemory(&wfdData,sizeof(wfdData));
  254. pdaArgs->hReq = FtpFindFirstFile(pdaArgs->hConn,pszObject,&wfdData,INTERNET_FLAG_RELOAD|INTERNET_FLAG_DONT_CACHE,0);
  255. if (*(pdaArgs->pbAbort))
  256. {
  257. MYDBG(("DownloadFileFtp() aborted."));
  258. goto done;
  259. }
  260. if (!pdaArgs->hReq)
  261. {
  262. MYDBG(("DownloadFileFtp() FtpFindFirstFile() failed, GLE=%u.",GetLastError()));
  263. goto done;
  264. }
  265. bRes = InternetFindNextFile(pdaArgs->hReq,&wfdData);
  266. if (*(pdaArgs->pbAbort))
  267. {
  268. MYDBG(("DownloadFileFtp() aborted."));
  269. goto done;
  270. }
  271. if (bRes || (GetLastError() != ERROR_NO_MORE_FILES))
  272. {
  273. MYDBG(("DownloadFileFtp() InternetFindNextFile() returned unexpected result, bRes=%u, GetLastError()=%u.",bRes,bRes?0:GetLastError()));
  274. bRes = FALSE;
  275. goto done;
  276. }
  277. InternetCloseHandle(pdaArgs->hReq);
  278. if (*(pdaArgs->pbAbort))
  279. {
  280. MYDBG(("DownloadFileFtp() aborted."));
  281. goto done;
  282. }
  283. pdaArgs->dwTotalSize = wfdData.nFileSizeLow;
  284. pdaArgs->hReq = FtpOpenFile(pdaArgs->hConn,pszObject,GENERIC_READ,FTP_TRANSFER_TYPE_BINARY,0);
  285. if (*(pdaArgs->pbAbort))
  286. {
  287. MYDBG(("DownloadFileFtp() aborted."));
  288. goto done;
  289. }
  290. if (!pdaArgs->hReq)
  291. {
  292. MYDBG(("DownloadFileFtp() FtpOpenFile() failed, GLE=%u.",GetLastError()));
  293. goto done;
  294. }
  295. pbData = (LPBYTE) CmMalloc(BUFFER_LENGTH);
  296. if (!pbData)
  297. {
  298. goto done;
  299. }
  300. while (1)
  301. {
  302. DWORD dwBytesRead;
  303. DWORD dwBytesWritten;
  304. bRes = InternetReadFile(pdaArgs->hReq,pbData,BUFFER_LENGTH,&dwBytesRead);
  305. if (*(pdaArgs->pbAbort))
  306. {
  307. MYDBG(("DownloadFileFtp() aborted."));
  308. goto done;
  309. }
  310. if (!bRes)
  311. {
  312. MYDBG(("DownloadFileFtp() InternetReadFile() failed, GLE=%u.",GetLastError()));
  313. goto done;
  314. }
  315. if (!dwBytesRead)
  316. {
  317. break;
  318. }
  319. bRes = WriteFile(hFile,pbData,dwBytesRead,&dwBytesWritten,NULL);
  320. if (*(pdaArgs->pbAbort))
  321. {
  322. MYDBG(("DownloadFileFtp() aborted."));
  323. goto done;
  324. }
  325. if (!bRes)
  326. {
  327. MYDBG(("DownloadFileFtp() WriteFile() failed, GLE=%u.",GetLastError()));
  328. goto done;
  329. }
  330. if (dwBytesRead != dwBytesWritten)
  331. {
  332. MYDBG(("DownloadFileFtp() dwBytesRead=%u, dwBytesWritten=%u.",dwBytesRead,dwBytesWritten));
  333. SetLastError(ERROR_DISK_FULL);
  334. goto done;
  335. }
  336. pdaArgs->dwTransferred += dwBytesRead;
  337. if (pdaArgs->pfnEvent)
  338. {
  339. pdaArgs->pfnEvent(pdaArgs->dwTransferred,pdaArgs->dwTotalSize,pdaArgs->pvEventParam);
  340. }
  341. if (*(pdaArgs->pbAbort))
  342. {
  343. MYDBG(("DownloadFileFtp() aborted."));
  344. goto done;
  345. }
  346. }
  347. bRes = TRUE;
  348. done:
  349. if (pbData)
  350. {
  351. CmFree(pbData);
  352. }
  353. if (pdaArgs->hReq)
  354. {
  355. InternetCloseHandle(pdaArgs->hReq);
  356. pdaArgs->hReq = NULL;
  357. }
  358. if (pdaArgs->hConn)
  359. {
  360. InternetCloseHandle(pdaArgs->hConn);
  361. pdaArgs->hConn = NULL;
  362. }
  363. if (pdaArgs->hInet)
  364. {
  365. InternetCloseHandle(pdaArgs->hInet);
  366. pdaArgs->hInet = NULL;
  367. }
  368. if (pszObject)
  369. {
  370. CmFree(pszObject);
  371. }
  372. return (bRes);
  373. }
  374. static BOOL DownloadFileFile(DownloadArgs *pdaArgs, HANDLE hFile)
  375. {
  376. BOOL bRes = FALSE;
  377. HANDLE hInFile = INVALID_HANDLE_VALUE;
  378. LPBYTE pbData = NULL;
  379. hInFile = CreateFile(pdaArgs->psUrl->lpszUrlPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  380. if (*(pdaArgs->pbAbort))
  381. {
  382. MYDBG(("DownloadFileFile() aborted."));
  383. goto done;
  384. }
  385. if (hInFile == INVALID_HANDLE_VALUE)
  386. {
  387. MYDBG(("DownloadFileFile() CreateFile(pszFile=%s) failed, GLE=%u.",pdaArgs->psUrl->lpszUrlPath,GetLastError()));
  388. goto done;
  389. }
  390. pdaArgs->dwTotalSize = GetFileSize(hInFile,NULL);
  391. if (*(pdaArgs->pbAbort))
  392. {
  393. MYDBG(("DownloadFileFile() aborted."));
  394. goto done;
  395. }
  396. if (pdaArgs->dwTotalSize == -1)
  397. {
  398. MYDBG(("DownloadFileFile() GetFileSize() failed, GLE=%u.",GetLastError()));
  399. goto done;
  400. }
  401. pbData = (LPBYTE) CmMalloc(BUFFER_LENGTH);
  402. if (!pbData)
  403. {
  404. goto done;
  405. }
  406. while (1)
  407. {
  408. DWORD dwBytesRead;
  409. DWORD dwBytesWritten;
  410. bRes = ReadFile(hInFile,pbData,BUFFER_LENGTH,&dwBytesRead,NULL);
  411. if (*(pdaArgs->pbAbort))
  412. {
  413. MYDBG(("DownloadFileFile() aborted."));
  414. goto done;
  415. }
  416. if (!bRes)
  417. {
  418. MYDBG(("DownloadFileFile() ReadFile() failed, GLE=%u.",GetLastError()));
  419. goto done;
  420. }
  421. if (!dwBytesRead)
  422. {
  423. break;
  424. }
  425. bRes = WriteFile(hFile,pbData,dwBytesRead,&dwBytesWritten,NULL);
  426. if (*(pdaArgs->pbAbort))
  427. {
  428. MYDBG(("DownloadFileFile() aborted."));
  429. goto done;
  430. }
  431. if (!bRes)
  432. {
  433. MYDBG(("DownloadFileFile() WriteFile() failed, GLE=%u.",GetLastError()));
  434. goto done;
  435. }
  436. if (dwBytesRead != dwBytesWritten)
  437. {
  438. MYDBG(("DownloadFileFile() dwBytesRead=%u, dwBytesWritten=%u.",dwBytesRead,dwBytesWritten));
  439. SetLastError(ERROR_DISK_FULL);
  440. goto done;
  441. }
  442. pdaArgs->dwTransferred += dwBytesWritten;
  443. if (pdaArgs->pfnEvent)
  444. {
  445. pdaArgs->pfnEvent(pdaArgs->dwTransferred,pdaArgs->dwTotalSize,pdaArgs->pvEventParam);
  446. }
  447. if (*(pdaArgs->pbAbort))
  448. {
  449. MYDBG(("DownloadFileFile() aborted."));
  450. goto done;
  451. }
  452. }
  453. bRes = TRUE;
  454. done:
  455. if (pbData)
  456. {
  457. CmFree(pbData);
  458. }
  459. if (hInFile != INVALID_HANDLE_VALUE)
  460. {
  461. CloseHandle(hInFile);
  462. }
  463. return (bRes);
  464. }
  465. static BOOL DownloadFileHttp(DownloadArgs *pdaArgs, HANDLE hFile)
  466. {
  467. BOOL bRes = FALSE;
  468. LPBYTE pbData = NULL;
  469. DWORD dwTmpLen;
  470. DWORD dwTmpIdx;
  471. DWORD dwStatus;
  472. LPCTSTR apszContent[] = {c_pszIConnDwnContent,NULL};
  473. LPTSTR pszObject = (LPTSTR) CmMalloc(INTERNET_MAX_PATH_LENGTH + 1);
  474. if (NULL == pszObject)
  475. {
  476. MYDBG(("DownloadFileHttp() aborted."));
  477. goto done;
  478. }
  479. pdaArgs->dwBubbledUpError = 0;
  480. pdaArgs->hInet = InternetOpen(c_pszIConnDwnAgent,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
  481. //
  482. // Supress auto-dial calls to CM from WININET now that we have a handle
  483. //
  484. SuppressInetAutoDial(pdaArgs->hInet);
  485. if (*(pdaArgs->pbAbort))
  486. {
  487. MYDBG(("DownloadFileHttp() aborted."));
  488. goto done;
  489. }
  490. if (!pdaArgs->hInet)
  491. {
  492. pdaArgs->dwBubbledUpError = GetLastError();
  493. MYDBG(("DownloadFileHttp() InternetOpen() failed, GLE=%u.", pdaArgs->dwBubbledUpError));
  494. goto done;
  495. }
  496. pdaArgs->hConn = InternetConnect(pdaArgs->hInet,
  497. pdaArgs->psUrl->lpszHostName,
  498. pdaArgs->psUrl->nPort,
  499. pdaArgs->psUrl->lpszUserName&&*pdaArgs->psUrl->lpszUserName?pdaArgs->psUrl->lpszUserName:NULL,
  500. pdaArgs->psUrl->lpszPassword&&*pdaArgs->psUrl->lpszPassword?pdaArgs->psUrl->lpszPassword:NULL,
  501. INTERNET_SERVICE_HTTP,
  502. 0,
  503. 0);
  504. if (*(pdaArgs->pbAbort))
  505. {
  506. MYDBG(("DownloadFileHttp() aborted."));
  507. goto done;
  508. }
  509. if (!pdaArgs->hConn)
  510. {
  511. pdaArgs->dwBubbledUpError = GetLastError();
  512. MYDBG(("DownloadFileHttp() InternetConnect(pszHostName=%s) failed, GLE=%u.", pdaArgs->psUrl->lpszHostName, pdaArgs->dwBubbledUpError));
  513. goto done;
  514. }
  515. lstrcpy(pszObject,pdaArgs->psUrl->lpszUrlPath);
  516. lstrcat(pszObject,pdaArgs->psUrl->lpszExtraInfo);
  517. MYDBG(("DownloadFileHttp() - HttpOpenRequest - %s", pszObject));
  518. pdaArgs->hReq = HttpOpenRequest(pdaArgs->hConn,
  519. NULL,
  520. pszObject,
  521. NULL,
  522. NULL,
  523. apszContent,
  524. INTERNET_FLAG_RELOAD|INTERNET_FLAG_DONT_CACHE|(pdaArgs->psUrl->nScheme==INTERNET_SCHEME_HTTPS?INTERNET_FLAG_SECURE:0),
  525. 0);
  526. if (*(pdaArgs->pbAbort))
  527. {
  528. MYDBG(("DownloadFileHttp() aborted."));
  529. goto done;
  530. }
  531. if (!pdaArgs->hReq)
  532. {
  533. pdaArgs->dwBubbledUpError = GetLastError();
  534. MYDBG(("DownloadFileHttp() HttpOpenRequest() failed, GLE=%u.", pdaArgs->dwBubbledUpError));
  535. goto done;
  536. }
  537. bRes = HttpSendRequest(pdaArgs->hReq,NULL,0,NULL,0);
  538. if (*(pdaArgs->pbAbort))
  539. {
  540. MYDBG(("DownloadFileHttp() aborted."));
  541. goto done;
  542. }
  543. if (!bRes)
  544. {
  545. pdaArgs->dwBubbledUpError = GetLastError();
  546. MYDBG(("DownloadFileHttp() HttpSendRequest() failed, GLE=%u.", pdaArgs->dwBubbledUpError));
  547. goto done;
  548. }
  549. pbData = (LPBYTE) CmMalloc(BUFFER_LENGTH);
  550. if (!pbData)
  551. {
  552. goto done;
  553. }
  554. while (1)
  555. {
  556. DWORD dwBytesRead;
  557. DWORD dwBytesWritten;
  558. bRes = InternetReadFile(pdaArgs->hReq,pbData,BUFFER_LENGTH,&dwBytesRead);
  559. if (*(pdaArgs->pbAbort))
  560. {
  561. MYDBG(("DownloadFileHttp() aborted."));
  562. goto done;
  563. }
  564. if (!bRes)
  565. {
  566. pdaArgs->dwBubbledUpError = GetLastError();
  567. MYDBG(("DownloadFileHttp() InternetReadFile() failed, GLE=%u.", pdaArgs->dwBubbledUpError));
  568. goto done;
  569. }
  570. if (!dwBytesRead)
  571. {
  572. break;
  573. }
  574. bRes = WriteFile(hFile,pbData,dwBytesRead,&dwBytesWritten,NULL);
  575. if (*(pdaArgs->pbAbort))
  576. {
  577. MYDBG(("DownloadFileHttp() aborted."));
  578. goto done;
  579. }
  580. if (!bRes)
  581. {
  582. pdaArgs->dwBubbledUpError = GetLastError();
  583. MYDBG(("DownloadFileHttp() WriteFile() failed, GLE=%u.", pdaArgs->dwBubbledUpError));
  584. goto done;
  585. }
  586. if (dwBytesRead != dwBytesWritten)
  587. {
  588. MYDBG(("DownloadFileHttp() dwBytesRead=%u, dwBytesWritten=%u.",dwBytesRead,dwBytesWritten));
  589. SetLastError(ERROR_DISK_FULL);
  590. goto done;
  591. }
  592. if (!pdaArgs->dwTransferred)
  593. {
  594. dwTmpLen = sizeof(pdaArgs->dwTotalSize);
  595. dwTmpIdx = 0;
  596. bRes = HttpQueryInfo(pdaArgs->hReq,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,&pdaArgs->dwTotalSize,&dwTmpLen,&dwTmpIdx);
  597. if (*(pdaArgs->pbAbort))
  598. {
  599. MYDBG(("DownloadFileHttp() aborted."));
  600. goto done;
  601. }
  602. MYDBGTST(!bRes,("DownloadFileHttp() HttpQueryInfo() failed, GLE=%u.",GetLastError()));
  603. if (!bRes)
  604. {
  605. pdaArgs->dwBubbledUpError = GetLastError();
  606. }
  607. }
  608. pdaArgs->dwTransferred += dwBytesRead;
  609. if (pdaArgs->pfnEvent)
  610. {
  611. pdaArgs->pfnEvent(pdaArgs->dwTransferred,pdaArgs->dwTotalSize,pdaArgs->pvEventParam);
  612. }
  613. if (*(pdaArgs->pbAbort))
  614. {
  615. MYDBG(("DownloadFileHttp() aborted."));
  616. goto done;
  617. }
  618. }
  619. dwTmpLen = sizeof(dwStatus);
  620. dwTmpIdx = 0;
  621. bRes = HttpQueryInfo(pdaArgs->hReq,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,&dwStatus,&dwTmpLen,&dwTmpIdx);
  622. if (!bRes)
  623. {
  624. pdaArgs->dwBubbledUpError = GetLastError();
  625. MYDBG(("DownloadFileHttp() HttpQueryInfo() failed, GLE=%u.", pdaArgs->dwBubbledUpError));
  626. goto done;
  627. }
  628. switch (dwStatus)
  629. {
  630. case HTTP_STATUS_OK:
  631. break;
  632. case HTTP_STATUS_NO_CONTENT:
  633. case HTTP_STATUS_BAD_REQUEST:
  634. case HTTP_STATUS_NOT_FOUND:
  635. case HTTP_STATUS_SERVER_ERROR:
  636. default:
  637. pdaArgs->dwBubbledUpError = dwStatus;
  638. MYDBG(("DownloadFileHttp() HTTP status code = %u.",dwStatus));
  639. bRes = FALSE;
  640. SetLastError(ERROR_FILE_NOT_FOUND);
  641. goto done;
  642. }
  643. bRes = TRUE;
  644. done:
  645. if ((0 == pdaArgs->dwBubbledUpError) && !*(pdaArgs->pbAbort))
  646. {
  647. //
  648. // If the error value hasn't been set yet, and isn't the Abort case (which
  649. // is logged separately) try to get it from GetLastError().
  650. //
  651. pdaArgs->dwBubbledUpError = GetLastError();
  652. }
  653. if (pbData)
  654. {
  655. CmFree(pbData);
  656. }
  657. if (pdaArgs->hReq)
  658. {
  659. InternetCloseHandle(pdaArgs->hReq);
  660. pdaArgs->hReq = NULL;
  661. }
  662. if (pdaArgs->hConn)
  663. {
  664. InternetCloseHandle(pdaArgs->hConn);
  665. pdaArgs->hConn = NULL;
  666. }
  667. if (pdaArgs->hInet)
  668. {
  669. InternetCloseHandle(pdaArgs->hInet);
  670. pdaArgs->hInet = NULL;
  671. }
  672. if (bRes && (pdaArgs->dwTransferred > pdaArgs->dwTotalSize))
  673. {
  674. pdaArgs->dwTotalSize = pdaArgs->dwTransferred;
  675. }
  676. if (pszObject)
  677. {
  678. CmFree(pszObject);
  679. }
  680. return (bRes);
  681. }
  682. static BOOL DownloadFile(DownloadArgs *pdaArgs, HANDLE hFile)
  683. {
  684. BOOL bRes = FALSE;
  685. pdaArgs->psUrl = MyInternetCrackUrl((LPTSTR) pdaArgs->pszUrl,ICU_ESCAPE);
  686. if (!pdaArgs->psUrl)
  687. {
  688. return (NULL);
  689. }
  690. switch (pdaArgs->psUrl->nScheme)
  691. {
  692. case INTERNET_SCHEME_FTP:
  693. bRes = DownloadFileFtp(pdaArgs,hFile);
  694. break;
  695. case INTERNET_SCHEME_HTTP:
  696. case INTERNET_SCHEME_HTTPS:
  697. bRes = DownloadFileHttp(pdaArgs,hFile);
  698. break;
  699. case INTERNET_SCHEME_FILE:
  700. bRes = DownloadFileFile(pdaArgs,hFile);
  701. break;
  702. default:
  703. MYDBG(("DownloadFile() unhandled scheme (%u).",pdaArgs->psUrl->nScheme));
  704. SetLastError(ERROR_INTERNET_UNRECOGNIZED_SCHEME);
  705. break;
  706. }
  707. // useful for logging
  708. lstrcpyn(pdaArgs->szHostName, pdaArgs->psUrl->lpszHostName, MAX_PATH);
  709. CmFree(pdaArgs->psUrl);
  710. pdaArgs->psUrl = NULL;
  711. return (bRes);
  712. }
  713. typedef struct _EventParam
  714. {
  715. ArgsStruct *pArgs;
  716. DWORD dwIdx;
  717. } EventParam;
  718. static void EventFunc(DWORD dwCompleted, DWORD dwTotal, LPVOID pvParam)
  719. {
  720. EventParam *pepParam = (EventParam *) pvParam;
  721. MYDBG(("EventFunc() dwCompleted=%u, dwTotal=%u.",dwCompleted,dwTotal));
  722. pepParam->pArgs->dwDataCompleted = dwCompleted;
  723. pepParam->pArgs->dwDataTotal = dwTotal;
  724. PostMessage(pepParam->pArgs->hwndDlg,pepParam->pArgs->nMsgId,etDataReceived,0);
  725. }
  726. static BOOL ProcessCabinet(DownloadArgs *pdaArgs, DWORD dwAppFlags)
  727. {
  728. BOOL fRet = TRUE;
  729. if (!pdaArgs->bTransferOk)
  730. return (TRUE); // If the transfer failed, just leave the install type as itInvalid.
  731. {
  732. HFDI hfdi;
  733. ERF erf;
  734. FDICABINETINFO info;
  735. BOOL bRes;
  736. NotifyArgs naArgs = {dwAppFlags,pdaArgs};
  737. bRes = CreateTempDir(pdaArgs->szCabDir);
  738. if (bRes)
  739. {
  740. hfdi = FDICreate(fdi_alloc,fdi_free,fdi_open,fdi_read,fdi_write,fdi_close,fdi_seek,cpu80386,&erf);
  741. MYDBGTST(!hfdi,("ProcessCabinet() FDICreate() failed, fError=%u, erfOper=%u, erfType=%u.",erf.fError,erf.fError?erf.erfOper:0,erf.fError?erf.erfType:0));
  742. if (hfdi)
  743. {
  744. // Open the suspected cab file
  745. CFDIFileFile fff;
  746. bRes = fff.CreateFile(pdaArgs->szFile,GENERIC_READ,FILE_SHARE_READ,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  747. if (bRes)
  748. {
  749. // Verify that this is in fact a cabinet file
  750. bRes = FDIIsCabinet(hfdi,(INT_PTR) &fff, &info);
  751. MYDBGTST(!bRes,("ProcessCabinet() FDIIsCabinet() failed, fError=%u, erfOper=%u, erfType=%u.",erf.fError,erf.fError?erf.erfOper:0,erf.fError?erf.erfType:0));
  752. fff.Close();
  753. if (bRes)
  754. {
  755. // Do the FDI copy
  756. bRes = FDICopy(hfdi,pdaArgs->szFile,TEXT(""),0,(PFNFDINOTIFY)fdi_notify,NULL,&naArgs);
  757. if (!bRes)
  758. {
  759. MYDBG(("ProcessCabinet() FDICopy() failed, fError=%u, erfOper=%u, erfType=%u.",erf.fError,erf.fError?erf.erfOper:0,erf.fError?erf.erfType:0));
  760. //pdaArgs->itType = itInvalid;
  761. }
  762. }
  763. #ifdef EXTENDED_CAB_CONTENTS
  764. else
  765. {
  766. // Not a Cab file, assume exe
  767. if (OS_NT)
  768. {
  769. BOOL bExe = FALSE;
  770. DWORD dwExe = 0;
  771. // GetBinaryType() is not supported under Win95.
  772. bExe = GetBinaryType(pdaArgs->szFile,&dwExe);
  773. MYDBG(("ProcessCabinet() GetBinaryType() return %u, dwExe=%u.",bExe,dwExe));
  774. if (!(bExe && ((dwExe & SCS_32BIT_BINARY) || (dwExe & SCS_DOS_BINARY))))
  775. {
  776. fRet = FALSE;
  777. // if it's not either a win32 or dos exe, then just cleanup and abort
  778. goto destroy_fdi;
  779. }
  780. }
  781. MYDBGASSERT(!pdaArgs->rgfpiFileProcessInfo && !pdaArgs->dwNumFilesToProcess);
  782. pdaArgs->rgfpiFileProcessInfo = (PFILEPROCESSINFO)CmMalloc(sizeof(FILEPROCESSINFO));
  783. if (!pdaArgs->rgfpiFileProcessInfo)
  784. {
  785. MYDBG((TEXT("ProcessCabinet: Malloc() failed.")));
  786. fRet = FALSE;
  787. goto destroy_fdi;
  788. }
  789. pdaArgs->dwNumFilesToProcess++;
  790. pdaArgs->rgfpiFileProcessInfo[0].itType = itExe;
  791. pdaArgs->rgfpiFileProcessInfo[0].pszFile = CmStrCpyAlloc(pdaArgs->szFile);
  792. pdaArgs->szCabDir[0] = TEXT('\0');
  793. // pdaArgs->itType = itExe;
  794. }
  795. destroy_fdi:
  796. #endif // EXTENDED_CAB_CONTENTS
  797. }
  798. // Destroy the FDI context
  799. bRes = FDIDestroy(hfdi);
  800. MYDBGTST(!bRes,("ProcessCabinet() FDIDestroy() failed."));
  801. }
  802. }
  803. }
  804. return fRet;
  805. }
  806. //
  807. // Recursively deletes the contents of a directory(pszDir). Changes the file
  808. // attributes from RO to RW if necessary.
  809. //
  810. static BOOL ZapDir(LPCTSTR pszDir)
  811. {
  812. HANDLE hFind = NULL;
  813. TCHAR szTmp[MAX_PATH+1];
  814. BOOL bRes;
  815. // If pszDir format is not appropriate, bail out
  816. if (!pszDir || !*pszDir || (lstrlen(pszDir)+2 > sizeof(szTmp)/sizeof(TCHAR)-1))
  817. {
  818. SetLastError(ERROR_BAD_PATHNAME);
  819. return (FALSE);
  820. }
  821. lstrcpy(szTmp,pszDir);
  822. if (GetLastChar(szTmp) != '\\')
  823. {
  824. lstrcat(szTmp,TEXT("\\"));
  825. }
  826. lstrcat(szTmp,TEXT("*"));
  827. // Traverse directory
  828. WIN32_FIND_DATA wfdData;
  829. hFind = FindFirstFile(szTmp,&wfdData);
  830. MYDBGTST((hFind==INVALID_HANDLE_VALUE)&&(GetLastError()!=ERROR_FILE_NOT_FOUND)&&(GetLastError()!=ERROR_NO_MORE_FILES)&&(GetLastError()!=ERROR_PATH_NOT_FOUND),("ZapDir() FindFirstFile() failed, GLE=%u.",GetLastError()));
  831. if (hFind != INVALID_HANDLE_VALUE)
  832. {
  833. while (1)
  834. {
  835. MYDBGTST(lstrlen(pszDir)+lstrlen(wfdData.cFileName)+1 > sizeof(szTmp)/sizeof(TCHAR)-1,("ZapDir() pszDir=%s+cFileName=%s exceeds %u.",pszDir,wfdData.cFileName,sizeof(szTmp)/sizeof(TCHAR)-1));
  836. if (lstrlen(pszDir)+lstrlen(wfdData.cFileName)+1 <= sizeof(szTmp)/sizeof(TCHAR)-1)
  837. {
  838. if ((lstrcmp(wfdData.cFileName,TEXT(".")) != 0) && (lstrcmp(wfdData.cFileName,TEXT("..")) != 0))
  839. {
  840. lstrcpy(szTmp,pszDir);
  841. if (GetLastChar(szTmp) != '\\')
  842. {
  843. lstrcat(szTmp,TEXT("\\"));
  844. }
  845. lstrcat(szTmp,wfdData.cFileName);
  846. // If the file is read-only, attrib writeable so we can delete it
  847. if (wfdData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
  848. {
  849. bRes = SetFileAttributes(szTmp,wfdData.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
  850. MYDBGTST(!bRes,("ZapDir() SetFileAttributes(szTmp=%s) failed, GLE=%u.",szTmp,GetLastError()));
  851. }
  852. // Found a dir entry, recurse down a level
  853. if (wfdData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  854. {
  855. ZapDir(szTmp);
  856. }
  857. else
  858. {
  859. bRes = DeleteFile(szTmp);
  860. MYDBGTST(!bRes,("ZapDir() DeleteFile(szTmp=%s) failed, GLE=%u.",szTmp,GetLastError()));
  861. }
  862. }
  863. }
  864. // Go to next file
  865. bRes = FindNextFile(hFind,&wfdData);
  866. if (!bRes)
  867. {
  868. MYDBGTST((GetLastError()!=ERROR_FILE_NOT_FOUND)&&(GetLastError()!=ERROR_NO_MORE_FILES),("ZapDir() FindNextFile() failed, GLE=%u.",GetLastError()));
  869. break;
  870. }
  871. }
  872. bRes = FindClose(hFind);
  873. MYDBGTST(!bRes,("ZapDir() FindClose() failed, GLE=%u.",GetLastError()));
  874. }
  875. // Now that the files have been removed, delete the directory
  876. bRes = RemoveDirectory(pszDir);
  877. MYDBGTST(!bRes&&(GetLastError()!=ERROR_PATH_NOT_FOUND),("ZapDir() RemoveDirectory(pszDir=%s) failed, GLE=%u.",pszDir,GetLastError()));
  878. return (bRes);
  879. }
  880. #ifdef EXTENDED_CAB_CONTENTS
  881. static long MyMsgWaitDlg(HWND hwndMsg, DWORD dwHandles, HANDLE *phHandles, DWORD dwTimeout)
  882. {
  883. long lRes;
  884. if (hwndMsg)
  885. {
  886. HCURSOR hPrev;
  887. MSG msg;
  888. hPrev = SetCursor(LoadCursor(NULL,IDC_WAIT));
  889. ShowCursor(TRUE);
  890. while (1)
  891. {
  892. lRes = MsgWaitForMultipleObjects(dwHandles,phHandles,FALSE,dwTimeout,QS_ALLINPUT);
  893. if (lRes == WAIT_TIMEOUT)
  894. {
  895. break;
  896. }
  897. if (lRes != (long) (WAIT_OBJECT_0+dwHandles))
  898. {
  899. MYDBGTST(-1 == lRes,("MyMsgWaitDlg() MsgWaitForMultipleObjects() failed, GLE=%u.",GetLastError()));
  900. break;
  901. }
  902. PeekMessage(&msg,hwndMsg,0,0,PM_NOREMOVE);
  903. }
  904. ShowCursor(FALSE);
  905. SetCursor(hPrev);
  906. }
  907. else
  908. {
  909. lRes = WaitForMultipleObjects(dwHandles,phHandles,FALSE,dwTimeout);
  910. }
  911. return (lRes);
  912. }
  913. #endif // EXTENDED_CAB_CONTENTS
  914. //
  915. // Executes installation of phone book update based upon download file
  916. //
  917. static BOOL DoInstall(ArgsStruct *pArgs, HWND hwndParent, DWORD dwAppFlags)
  918. {
  919. DWORD dwIdx;
  920. // If no install, we are done
  921. if (dwAppFlags & AF_NO_INSTALL)
  922. {
  923. return (TRUE);
  924. }
  925. // For each arg, handle installation
  926. for (dwIdx=0;dwIdx<pArgs->dwArgsCnt;dwIdx++)
  927. {
  928. DownloadArgs *pdaArgs;
  929. UINT i;
  930. BOOL bInstallOk = FALSE;
  931. BOOL bRes = TRUE;
  932. pdaArgs = pArgs->pdaArgs + dwIdx;
  933. pdaArgs->dwBubbledUpError = 0;
  934. #ifdef EXTENDED_CAB_CONTENTS
  935. BOOL fCabDirRenamed = FALSE;
  936. // rename the dir the downloaded file is not an EXE
  937. if (pdaArgs->szCabDir[0])
  938. {
  939. ZapDir(c_pszDirName);
  940. bRes = MoveFile(pdaArgs->szCabDir,c_pszDirName);
  941. MYDBGTST(!bRes,("DoInstall() MoveFile(szCabDir=%s,c_pszDirName) failed, GLE=%u.",pdaArgs->szCabDir,GetLastError()));
  942. if (bRes)
  943. {
  944. fCabDirRenamed = TRUE;
  945. }
  946. }
  947. #endif // EXTENDED_CAB_CONTENTS
  948. // Only perform if the rename worked.
  949. if (bRes)
  950. {
  951. for (i=0; i<pdaArgs->dwNumFilesToProcess; i++)
  952. {
  953. //
  954. // Reset install flag for each file that is processed,
  955. // otherwise a single success will cause us to interpret
  956. // the entire install as successful. #5887
  957. //
  958. bInstallOk = FALSE;
  959. switch (pdaArgs->rgfpiFileProcessInfo[i].itType)
  960. {
  961. #ifdef EXTENDED_CAB_CONTENTS
  962. case itExeInCab:
  963. case itExe:
  964. {
  965. STARTUPINFO siInfo;
  966. PROCESS_INFORMATION piInfo;
  967. ZeroMemory(&siInfo,sizeof(siInfo));
  968. ZeroMemory(&piInfo,sizeof(piInfo));
  969. siInfo.cb = sizeof(siInfo);
  970. bRes = CreateProcess(pdaArgs->rgfpiFileProcessInfo[i].pszFile,
  971. NULL,NULL,NULL,FALSE,0,NULL,NULL,&siInfo,&piInfo);
  972. MYDBGTST(!bRes,("DoInstall() CreateProcess(pszExe=%s) failed, GLE=%u.",pdaArgs->rgfpiFileProcessInfo[i].pszFile,GetLastError()));
  973. // If CreateProcess worked, wait for process to terminate before continuing
  974. if (bRes)
  975. {
  976. CloseHandle(piInfo.hThread);
  977. MyMsgWaitDlg(hwndParent,1,&piInfo.hProcess,INFINITE);
  978. CloseHandle(piInfo.hProcess);
  979. bInstallOk = TRUE;
  980. }
  981. break;
  982. }
  983. case itInfInCab: // .INF file
  984. {
  985. TCHAR szCabDir[MAX_PATH+1];
  986. DWORD dwRes;
  987. HRESULT hRes;
  988. ZeroMemory(szCabDir,sizeof(szCabDir));
  989. dwRes = GetCurrentDirectory(sizeof(szCabDir)/sizeof(TCHAR)-1,szCabDir);
  990. MYDBGTST(!dwRes,("DoInstall() GetCurrentDirectory() failed, GLE=%u.",GetLastError()));
  991. if (GetLastChar(szCabDir) != '\\')
  992. {
  993. lstrcat(szCabDir,TEXT("\\"));
  994. }
  995. lstrcat(szCabDir,c_pszDirName);
  996. // Since RunSetupCommand() has problems with long file names, we'll
  997. // convert the path just to be sure.
  998. dwRes = GetShortPathName(szCabDir,szCabDir,sizeof(szCabDir)/sizeof(TCHAR)-1);
  999. MYDBGTST(!dwRes,("DoInstall() GetShortPathName() failed, GLE=%u.",GetLastError()));
  1000. // TBD: Initialize pArgs->szInstallTitle from service file instead of from resource.
  1001. LPTSTR pszTmp = CmFmtMsg(pArgs->hInst,IDMSG_PBTITLE);
  1002. lstrcpy(pArgs->szInstallTitle,pszTmp);
  1003. CmFree(pszTmp);
  1004. hRes = MyRunSetupCommand(pArgs,
  1005. hwndParent,
  1006. c_pszInfInDir,
  1007. NULL,
  1008. szCabDir,
  1009. pArgs->szInstallTitle,
  1010. NULL,
  1011. RSC_FLAG_INF,
  1012. NULL);
  1013. if (!HRESULT_SEVERITY(hRes))
  1014. {
  1015. bInstallOk = TRUE;
  1016. }
  1017. break;
  1018. }
  1019. #endif // EXTENDED_CAB_CONTENTS
  1020. case itPbdInCab: // Delta phonebook file
  1021. // if the CAB contains an EXE or an INF, then we don't do PBD
  1022. if (pdaArgs->fContainsExeOrInf)
  1023. {
  1024. continue;
  1025. }
  1026. if (pdaArgs->pszCMSFile)
  1027. {
  1028. HRESULT hRes;
  1029. DWORD_PTR dwPb;
  1030. // Update the Phonebook using API calls
  1031. hRes = PhoneBookLoad(pdaArgs->pszCMSFile, &dwPb);
  1032. MYDBGTST(hRes!=ERROR_SUCCESS,("DoInstall() PhoneBookLoad(pszCMSFile=%s) failed, GLE=%u.", pdaArgs->pszCMSFile, hRes));
  1033. if (hRes == ERROR_SUCCESS)
  1034. {
  1035. #ifdef EXTENDED_CAB_CONTENTS
  1036. hRes = PhoneBookMergeChanges(dwPb, c_pszPbdInDir);
  1037. #else
  1038. //
  1039. // Build path to delta file, to be passed to phonebook merge
  1040. //
  1041. TCHAR szPbd[MAX_PATH+1];
  1042. lstrcpy(szPbd, pdaArgs->szCabDir);
  1043. lstrcat(szPbd, TEXT("\\"));
  1044. lstrcat(szPbd, c_pszPbdFile);
  1045. hRes = PhoneBookMergeChanges(dwPb, szPbd);
  1046. #endif // EXTENDED_CAB_CONTENTS
  1047. MYDBGTST(hRes!=ERROR_SUCCESS,("DoInstall() PhoneBookMergeChanges() failed, GLE=%u.",hRes));
  1048. if (hRes == ERROR_SUCCESS)
  1049. {
  1050. bInstallOk = TRUE;
  1051. }
  1052. else
  1053. {
  1054. pdaArgs->dwBubbledUpError = hRes;
  1055. }
  1056. hRes = PhoneBookUnload(dwPb);
  1057. MYDBGTST(hRes!=ERROR_SUCCESS,("DoInstall() PhoneBookUnload() failed, GLE=%u.",hRes));
  1058. }
  1059. if (!bInstallOk && !(dwAppFlags & AF_NO_VER))
  1060. {
  1061. // We currently zap the version string on any failure. This should cause
  1062. // the phone book to get completely update the next time around.
  1063. WritePrivateProfileString(c_pszCmSection,
  1064. c_pszVersion,
  1065. TEXT(""),
  1066. pdaArgs->pszCMSFile);
  1067. }
  1068. }
  1069. break;
  1070. case itPbkInCab: // Phone book file
  1071. {
  1072. TCHAR szPbk[MAX_PATH+1];
  1073. // if the CAB contains an EXE or an INF, then we don't do PBK
  1074. if (pdaArgs->fContainsExeOrInf)
  1075. {
  1076. continue;
  1077. }
  1078. #ifdef EXTENDED_CAB_CONTENTS
  1079. lstrcpy(szPbk, c_pszDirName);
  1080. #else // EXTENDED_CAB_CONTENTS
  1081. lstrcpy(szPbk, pdaArgs->szCabDir);
  1082. #endif
  1083. lstrcat(szPbk, TEXT("\\"));
  1084. lstrcat(szPbk, pdaArgs->rgfpiFileProcessInfo[i].pszFile);
  1085. // Try to copy the phonebook file directly
  1086. if (!CopyFile(szPbk, pdaArgs->pszPbkFile, FALSE))
  1087. {
  1088. pdaArgs->dwBubbledUpError = GetLastError();
  1089. MYDBG((TEXT("DoInstall() itPbkInCab, CopyFile() failed, GLE=%u."), pdaArgs->dwBubbledUpError));
  1090. }
  1091. else
  1092. {
  1093. bInstallOk = TRUE;
  1094. }
  1095. break;
  1096. }
  1097. case itPbrInCab: // Region file
  1098. {
  1099. TCHAR szPbr[MAX_PATH+1];
  1100. // if the CAB contains an EXE or an INF, then we don't do PBD
  1101. if (pdaArgs->fContainsExeOrInf)
  1102. {
  1103. continue;
  1104. }
  1105. #ifdef EXTENDED_CAB_CONTENTS
  1106. lstrcpy(szPbr, c_pszDirName);
  1107. #else // EXTENDED_CAB_CONTENTS
  1108. lstrcpy(szPbr, pdaArgs->szCabDir);
  1109. #endif
  1110. lstrcat(szPbr, TEXT("\\"));
  1111. lstrcat(szPbr, pdaArgs->rgfpiFileProcessInfo[i].pszFile);
  1112. // Try to copy the region file directly
  1113. if (!CopyFile(szPbr, pdaArgs->pszPbrFile, FALSE))
  1114. {
  1115. MYDBG((TEXT("DoInstall() itPbrInCab, CopyFile() failed, GLE=%u."), GetLastError()));
  1116. }
  1117. else
  1118. {
  1119. bInstallOk = TRUE;
  1120. }
  1121. break;
  1122. }
  1123. #ifdef EXTENDED_CAB_CONTENTS
  1124. case itShlInCab: // Shell execute target
  1125. {
  1126. TCHAR szShl[MAX_PATH+1];
  1127. lstrcpy(szShl,c_pszDirName);
  1128. lstrcat(szShl,TEXT("\\"));
  1129. lstrcat(szShl,pdaArgs->rgfpiFileProcessInfo[i].pszFile);
  1130. SHELLEXECUTEINFO seiInfo;
  1131. ZeroMemory(&seiInfo,sizeof(seiInfo));
  1132. seiInfo.cbSize = sizeof(seiInfo);
  1133. seiInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
  1134. seiInfo.hwnd = hwndParent;
  1135. seiInfo.lpFile = szShl;
  1136. seiInfo.nShow = SW_SHOWNORMAL;
  1137. bRes = ShellExecuteEx(&seiInfo);
  1138. MYDBGTST(!bRes,("DoInstall() ShellExecuteEx(szShl=%s) failed, GLE=%u.",szShl,GetLastError()));
  1139. // If it worked, wait for termination
  1140. if (bRes)
  1141. {
  1142. MyMsgWaitDlg(hwndParent,1,&seiInfo.hProcess,INFINITE);
  1143. CloseHandle(seiInfo.hProcess);
  1144. bInstallOk = TRUE;
  1145. }
  1146. break;
  1147. } // case itShlInCab
  1148. #endif // EXTENDED_CAB_CONTENTS
  1149. } // switch (pdaArgs->rgfpiFileProcessInfo[i].itType)
  1150. } // for (i=0; i<pdaArgs->dwNumFilesToProcess; i++)
  1151. } // if (bRes)
  1152. #ifdef EXTENDED_CAB_CONTENTS
  1153. if (fCabDirRenamed)
  1154. {
  1155. // Copy the Cab directory back to tmp name
  1156. bRes = MoveFile(c_pszDirName,pdaArgs->szCabDir);
  1157. MYDBGTST(!bRes,("DoInstall() MoveFile(c_pszDirName,szCabDir=%s) failed, GLE=%u.",pdaArgs->szCabDir,GetLastError()));
  1158. }
  1159. #endif // EXTENDED_CAB_CONTENTS
  1160. // Update version info in CMS
  1161. if (bInstallOk && !(dwAppFlags & AF_NO_VER) && pdaArgs->pszVerNew && pdaArgs->pszCMSFile)
  1162. {
  1163. WritePrivateProfileString(c_pszCmSection,
  1164. c_pszVersion,
  1165. pdaArgs->pszVerNew,
  1166. pdaArgs->pszCMSFile);
  1167. }
  1168. }
  1169. return (TRUE);
  1170. }
  1171. //+----------------------------------------------------------------------------
  1172. //
  1173. // Func: CheckFileForPBSErrors
  1174. //
  1175. // Desc: Scan the downloaded file for PBS errors
  1176. //
  1177. // Args: [hFile] - handle to the already opened tempfile
  1178. //
  1179. // Return: LONG (0 = no download needed, +ve = PBS error code, -1 = other error)
  1180. //
  1181. // Notes:
  1182. //
  1183. // History: 14-Apr-2001 SumitC Created
  1184. //
  1185. //-----------------------------------------------------------------------------
  1186. static LONG CheckFileForPBSErrors(HANDLE hFile)
  1187. {
  1188. LONG lRet = -1;
  1189. MYDBGASSERT(hFile);
  1190. if (hFile && (INVALID_HANDLE_VALUE != hFile))
  1191. {
  1192. TCHAR szFirstThree[4] = {0};
  1193. DWORD dwBytesRead;
  1194. SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
  1195. if (ReadFile(hFile, szFirstThree, 3, &dwBytesRead, NULL) &&
  1196. (dwBytesRead >= 3))
  1197. {
  1198. if (0 == lstrcmpi(szFirstThree, TEXT("204")))
  1199. {
  1200. //
  1201. // "204" => no download necessary
  1202. //
  1203. lRet = 0;
  1204. }
  1205. else if (0 != lstrcmpi(szFirstThree, TEXT("MSC")))
  1206. {
  1207. //
  1208. // "MSC" => we have a phonebook. If *not* MSC, get the error number
  1209. //
  1210. LONG lVal = 0;
  1211. for (int i = 0 ; i < 3; ++i)
  1212. {
  1213. if ((szFirstThree[i] >= TEXT('0')) && (szFirstThree[i] <= TEXT('9')))
  1214. {
  1215. lVal = (lVal *10) + (szFirstThree[i] - TEXT('0'));
  1216. }
  1217. else
  1218. {
  1219. break;
  1220. }
  1221. }
  1222. if (lVal)
  1223. {
  1224. lRet = lVal;
  1225. }
  1226. }
  1227. }
  1228. }
  1229. return lRet;
  1230. }
  1231. //static unsigned __stdcall InetThreadFunc(void *pvParam)
  1232. DWORD WINAPI InetThreadFunc(void *pvParam)
  1233. {
  1234. EventParam epParam = {(ArgsStruct *) pvParam,0};
  1235. BOOL bRes = FALSE;
  1236. BOOL bSuccess = FALSE;
  1237. DWORD dwFileIdx;
  1238. HANDLE hFile = INVALID_HANDLE_VALUE;
  1239. RASCONN RasConn, *prgRasConn;
  1240. DWORD cb, cConnections;
  1241. PVOID pRasEnumMem = NULL;
  1242. // Wait for delay period to expire
  1243. DWORD dwRes = WaitForSingleObject(epParam.pArgs->ahHandles[1], epParam.pArgs->dwDownloadDelay);
  1244. MYDBGTST(dwRes==WAIT_FAILED,("InetThreadFunc() WaitForMultipleObjects() failed, GLE=%u.",GetLastError()));
  1245. //
  1246. // Check if connection is still valid before starting the download
  1247. // on NT5 we depend on setting the don't autodial flag for InternetSetOptions()
  1248. // Unless, of course, the /LAN flag was specified in which case we don't want
  1249. // this connection check to happen because the caller is telling us this is happening
  1250. // over a LAN connection.
  1251. //
  1252. if (!(epParam.pArgs->dwAppFlags & AF_LAN))
  1253. {
  1254. cb = sizeof(RasConn);
  1255. prgRasConn = &RasConn;
  1256. prgRasConn->dwSize = cb;
  1257. dwRes = RasEnumConnections(prgRasConn, &cb, &cConnections);
  1258. if (dwRes == ERROR_BUFFER_TOO_SMALL)
  1259. {
  1260. pRasEnumMem = CmMalloc(cb);
  1261. if (pRasEnumMem == NULL)
  1262. {
  1263. MYDBG(("InetThreadFunc() aborted. Out of memory"));
  1264. epParam.pArgs->bAbort = TRUE;
  1265. goto done;
  1266. }
  1267. prgRasConn = (RASCONN *) pRasEnumMem;
  1268. prgRasConn[0].dwSize = sizeof(RASCONN);
  1269. dwRes = RasEnumConnections(prgRasConn, &cb, &cConnections);
  1270. }
  1271. //
  1272. // Iterate through connections to check if our's is active
  1273. // if there is a problem getting this list we don't abort?
  1274. //
  1275. if (dwRes == ERROR_SUCCESS)
  1276. {
  1277. DWORD iConn;
  1278. BOOL fConnected = FALSE;
  1279. for (iConn = 0; iConn < cConnections; iConn++)
  1280. {
  1281. if (lstrcmpi(epParam.pArgs->pszServiceName, prgRasConn[iConn].szEntryName) == 0)
  1282. {
  1283. fConnected = TRUE;
  1284. break;
  1285. }
  1286. }
  1287. if (fConnected == FALSE)
  1288. {
  1289. MYDBG(("InetThreadFunc() aborted. No connection"));
  1290. epParam.pArgs->bAbort = TRUE;
  1291. goto done;
  1292. }
  1293. }
  1294. }
  1295. if (epParam.pArgs->bAbort)
  1296. {
  1297. MYDBG(("InetThreadFunc() aborted."));
  1298. }
  1299. for (epParam.dwIdx=0;epParam.dwIdx<epParam.pArgs->dwArgsCnt;epParam.dwIdx++)
  1300. {
  1301. int i = 0;
  1302. UINT uReturn = 0;
  1303. DownloadArgs * pDA = &(epParam.pArgs->pdaArgs[epParam.dwIdx]);
  1304. while (i++ < 3)
  1305. {
  1306. //
  1307. // On Win9x and/or slow machines, GetTempFileName sometimes fails,
  1308. // and cmdl32 errors all the way out. In the debugger, if the call
  1309. // is retried, it will invariably succeed. This sounds like a timing
  1310. // issue with the OS. We do 3 tries, separated by a 1-second sleep.
  1311. //
  1312. uReturn = GetTempFileName(TEXT("."), TEXT("000"), 0, epParam.pArgs->pdaArgs[epParam.dwIdx].szFile);
  1313. if (uReturn)
  1314. {
  1315. break;
  1316. }
  1317. Sleep(1000);
  1318. }
  1319. if (0 == uReturn)
  1320. {
  1321. DWORD dwError = GetLastError();
  1322. MYDBG(("InetThreadFunc() GetTempFileName failed, GLE=%u.", dwError));
  1323. epParam.pArgs->Log.Log(PB_DOWNLOAD_FAILURE, dwError, pDA->pszPhoneBookName, pDA->szHostName);
  1324. goto done;
  1325. }
  1326. else
  1327. {
  1328. hFile = CreateFile(epParam.pArgs->pdaArgs[epParam.dwIdx].szFile,
  1329. GENERIC_READ | GENERIC_WRITE,
  1330. FILE_SHARE_READ,
  1331. NULL,
  1332. CREATE_ALWAYS,
  1333. FILE_ATTRIBUTE_NORMAL,
  1334. NULL);
  1335. if (INVALID_HANDLE_VALUE == hFile)
  1336. {
  1337. DWORD dwError = GetLastError();
  1338. MYDBG(("InetThreadFunc() CreateFile(szFile=%s) failed, GLE=%u.", epParam.pArgs->pdaArgs[epParam.dwIdx].szFile, dwError));
  1339. epParam.pArgs->Log.Log(PB_DOWNLOAD_FAILURE, dwError, pDA->pszPhoneBookName, pDA->szHostName);
  1340. goto done;
  1341. }
  1342. }
  1343. //
  1344. // Check to make sure we haven't been aborted
  1345. //
  1346. if (epParam.pArgs->bAbort)
  1347. {
  1348. MYDBG(("InetThreadFunc() aborted."));
  1349. goto done;
  1350. }
  1351. // We have a valid tmp file name, download phonebook update into it.
  1352. epParam.pArgs->pdaArgs[epParam.dwIdx].pfnEvent = EventFunc;
  1353. epParam.pArgs->pdaArgs[epParam.dwIdx].pvEventParam = &epParam;
  1354. epParam.pArgs->pdaArgs[epParam.dwIdx].pbAbort = &epParam.pArgs->bAbort;
  1355. PostMessage(epParam.pArgs->hwndDlg,epParam.pArgs->nMsgId,etDataBegin,0);
  1356. bRes = DownloadFile(&epParam.pArgs->pdaArgs[epParam.dwIdx],hFile);
  1357. FlushFileBuffers(hFile);
  1358. LONG lResult = CheckFileForPBSErrors(hFile);
  1359. CloseHandle(hFile);
  1360. hFile = INVALID_HANDLE_VALUE;
  1361. if (epParam.pArgs->bAbort)
  1362. {
  1363. MYDBG(("InetThreadFunc() aborted."));
  1364. goto done;
  1365. }
  1366. PostMessage(epParam.pArgs->hwndDlg,epParam.pArgs->nMsgId,etDataEnd,0);
  1367. #if 0
  1368. /*
  1369. if (!bRes && !epParam.dwIdx)
  1370. {
  1371. // TBD: Currently, a failure to update the primary phonebook prevents any
  1372. // secondary phonebooks from being updated. But a failure to update one
  1373. // secondary does not prevent other secondaries from being updated.
  1374. goto done;
  1375. }
  1376. */
  1377. #endif
  1378. //
  1379. // If download failed (either cpserver thinks that we don't need to update
  1380. // the phone book or the phone book doesn't exist on the server), just keep
  1381. // on downloading the phone books for other profiles.
  1382. //
  1383. if (!bRes)
  1384. {
  1385. if (lResult < 0)
  1386. {
  1387. //
  1388. // we parsed the downloaded file and got some error other than
  1389. // the 2 cases handled below
  1390. //
  1391. epParam.pArgs->Log.Log(PB_DOWNLOAD_FAILURE, pDA->dwBubbledUpError, pDA->pszPhoneBookName, pDA->szHostName);
  1392. }
  1393. else
  1394. {
  1395. //
  1396. // we contacted the web server successfully, and...
  1397. //
  1398. epParam.pArgs->Log.Log(PB_DOWNLOAD_SUCCESS, pDA->pszPhoneBookName, pDA->pszVerCurr, pDA->szHostName);
  1399. if (lResult > 0)
  1400. {
  1401. //
  1402. // ... (case 1) the web server or PBS reported an error
  1403. //
  1404. epParam.pArgs->Log.Log(PB_UPDATE_FAILURE_PBS, lResult, pDA->pszPhoneBookName);
  1405. }
  1406. else
  1407. {
  1408. //
  1409. // ... (case 2) PBS said no download necessary
  1410. //
  1411. MYDBGASSERT(0 == lResult);
  1412. LPTSTR pszText = CmFmtMsg(epParam.pArgs->hInst, IDMSG_LOG_NO_UPDATE_REQUIRED);
  1413. epParam.pArgs->Log.Log(PB_UPDATE_SUCCESS,
  1414. SAFE_LOG_ARG(pszText),
  1415. pDA->pszPhoneBookName,
  1416. pDA->pszVerCurr,
  1417. pDA->pszVerCurr, // for no-download case, these are the same
  1418. pDA->szHostName);
  1419. CmFree(pszText);
  1420. }
  1421. }
  1422. continue;
  1423. }
  1424. if (bRes && epParam.pArgs->pdaArgs[epParam.dwIdx].dwTotalSize)
  1425. {
  1426. epParam.pArgs->pdaArgs[epParam.dwIdx].bTransferOk = TRUE;
  1427. }
  1428. if (epParam.pArgs->bAbort)
  1429. {
  1430. MYDBG(("InetThreadFunc() aborted."));
  1431. goto done;
  1432. }
  1433. //
  1434. // Phonebook download was successful, log this and proceed to unpack/update
  1435. //
  1436. epParam.pArgs->Log.Log(PB_DOWNLOAD_SUCCESS, pDA->pszPhoneBookName, pDA->pszVerCurr, pDA->szHostName);
  1437. bRes = ProcessCabinet(&epParam.pArgs->pdaArgs[epParam.dwIdx],epParam.pArgs->dwAppFlags);
  1438. if (bRes && (NULL == pDA->rgfpiFileProcessInfo))
  1439. {
  1440. MYDBGASSERT(FALSE);
  1441. // strange case. set error here so that we log something sensible later
  1442. pDA->dwBubbledUpError = ERROR_INVALID_DATA; // yes. we know this is lame.
  1443. }
  1444. if (bRes && pDA->rgfpiFileProcessInfo)
  1445. {
  1446. //
  1447. // figure out if this was a full or delta download
  1448. //
  1449. BOOL fFoundFullCab = FALSE;
  1450. BOOL fFoundDeltaCab = FALSE;
  1451. for (DWORD dwFileIndex = 0; dwFileIndex < pDA->dwNumFilesToProcess; ++dwFileIndex)
  1452. {
  1453. switch (pDA->rgfpiFileProcessInfo[dwFileIndex].itType)
  1454. {
  1455. case itPbkInCab:
  1456. fFoundFullCab = TRUE;
  1457. break;
  1458. case itPbdInCab:
  1459. fFoundDeltaCab = TRUE;
  1460. break;
  1461. }
  1462. }
  1463. if (fFoundFullCab ^ fFoundDeltaCab)
  1464. {
  1465. // the cab should contain one or the other, but not both
  1466. LPTSTR pszTemp = NULL;
  1467. if (fFoundFullCab)
  1468. {
  1469. pszTemp = CmFmtMsg(epParam.pArgs->hInst, IDMSG_LOG_FULL_UPDATE);
  1470. }
  1471. else if (fFoundDeltaCab)
  1472. {
  1473. pszTemp = CmFmtMsg(epParam.pArgs->hInst, IDMSG_LOG_DELTA_UPDATE);
  1474. }
  1475. MYDBGASSERT(pszTemp);
  1476. if (pszTemp)
  1477. {
  1478. epParam.pArgs->Log.Log(PB_UPDATE_SUCCESS,
  1479. SAFE_LOG_ARG(pszTemp),
  1480. pDA->pszPhoneBookName,
  1481. pDA->pszVerCurr,
  1482. pDA->pszVerNew,
  1483. pDA->szHostName);
  1484. CmFree(pszTemp);
  1485. }
  1486. }
  1487. else
  1488. {
  1489. // strange cab (or at least, doesn't contain what we expected)
  1490. // both full and delta
  1491. CMASSERTMSG(!(fFoundFullCab && fFoundDeltaCab), TEXT("This cab has both full and delta phonebooks!!"));
  1492. // neither full nor delta
  1493. CMASSERTMSG(! (!fFoundFullCab && !fFoundDeltaCab), TEXT("This cab has neither a full nor a delta phonebook!!"));
  1494. pDA->dwBubbledUpError = ERROR_BAD_FORMAT;
  1495. epParam.pArgs->Log.Log(PB_UPDATE_FAILURE_CMPBK, pDA->dwBubbledUpError, pDA->pszPhoneBookName);
  1496. }
  1497. }
  1498. else
  1499. {
  1500. epParam.pArgs->Log.Log(PB_UPDATE_FAILURE_CMPBK, pDA->dwBubbledUpError, pDA->pszPhoneBookName);
  1501. }
  1502. if (!bRes)
  1503. {
  1504. goto done;
  1505. }
  1506. bSuccess = TRUE; // We have at least one successful download #5635
  1507. #if 0
  1508. /*
  1509. if (!epParam.dwIdx &&
  1510. epParam.pArgs->pdaArgs[epParam.dwIdx].dwTotalSize &&
  1511. (epParam.pArgs->pdaArgs[epParam.dwIdx].itType != itInvalid) &&
  1512. (epParam.pArgs->pdaArgs[epParam.dwIdx].itType != itPbdInCab))
  1513. {
  1514. // TBD: Currently, if the primary service is being updated in any way other than
  1515. // a simple phone number delta, we do *not* update any of the secondary phonebooks
  1516. // this time around.
  1517. break;
  1518. }
  1519. */
  1520. #endif
  1521. }
  1522. //
  1523. // If no download attempts succeeded, bail completely
  1524. //
  1525. if (!bSuccess)
  1526. {
  1527. MYDBG(("InetThreadFunc() no download success."));
  1528. goto done;
  1529. }
  1530. if (epParam.pArgs->bAbort)
  1531. {
  1532. MYDBG(("InetThreadFunc() aborted."));
  1533. goto done;
  1534. }
  1535. #ifdef EXTENDED_CAB_CONTENTS
  1536. // At this point, all of the downloads are complete. We post a message to the main
  1537. // window, asking it to call WinVerifyTrust() as appropriate for all of the downloaded
  1538. // blobs. The main window will post the event back to us when it is done.
  1539. PostMessage(epParam.pArgs->hwndDlg,epParam.pArgs->nMsgId,etVerifyTrust,0);
  1540. dwRes = WaitForSingleObject(epParam.pArgs->ahHandles[IDX_EVENT_HANDLE],INFINITE);
  1541. if (epParam.pArgs->bAbort)
  1542. {
  1543. MYDBG(("InetThreadFunc() aborted."));
  1544. goto done;
  1545. }
  1546. #endif // EXTENDED_CAB_CONTENTS
  1547. // At this point, everything is all set - we're ready to perform the actual installs. So
  1548. // send a message to the main window telling it to do the installs, and wait until it
  1549. // signals success back.
  1550. PostMessage(epParam.pArgs->hwndDlg,epParam.pArgs->nMsgId,etInstall,0);
  1551. dwRes = WaitForSingleObject(epParam.pArgs->ahHandles[IDX_EVENT_HANDLE],INFINITE);
  1552. if (epParam.pArgs->bAbort)
  1553. {
  1554. MYDBG(("InetThreadFunc() aborted."));
  1555. goto done;
  1556. }
  1557. SetLastError(ERROR_SUCCESS);
  1558. done:
  1559. if (epParam.pArgs->bAbort)
  1560. {
  1561. epParam.pArgs->Log.Log(PB_ABORTED);
  1562. }
  1563. if (hFile != INVALID_HANDLE_VALUE)
  1564. {
  1565. CloseHandle(hFile);
  1566. }
  1567. if (pRasEnumMem != NULL)
  1568. {
  1569. CmFree(pRasEnumMem);
  1570. }
  1571. PostMessage(epParam.pArgs->hwndDlg,epParam.pArgs->nMsgId,etDone,0);
  1572. return (GetLastError());
  1573. }
  1574. //
  1575. // The main dlg
  1576. //
  1577. BOOL CALLBACK MainDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1578. {
  1579. ArgsStruct *pArgs = (ArgsStruct *) GetWindowLongPtr(hwndDlg,DWLP_USER);
  1580. static UINT uTimerID = 0;
  1581. switch (uMsg)
  1582. {
  1583. case WM_INITDIALOG:
  1584. {
  1585. RECT rDlg;
  1586. RECT rWorkArea;
  1587. DWORD dwThreadId = 0;
  1588. SetWindowLongPtr(hwndDlg,DWLP_USER,(LONG_PTR)lParam);
  1589. pArgs = (ArgsStruct *) lParam;
  1590. pArgs->hwndDlg = hwndDlg;
  1591. MYDBG(("MainDlgProc() - WM_INITDIALOG."));
  1592. // Get the dialog rect and the available work area.
  1593. GetWindowRect(hwndDlg,&rDlg);
  1594. if (SystemParametersInfoA(SPI_GETWORKAREA,0,&rWorkArea,0))
  1595. {
  1596. // Move the dialog to the bottom right of the screen
  1597. MoveWindow(hwndDlg,
  1598. rWorkArea.left + ((rWorkArea.right-rWorkArea.left) - (rDlg.right-rDlg.left) - GetSystemMetrics(SM_CXBORDER)),
  1599. rWorkArea.top + ((rWorkArea.bottom-rWorkArea.top) - (rDlg.bottom-rDlg.top) - GetSystemMetrics(SM_CYBORDER)),
  1600. rDlg.right-rDlg.left,
  1601. rDlg.bottom-rDlg.top,
  1602. FALSE);
  1603. }
  1604. // Get update message from ini
  1605. if (pArgs->pszProfile)
  1606. {
  1607. TCHAR szTmp1[MAX_PATH+1];
  1608. TCHAR szTmp2[MAX_PATH+1];
  1609. GetDlgItemText(hwndDlg,IDC_MAIN_MESSAGE,szTmp2,sizeof(szTmp2)/sizeof(TCHAR)-1);
  1610. GetPrivateProfileString(c_pszCmSection,
  1611. c_pszCmEntryPbUpdateMessage,
  1612. szTmp2,
  1613. szTmp1,
  1614. sizeof(szTmp1)/sizeof(TCHAR)-1,
  1615. pArgs->pdaArgs->pszCMSFile);
  1616. SetDlgItemText(hwndDlg,IDC_MAIN_MESSAGE,szTmp1);
  1617. }
  1618. // Spin download thread (InetThreadFunc)
  1619. pArgs->dwHandles = sizeof(pArgs->ahHandles) / sizeof(pArgs->ahHandles[0]);
  1620. pArgs->ahHandles[IDX_EVENT_HANDLE] = CreateEvent(NULL,FALSE,FALSE,NULL);
  1621. if (!pArgs->ahHandles[IDX_EVENT_HANDLE])
  1622. {
  1623. MYDBG(("MainDlgProc() CreateEvent() failed, GLE=%u.",GetLastError()));
  1624. EndDialog(hwndDlg,FALSE);
  1625. }
  1626. //pArgs->ahHandles[IDX_INETTHREAD_HANDLE] = (HANDLE) _beginthreadex(NULL,0,InetThreadFunc,pArgs,0,&nThreadId);
  1627. pArgs->ahHandles[IDX_INETTHREAD_HANDLE] = (HANDLE) CreateThread(0,0,InetThreadFunc,pArgs,0,&dwThreadId);
  1628. if (!pArgs->ahHandles[IDX_INETTHREAD_HANDLE])
  1629. {
  1630. MYDBG(("MainDlgProc() CreateThread() failed, GLE=%u.",GetLastError()));
  1631. EndDialog(hwndDlg,FALSE);
  1632. }
  1633. SetFocus((HWND) wParam);
  1634. return (FALSE);
  1635. }
  1636. case WM_WINDOWPOSCHANGING:
  1637. // Until we set pArgs->bShow to TRUE, we prevent the window from
  1638. // ever being shown.
  1639. if (!pArgs->bShow && (((LPWINDOWPOS) lParam)->flags & SWP_SHOWWINDOW))
  1640. {
  1641. ((LPWINDOWPOS) lParam)->flags &= ~SWP_SHOWWINDOW;
  1642. ((LPWINDOWPOS) lParam)->flags |= SWP_HIDEWINDOW;
  1643. }
  1644. break;
  1645. case WM_INITMENUPOPUP:
  1646. {
  1647. HMENU hMenu = (HMENU) wParam;
  1648. // UINT nPos = (UINT) LOWORD(lParam);
  1649. BOOL fSysMenu = (BOOL) HIWORD(lParam);
  1650. if (fSysMenu)
  1651. {
  1652. EnableMenuItem(hMenu,SC_MAXIMIZE,MF_BYCOMMAND|MF_GRAYED);
  1653. }
  1654. break;
  1655. }
  1656. case WM_DESTROY:
  1657. {
  1658. // Kill timer if we have one
  1659. if (uTimerID)
  1660. {
  1661. KillTimer(hwndDlg, uTimerID);
  1662. }
  1663. // If we have args, set bAbort true
  1664. if (pArgs)
  1665. {
  1666. pArgs->bAbort = TRUE;
  1667. }
  1668. else
  1669. {
  1670. MYDBGASSERT(FALSE); // should not happen if dailog loads
  1671. }
  1672. break;
  1673. }
  1674. default:
  1675. break;
  1676. }
  1677. // Check for custom messages
  1678. if (pArgs && (uMsg == pArgs->nMsgId))
  1679. {
  1680. LPTSTR pszMsg;
  1681. MYDBG(("Custom arg - %u received.", (DWORD) wParam));
  1682. //
  1683. // Setup FirstEvent time for tracking delays
  1684. //
  1685. if (!pArgs->dwFirstEventTime)
  1686. {
  1687. pArgs->dwFirstEventTime = GetTickCount();
  1688. MYDBG(("Setting FirstEventTime to %u.", pArgs->dwFirstEventTime));
  1689. }
  1690. if (!pArgs->bShow && (GetTickCount() - pArgs->dwFirstEventTime > pArgs->dwHideDelay))
  1691. {
  1692. MYDBG(("HideDelay of %u expired, displaying dlg now.", pArgs->dwHideDelay));
  1693. pArgs->bShow = TRUE;
  1694. ShowWindow(hwndDlg,SW_SHOWNA);
  1695. }
  1696. // Handle specific message
  1697. switch (wParam)
  1698. {
  1699. case etDataBegin:
  1700. pArgs->dwDataStepSize = 0;
  1701. SendDlgItemMessage(hwndDlg,IDC_MAIN_PROGRESS,PBM_SETRANGE,0,MAKELPARAM(0,100));
  1702. SendDlgItemMessage(hwndDlg,IDC_MAIN_PROGRESS,PBM_SETPOS,0,0);
  1703. pszMsg = CmFmtMsg(pArgs->hInst,IDMSG_PERCENT_COMPLETE,0);
  1704. SetWindowText(hwndDlg,pszMsg);
  1705. CmFree(pszMsg);
  1706. break;
  1707. case etDataReceived:
  1708. if (pArgs->dwDataTotal) // PREVENT DIVIDE BY ZERO
  1709. {
  1710. if (!pArgs->dwDataStepSize )
  1711. {
  1712. //
  1713. // Progress controls have a limit to there maximum
  1714. // integral value so calculate an aproximate step size.
  1715. //
  1716. //
  1717. pArgs->dwDataStepSize = (pArgs->dwDataTotal / 65535) + 1;
  1718. SendDlgItemMessage(hwndDlg,
  1719. IDC_MAIN_PROGRESS,
  1720. PBM_SETRANGE,
  1721. 0,
  1722. MAKELPARAM(0,pArgs->dwDataTotal/pArgs->dwDataStepSize));
  1723. }
  1724. if (pArgs->dwDataStepSize)
  1725. {
  1726. SendDlgItemMessage(hwndDlg,IDC_MAIN_PROGRESS,PBM_SETPOS,(WORD) (pArgs->dwDataCompleted / pArgs->dwDataStepSize),0);
  1727. pszMsg = CmFmtMsg(pArgs->hInst,IDMSG_PERCENT_COMPLETE,(pArgs->dwDataCompleted*100)/pArgs->dwDataTotal);
  1728. SetWindowText(hwndDlg,pszMsg);
  1729. CmFree(pszMsg);
  1730. }
  1731. }
  1732. break;
  1733. case etDataEnd:
  1734. pszMsg = CmFmtMsg(pArgs->hInst,IDMSG_PERCENT_COMPLETE,100);
  1735. SetWindowText(hwndDlg,pszMsg);
  1736. CmFree(pszMsg);
  1737. break;
  1738. #ifdef EXTENDED_CAB_CONTENTS
  1739. case etVerifyTrust:
  1740. {
  1741. DWORD dwIdx;
  1742. UINT i;
  1743. for (dwIdx=0;dwIdx<pArgs->dwArgsCnt;dwIdx++)
  1744. {
  1745. DownloadArgs *pdaArgs;
  1746. LONG lRes = ERROR_INVALID_PARAMETER;
  1747. WCHAR szPath[MAX_PATH+1];
  1748. GUID gCabSubjectType = WIN_TRUST_SUBJTYPE_CABINET;
  1749. GUID gExeSubjectType = WIN_TRUST_SUBJTYPE_PE_IMAGE;
  1750. WIN_TRUST_SUBJECT_FILE sSubject = {INVALID_HANDLE_VALUE,szPath};
  1751. GUID gActionID = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
  1752. WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT sActionData = {NULL,&gCabSubjectType,&sSubject};
  1753. int iRes;
  1754. BOOL fStandaloneExe;
  1755. pdaArgs = pArgs->pdaArgs + dwIdx;
  1756. ZeroMemory(szPath,sizeof(szPath));
  1757. pszMsg = CmFmtMsg(pArgs->hInst,IDMSG_PBTITLEMSG);
  1758. iRes = MultiByteToWideChar(CP_OEMCP,0,pszMsg,-1,szPath,sizeof(szPath)/sizeof(WCHAR)-1);
  1759. MYDBGTST(!iRes,("MainDlgProc() MultiByteToWideChar() failed, GLE=%u.",GetLastError()));
  1760. CmFree(pszMsg);
  1761. fStandaloneExe = (pdaArgs->dwNumFilesToProcess == 1 &&
  1762. pdaArgs->rgfpiFileProcessInfo[0].itType == itExe);
  1763. if (fStandaloneExe || pdaArgs->fContainsExeOrInf || pdaArgs->fContainsShl)
  1764. {
  1765. HRESULT hRes;
  1766. if (fStandaloneExe)
  1767. sActionData.SubjectType = &gExeSubjectType;
  1768. #ifdef DEBUG
  1769. if (!(pArgs->dwAppFlags & AF_NO_VERIFY))
  1770. {
  1771. #endif
  1772. sSubject.hFile = CreateFile(pdaArgs->szFile,
  1773. GENERIC_READ,
  1774. FILE_SHARE_READ,
  1775. NULL,
  1776. OPEN_EXISTING,
  1777. 0,
  1778. NULL);
  1779. MYDBGTST(sSubject.hFile==INVALID_HANDLE_VALUE,("MainDlgProc() CreateFile(szFile=%s) failed, GLE=%u.",pdaArgs->szFile,GetLastError()));
  1780. if (sSubject.hFile != INVALID_HANDLE_VALUE)
  1781. {
  1782. //
  1783. // Now that we know we're going to do something, show the window #6335
  1784. //
  1785. pArgs->bShow = TRUE;
  1786. ShowWindow(hwndDlg,SW_SHOWNA);
  1787. //
  1788. // Perform verification
  1789. //
  1790. hRes = WinVerifyTrust(hwndDlg,&gActionID,&sActionData);
  1791. if (!HRESULT_SEVERITY(hRes))
  1792. {
  1793. lRes = ERROR_SUCCESS;
  1794. }
  1795. else
  1796. {
  1797. MYDBG(("MainDlgProc() WinVerifyTrust(pszFile=%s) failed, GLE=%u.",pdaArgs->szFile,hRes));
  1798. lRes = HRESULT_CODE(hRes);
  1799. }
  1800. CloseHandle(sSubject.hFile);
  1801. }
  1802. #ifdef DEBUG
  1803. }
  1804. else
  1805. {
  1806. lRes = ERROR_SUCCESS;
  1807. }
  1808. #endif
  1809. }
  1810. else // we don't do signing of other files
  1811. lRes = ERROR_SUCCESS;
  1812. if (lRes != ERROR_SUCCESS)
  1813. {
  1814. // pdaArgs->itType = itInvalid;
  1815. pArgs->bAbort = TRUE;
  1816. }
  1817. }
  1818. #ifdef EXTENDED_CAB_CONTENTS
  1819. pArgs->bVerified = TRUE;
  1820. #endif // EXTENDED_CAB_CONTENTS
  1821. ShowWindow(hwndDlg,SW_HIDE);
  1822. SetEvent(pArgs->ahHandles[IDX_EVENT_HANDLE]);
  1823. break;
  1824. }
  1825. #endif // EXTENDED_CAB_CONTENTS
  1826. case etInstall:
  1827. {
  1828. CNamedMutex PbMutex;
  1829. //
  1830. // Hide the window, we're ready to install
  1831. //
  1832. pArgs->bShow = TRUE;
  1833. ShowWindow(hwndDlg,SW_HIDE);
  1834. //
  1835. // Grab the mutex before we begin PB updates. If it fails then
  1836. // abort the install, we'll try again next time the user connects.
  1837. if (PbMutex.Lock(c_pszCMPhoneBookMutex))
  1838. {
  1839. DoInstall(pArgs,hwndDlg,pArgs->dwAppFlags);
  1840. PbMutex.Unlock();
  1841. }
  1842. SetEvent(pArgs->ahHandles[IDX_EVENT_HANDLE]);
  1843. ShowWindow(hwndDlg,SW_HIDE);
  1844. break;
  1845. }
  1846. case etDone:
  1847. EndDialog(hwndDlg,TRUE);
  1848. break;
  1849. case etICMTerm:
  1850. #ifdef EXTENDED_CAB_CONTENTS
  1851. if (!pArgs->bVerified)
  1852. {
  1853. pArgs->bAbort = TRUE;
  1854. EndDialog(hwndDlg,FALSE);
  1855. }
  1856. #endif // EXTENDED_CAB_CONTENTS
  1857. SetEvent(pArgs->ahHandles[IDX_EVENT_HANDLE]);
  1858. break;
  1859. }
  1860. }
  1861. return (FALSE);
  1862. }
  1863. static void AddToUrl(LPTSTR pszUrl, LPTSTR pszVersion, LPTSTR pszService)
  1864. {
  1865. TCHAR szHttpstr[MAX_PATH];
  1866. TCHAR szChar[16];
  1867. int i,len;
  1868. if (!CmStrchr(pszUrl,'?'))
  1869. {
  1870. lstrcat(pszUrl,TEXT("?"));
  1871. }
  1872. else
  1873. {
  1874. if (pszUrl[lstrlen(pszUrl)-1] != '&')
  1875. {
  1876. lstrcat(pszUrl,TEXT("&"));
  1877. }
  1878. }
  1879. // TBD Maybe get more info to send to the server. We currently send
  1880. // OSArch, OSType, LCID, OSVer, CMVer, PBVer, and ServiceName.
  1881. SYSTEM_INFO siInfo;
  1882. OSVERSIONINFO oviInfo;
  1883. GetSystemInfo(&siInfo);
  1884. ZeroMemory(&oviInfo,sizeof(oviInfo));
  1885. oviInfo.dwOSVersionInfoSize = sizeof(oviInfo);
  1886. GetVersionEx(&oviInfo);
  1887. // #pragma message("ALERT - Resolution required - need to remove ISBU_VERSION." __FILE__)
  1888. wsprintf(pszUrl+lstrlen(pszUrl),
  1889. TEXT("OSArch=%u&OSType=%u&LCID=%u&OSVer=%u.%u.%u&CMVer=%s"),
  1890. siInfo.wProcessorArchitecture,
  1891. oviInfo.dwPlatformId,
  1892. ConvertDefaultLocale(LOCALE_SYSTEM_DEFAULT),
  1893. oviInfo.dwMajorVersion,
  1894. oviInfo.dwMinorVersion,
  1895. (oviInfo.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)?LOWORD(oviInfo.dwBuildNumber):oviInfo.dwBuildNumber,
  1896. VER_PRODUCTVERSION_STR);
  1897. if (pszVersion && *pszVersion)
  1898. {
  1899. wsprintf(pszUrl+lstrlen(pszUrl),TEXT("&PBVer=%s"),pszVersion);
  1900. }
  1901. if (pszService && *pszService)
  1902. {
  1903. // replace spaces with %20 for HTTP - 10216
  1904. len = strlen(pszService);
  1905. szHttpstr[0] = 0;
  1906. szChar[1] = 0;
  1907. for (i=0; i<len; ++i)
  1908. {
  1909. if (pszService[i] == ' ')
  1910. {
  1911. lstrcat(szHttpstr,"%20");
  1912. }
  1913. else
  1914. {
  1915. szChar[0] = pszService[i];
  1916. lstrcat(szHttpstr,szChar);
  1917. }
  1918. }
  1919. wsprintf(pszUrl+lstrlen(pszUrl),TEXT("&PB=%s"),szHttpstr);
  1920. }
  1921. }
  1922. static BOOL WINAPI RefFunc(LPCTSTR pszFile,
  1923. LPCTSTR pszURL,
  1924. PPBFS , // pFilterA,
  1925. PPBFS , // pFilterB,
  1926. DWORD_PTR dwParam)
  1927. {
  1928. ArgsStruct *pArgs = (ArgsStruct *) dwParam;
  1929. DownloadArgs *pdaArgsTmp;
  1930. TCHAR szTmp[MAX_PATH+1];
  1931. BOOL bOk = FALSE;
  1932. LPTSTR pszSlash;
  1933. LPTSTR pszDot;
  1934. pdaArgsTmp = (DownloadArgs *) CmRealloc(pArgs->pdaArgs,(pArgs->dwArgsCnt+1)*sizeof(DownloadArgs));
  1935. if (pdaArgsTmp)
  1936. {
  1937. pArgs->pdaArgs = pdaArgsTmp;
  1938. pdaArgsTmp += pArgs->dwArgsCnt;
  1939. pdaArgsTmp->pszCMSFile = CmStrCpyAlloc(pszFile);
  1940. if (pdaArgsTmp->pszCMSFile)
  1941. {
  1942. // If get the version number from the CMS file
  1943. GetPrivateProfileString(c_pszCmSection,
  1944. c_pszVersion,
  1945. TEXT(""),
  1946. szTmp,
  1947. (sizeof(szTmp)/sizeof(TCHAR))-1,
  1948. pdaArgsTmp->pszCMSFile);
  1949. pdaArgsTmp->pszVerCurr = CmStrCpyAlloc(szTmp);
  1950. // get the PBK filename from the CMS file
  1951. GetPrivateProfileString(c_pszCmSectionIsp,
  1952. c_pszCmEntryIspPbFile,
  1953. TEXT(""),
  1954. szTmp,
  1955. sizeof(szTmp)/sizeof(TCHAR)-1,
  1956. pdaArgsTmp->pszCMSFile);
  1957. pdaArgsTmp->pszPbkFile = CmStrCpyAlloc(szTmp);
  1958. // get the PDR filename from the CMS file
  1959. GetPrivateProfileString(c_pszCmSectionIsp,
  1960. c_pszCmEntryIspRegionFile,
  1961. TEXT(""),
  1962. szTmp,
  1963. sizeof(szTmp)/sizeof(TCHAR)-1,
  1964. pdaArgsTmp->pszCMSFile);
  1965. pdaArgsTmp->pszPbrFile = CmStrCpyAlloc(szTmp);
  1966. // get the phone book name
  1967. if (!(pszSlash = CmStrrchr(pdaArgsTmp->pszPbkFile, TEXT('\\'))))
  1968. {
  1969. MYDBG((TEXT("RefFunc() bad PBK FILE - no backslash.")));
  1970. goto parse_err;
  1971. }
  1972. if (!(pszDot = CmStrchr(pszSlash, TEXT('.'))))
  1973. {
  1974. MYDBG((TEXT("Reffunc() bad PBK FILE - no dot.")));
  1975. goto parse_err;
  1976. }
  1977. *pszDot = TEXT('\0');
  1978. if (!(pdaArgsTmp->pszPhoneBookName = CmStrCpyAlloc(pszSlash+1)))
  1979. {
  1980. MYDBG((TEXT("Reffunc() out of memory.")));
  1981. }
  1982. // restore the slash
  1983. *pszDot = TEXT('.');
  1984. goto next_param;
  1985. parse_err:
  1986. pdaArgsTmp->pszPhoneBookName = CmStrCpyAlloc(TEXT(""));
  1987. next_param:
  1988. if (pdaArgsTmp->pszVerCurr)
  1989. {
  1990. // Build URL with version number and service name
  1991. pdaArgsTmp->pszUrl = (LPTSTR) CmMalloc((INTERNET_MAX_URL_LENGTH+1)*sizeof(TCHAR));
  1992. if (pdaArgsTmp->pszUrl)
  1993. {
  1994. lstrcpy(pdaArgsTmp->pszUrl,pszURL);
  1995. AddToUrl(pdaArgsTmp->pszUrl,pdaArgsTmp->pszVerCurr,pdaArgsTmp->pszPhoneBookName);
  1996. pArgs->dwArgsCnt++;
  1997. bOk = TRUE;
  1998. }
  1999. }
  2000. }
  2001. }
  2002. // Cleanup
  2003. if (!bOk && pdaArgsTmp)
  2004. {
  2005. CmFreeIndirect(&pdaArgsTmp->pszCMSFile);
  2006. CmFreeIndirect(&pdaArgsTmp->pszVerCurr);
  2007. CmFreeIndirect(&pdaArgsTmp->pszUrl);
  2008. }
  2009. return (TRUE);
  2010. }
  2011. //
  2012. // cmmgr32.exe passes cmdl32.exe the cmp filename in full path.
  2013. //
  2014. static BOOL InitArgs(ArgsStruct *pArgs)
  2015. {
  2016. static struct
  2017. {
  2018. LPTSTR pszFlag;
  2019. DWORD dwFlag;
  2020. } asFlags[] = {{TEXT("/no_delete"),AF_NO_DELETE},
  2021. {TEXT("/no_install"),AF_NO_INSTALL},
  2022. #ifdef DEBUG
  2023. {TEXT("/no_verify"),AF_NO_VERIFY},
  2024. #endif
  2025. {TEXT("/url"),AF_URL},
  2026. {TEXT("/no_profile"),AF_NO_PROFILE},
  2027. {TEXT("/no_exe"),AF_NO_EXE},
  2028. {TEXT("/no_exeincab"),AF_NO_EXEINCAB},
  2029. {TEXT("/no_infincab"),AF_NO_INFINCAB},
  2030. {TEXT("/no_pbdincab"),AF_NO_PBDINCAB},
  2031. {TEXT("/no_shlincab"),AF_NO_SHLINCAB},
  2032. {TEXT("/no_ver"),AF_NO_VER},
  2033. {TEXT("/LAN"),AF_LAN},
  2034. {TEXT("/VPN"),AF_VPN},
  2035. {NULL,0}};
  2036. DWORD dwIdx;
  2037. BOOL bInUrl;
  2038. LPTSTR pszUrl = NULL;
  2039. BOOL bRes = FALSE;
  2040. TCHAR szPath[MAX_PATH+1];
  2041. DWORD dwRes;
  2042. // LPTSTR pszFileInPath;
  2043. //
  2044. // Get simulated ArgV
  2045. //
  2046. LPTSTR pszCmdLine = CmStrCpyAlloc(GetCommandLine());
  2047. LPTSTR *ppszArgv = GetCmArgV(pszCmdLine);
  2048. if (!ppszArgv || !ppszArgv[0])
  2049. {
  2050. MYDBG(("InitArgs() invalid parameter."));
  2051. goto done;
  2052. }
  2053. //
  2054. // Proces arguments
  2055. //
  2056. bInUrl = FALSE;
  2057. for (dwIdx=1;ppszArgv[dwIdx];dwIdx++)
  2058. {
  2059. DWORD dwFlagIdx;
  2060. for (dwFlagIdx=0;asFlags[dwFlagIdx].pszFlag;dwFlagIdx++)
  2061. {
  2062. if (lstrcmpi(asFlags[dwFlagIdx].pszFlag,ppszArgv[dwIdx]) == 0)
  2063. {
  2064. if (bInUrl)
  2065. {
  2066. MYDBG(("InitArgs() URL expected after AF_URL flag."));
  2067. goto done;
  2068. }
  2069. switch (asFlags[dwFlagIdx].dwFlag)
  2070. {
  2071. case AF_URL:
  2072. bInUrl = TRUE;
  2073. break;
  2074. case AF_NO_PROFILE:
  2075. if (pArgs->pszProfile)
  2076. {
  2077. MYDBG(("InitArgs() argument number %u (%s) is invalid.",dwIdx,ppszArgv[dwIdx]));
  2078. goto done;
  2079. }
  2080. // fall through
  2081. default:
  2082. pArgs->dwAppFlags |= asFlags[dwFlagIdx].dwFlag;
  2083. break;
  2084. }
  2085. break;
  2086. }
  2087. }
  2088. if (!asFlags[dwFlagIdx].pszFlag)
  2089. {
  2090. if (bInUrl)
  2091. {
  2092. if (pszUrl)
  2093. {
  2094. MYDBG(("InitArgs() argument number %u (%s) is invalid.",dwIdx,ppszArgv[dwIdx]));
  2095. goto done;
  2096. }
  2097. bInUrl = FALSE;
  2098. pszUrl = (LPTSTR) CmMalloc((INTERNET_MAX_URL_LENGTH+1)*sizeof(TCHAR));
  2099. if (!pszUrl)
  2100. {
  2101. goto done;
  2102. }
  2103. lstrcpy(pszUrl,ppszArgv[dwIdx]);
  2104. }
  2105. else
  2106. {
  2107. if (pArgs->pszProfile || (pArgs->dwAppFlags & AF_NO_PROFILE))
  2108. {
  2109. MYDBG(("InitArgs() argument number %u (%s) is invalid.",dwIdx,ppszArgv[dwIdx]));
  2110. goto done;
  2111. }
  2112. /*
  2113. ZeroMemory(szPath,sizeof(szPath));
  2114. dwRes = GetFullPathName(ppszArgv[dwIdx],sizeof(szPath)/sizeof(TCHAR)-1,szPath,&pszFileInPath);
  2115. MYDBGTST(!dwRes,("InitArgs() GetFullPathName() failed, GLE=%u.",GetLastError()));
  2116. */
  2117. //
  2118. // the cmp filename is always in full path.
  2119. //
  2120. lstrcpy(szPath, ppszArgv[dwIdx]);
  2121. pArgs->pszProfile = CmStrCpyAlloc(szPath);
  2122. if (!pArgs->pszProfile)
  2123. {
  2124. goto done;
  2125. }
  2126. else
  2127. {
  2128. //
  2129. // Set the current dir to the profile dir
  2130. // If the szPath contains only the file name, then
  2131. // assume that the current dir is the profile dir
  2132. //
  2133. char *pszTemp = NULL;
  2134. pszTemp = CmStrrchr(szPath, TEXT('\\'));
  2135. if (NULL != pszTemp)
  2136. {
  2137. *pszTemp = TEXT('\0');
  2138. MYVERIFY(SetCurrentDirectory(szPath));
  2139. }
  2140. }
  2141. }
  2142. }
  2143. }
  2144. ////////////////////////////////////////////////////////////////////////////////////////////
  2145. if (pArgs->dwAppFlags & AF_VPN)
  2146. {
  2147. //
  2148. // They have asked for a VPN download. Let's make sure that the only other flags
  2149. // they have specified are /LAN or /NO_DELETE
  2150. //
  2151. DWORD dwAllowedFlags = AF_VPN | AF_LAN | AF_NO_DELETE;
  2152. if ((dwAllowedFlags | pArgs->dwAppFlags) != dwAllowedFlags)
  2153. {
  2154. CMASSERTMSG(FALSE, TEXT("InitArgs in cmdl32.exe -- VPN flag specified with other non supported flags, exiting."));
  2155. goto done;
  2156. }
  2157. bRes = TRUE;
  2158. CMTRACE(TEXT("InitArgs - /VPN flag detected going into VPN file download mode."));
  2159. goto done;
  2160. }
  2161. ////////////////////////////////////////////////////////////////////////////////////////////
  2162. if (bInUrl)
  2163. {
  2164. MYDBG(("InitArgs() URL expected after AF_URL flag."));
  2165. goto done;
  2166. }
  2167. if (!pArgs->pszProfile && !(pArgs->dwAppFlags & AF_NO_PROFILE))
  2168. {
  2169. MYDBG(("InitArgs() must use AF_NO_PROFILE if no profile given on command line."));
  2170. goto done;
  2171. }
  2172. if (pArgs->pszProfile && pszUrl)
  2173. {
  2174. MYDBG(("InitArgs() can't give both a profile and a URL on the command line."));
  2175. goto done;
  2176. }
  2177. pArgs->pdaArgs = (DownloadArgs *) CmMalloc(sizeof(DownloadArgs));
  2178. if (!pArgs->pdaArgs)
  2179. {
  2180. goto done;
  2181. }
  2182. pArgs->dwArgsCnt++;
  2183. if (!pszUrl)
  2184. {
  2185. TCHAR szTmp[MAX_PATH+1];
  2186. PhoneBookParseInfoStruct pbpisInfo;
  2187. LPTSTR pszSlash;
  2188. LPTSTR pszDot;
  2189. int nVal = 0;
  2190. if (!pArgs->pszProfile)
  2191. {
  2192. MYDBG(("InitArgs() must give AF_URL on command line when AF_NO_PROFILE is given."));
  2193. goto done;
  2194. }
  2195. // Get CMS file name
  2196. GetPrivateProfileString(c_pszCmSection,
  2197. c_pszCmEntryCmsFile,
  2198. TEXT(""),
  2199. szTmp,
  2200. sizeof(szTmp)/sizeof(TCHAR)-1,
  2201. pArgs->pszProfile);
  2202. if (!szTmp[0])
  2203. {
  2204. MYDBG(("InitArgs() [Connection Manager] CMSFile= entry not found in %s.",pArgs->pszProfile));
  2205. goto done;
  2206. }
  2207. /*
  2208. ZeroMemory(szPath,sizeof(szPath));
  2209. dwRes = GetFullPathName(szTmp,sizeof(szPath)/sizeof(TCHAR)-1,szPath,&pszFileInPath);
  2210. MYDBGTST(!dwRes,("InitArgs() GetFullPathName() failed, GLE=%u.",GetLastError()));
  2211. */
  2212. //
  2213. // we simply append the relative path of the cms file to the profile dir to
  2214. // construct the cms path.
  2215. //
  2216. lstrcat(szPath, TEXT("\\"));
  2217. lstrcat(szPath, szTmp);
  2218. pArgs->pdaArgs->pszCMSFile = CmStrCpyAlloc(szPath);
  2219. if (!pArgs->pdaArgs->pszCMSFile)
  2220. {
  2221. goto done;
  2222. }
  2223. // get the PBK filename from the CMS file
  2224. GetPrivateProfileString(c_pszCmSectionIsp,
  2225. c_pszCmEntryIspPbFile,
  2226. TEXT(""),
  2227. szTmp,
  2228. sizeof(szTmp)/sizeof(TCHAR)-1,
  2229. pArgs->pdaArgs->pszCMSFile);
  2230. if (!*szTmp)
  2231. {
  2232. MYDBG(("InitArgs() [ISP Info] RegionFile= entry not found in %s.",pArgs->pdaArgs->pszCMSFile));
  2233. pArgs->pdaArgs->pszPhoneBookName = CmStrCpyAlloc(TEXT(""));
  2234. }
  2235. else
  2236. {
  2237. if (!(pArgs->pdaArgs->pszPbkFile = CmStrCpyAlloc(szTmp)))
  2238. goto done;
  2239. // get the phone book name
  2240. if (!(pszSlash = CmStrrchr(pArgs->pdaArgs->pszPbkFile, TEXT('\\'))))
  2241. {
  2242. MYDBG((TEXT("InitArgs() bad PBKFILE - no backslash.")));
  2243. goto done;
  2244. }
  2245. if (!(pszDot = CmStrchr(pszSlash, TEXT('.'))))
  2246. {
  2247. MYDBG((TEXT("InitArgs() bad PBKFILE - no dot.")));
  2248. goto done;
  2249. }
  2250. *pszDot = TEXT('\0');
  2251. if (!(pArgs->pdaArgs->pszPhoneBookName = CmStrCpyAlloc(pszSlash+1)))
  2252. goto done;
  2253. // restore the slash
  2254. *pszDot = TEXT('.');
  2255. }
  2256. // get the PBR filename from the CMS file
  2257. GetPrivateProfileString(c_pszCmSectionIsp,
  2258. c_pszCmEntryIspRegionFile,
  2259. TEXT(""),
  2260. szTmp,
  2261. sizeof(szTmp)/sizeof(TCHAR)-1,
  2262. pArgs->pdaArgs->pszCMSFile);
  2263. MYDBGTST(!*szTmp, ("InitArgs() [ISP Info] RegionFile= entry not found in %s.",pArgs->pdaArgs->pszCMSFile));
  2264. if (!(pArgs->pdaArgs->pszPbrFile = CmStrCpyAlloc(szTmp)))
  2265. goto done;
  2266. GetPrivateProfileString(c_pszCmSection,
  2267. c_pszVersion,
  2268. TEXT(""),
  2269. szTmp,
  2270. sizeof(szTmp)/sizeof(TCHAR)-1,
  2271. pArgs->pdaArgs->pszCMSFile);
  2272. pArgs->pdaArgs->pszVerCurr = CmStrCpyAlloc(szTmp);
  2273. if (!pArgs->pdaArgs->pszVerCurr)
  2274. {
  2275. goto done;
  2276. }
  2277. pArgs->pdaArgs->pszUrl = (LPTSTR) CmMalloc((INTERNET_MAX_URL_LENGTH+1)*sizeof(TCHAR));
  2278. if (!pArgs->pdaArgs->pszUrl)
  2279. {
  2280. goto done;
  2281. }
  2282. ZeroMemory(&pbpisInfo,sizeof(pbpisInfo));
  2283. pbpisInfo.dwSize = sizeof(pbpisInfo);
  2284. pbpisInfo.pszURL = pArgs->pdaArgs->pszUrl;
  2285. pbpisInfo.dwURL = INTERNET_MAX_URL_LENGTH;
  2286. pbpisInfo.pfnRef = RefFunc;
  2287. pbpisInfo.dwRefParam = (DWORD_PTR) pArgs;
  2288. bRes = PhoneBookParseInfo(pArgs->pdaArgs->pszCMSFile,&pbpisInfo);
  2289. if (!bRes)
  2290. {
  2291. MYDBG(("InitArgs() PhoneBookParseInfo() failed, GLE=%u.",GetLastError()));
  2292. goto done;
  2293. }
  2294. PhoneBookFreeFilter(pbpisInfo.pFilterA);
  2295. PhoneBookFreeFilter(pbpisInfo.pFilterB);
  2296. //
  2297. // Bug fix #3064, a-nichb - HideDelay & DownloadDelay
  2298. // Use nVal while retrieving entries, then assign to global
  2299. //
  2300. // Get Download delay
  2301. nVal = GetPrivateProfileInt(c_pszCmSection,
  2302. c_pszCmEntryDownloadDelay,
  2303. DEFAULT_DELAY,
  2304. pArgs->pdaArgs->pszCMSFile);
  2305. // Convert to milliseconds
  2306. pArgs->dwDownloadDelay = ((DWORD) nVal * (DWORD) 1000);
  2307. MYDBG(("Download delay is %u millisseconds.", pArgs->dwDownloadDelay));
  2308. // Get Hide delay
  2309. nVal = GetPrivateProfileInt(c_pszCmSection,
  2310. c_pszCmEntryHideDelay,
  2311. -1,
  2312. pArgs->pdaArgs->pszCMSFile);
  2313. //
  2314. // Convert to milliseconds
  2315. //
  2316. if (nVal < 0)
  2317. {
  2318. pArgs->dwHideDelay = DEFAULT_HIDE;
  2319. }
  2320. else
  2321. {
  2322. pArgs->dwHideDelay = ((DWORD) nVal * (DWORD) 1000);
  2323. }
  2324. MYDBG(("Hide delay is %u milliseconds.", pArgs->dwHideDelay));
  2325. #if 0
  2326. /*
  2327. // we don't support SuppressUpdates anymore
  2328. if (GetPrivateProfileInt(c_pszCmSection, //13226
  2329. TEXT("SuppressUpdates"),
  2330. 0,
  2331. pArgs->pszProfile))
  2332. {
  2333. pArgs->dwAppFlags |= AF_NO_UPDATE;
  2334. }
  2335. */
  2336. #endif
  2337. }
  2338. else
  2339. {
  2340. pArgs->pdaArgs[0].pszUrl = pszUrl;
  2341. pszUrl = NULL;
  2342. }
  2343. if (pArgs->pszProfile)
  2344. {
  2345. TCHAR szTmp1[MAX_PATH+1];
  2346. TCHAR szTmp2[MAX_PATH+1];
  2347. pArgs->pszServiceName = (LPTSTR) CmMalloc((MAX_PATH+1)*sizeof(TCHAR));
  2348. if (!pArgs->pszServiceName)
  2349. {
  2350. goto done;
  2351. }
  2352. lstrcpy(szTmp1,pArgs->pdaArgs->pszCMSFile);
  2353. if (CmStrrchr(szTmp1,'.'))
  2354. {
  2355. *CmStrrchr(szTmp1,'.') = 0;
  2356. }
  2357. if (CmStrrchr(szTmp1,'\\'))
  2358. {
  2359. lstrcpy(szTmp1,CmStrrchr(szTmp1,'\\')+1);
  2360. }
  2361. GetPrivateProfileString(c_pszCmSection,
  2362. c_pszCmEntryServiceName,
  2363. szTmp1,
  2364. pArgs->pszServiceName,
  2365. MAX_PATH,
  2366. pArgs->pdaArgs->pszCMSFile);
  2367. // Get the name of the large icon
  2368. GetPrivateProfileString(c_pszCmSection,
  2369. c_pszCmEntryBigIcon,
  2370. TEXT(""),
  2371. szTmp2,
  2372. sizeof(szTmp2)/sizeof(TCHAR)-1,
  2373. pArgs->pdaArgs->pszCMSFile);
  2374. // If we have a name, load the large icon
  2375. if (szTmp2[0])
  2376. {
  2377. pArgs->hIcon = CmLoadIcon(pArgs->hInst,szTmp2);
  2378. }
  2379. // Get the name of the small icon
  2380. GetPrivateProfileString(c_pszCmSection,
  2381. c_pszCmEntrySmallIcon,
  2382. TEXT(""),
  2383. szTmp2,
  2384. sizeof(szTmp2)/sizeof(TCHAR)-1,
  2385. pArgs->pdaArgs->pszCMSFile);
  2386. // If we have a name, load the small icon
  2387. if (szTmp2[0])
  2388. {
  2389. pArgs->hSmallIcon = CmLoadSmallIcon(pArgs->hInst,szTmp2);
  2390. }
  2391. }
  2392. //
  2393. // If the name based icon loads were not successful, load defaults from EXE
  2394. //
  2395. if (!pArgs->hIcon)
  2396. {
  2397. pArgs->hIcon = CmLoadIcon(pArgs->hInst, MAKEINTRESOURCE(IDI_APP));
  2398. }
  2399. if (!pArgs->hSmallIcon)
  2400. {
  2401. pArgs->hSmallIcon = CmLoadSmallIcon(pArgs->hInst,MAKEINTRESOURCE(IDI_APP));
  2402. }
  2403. AddToUrl(pArgs->pdaArgs->pszUrl,pArgs->pdaArgs->pszVerCurr,pArgs->pdaArgs->pszPhoneBookName);
  2404. bRes = TRUE;
  2405. done:
  2406. //
  2407. // Cleanup
  2408. //
  2409. if (pszUrl)
  2410. {
  2411. CmFree(pszUrl);
  2412. }
  2413. if (pszCmdLine)
  2414. {
  2415. CmFree(pszCmdLine);
  2416. }
  2417. if (ppszArgv)
  2418. {
  2419. CmFree(ppszArgv);
  2420. }
  2421. return (bRes);
  2422. }
  2423. static BOOL InitApplication(ArgsStruct *pArgs)
  2424. {
  2425. WNDCLASSEX wcDlg;
  2426. wcDlg.cbSize = sizeof(wcDlg);
  2427. if (FALSE == GetClassInfoEx(NULL, WC_DIALOG, &wcDlg))
  2428. {
  2429. MYDBG(("InitApplication() GetClassInfoEx() failed, GLE=%u.",GetLastError()));
  2430. return (FALSE);
  2431. }
  2432. wcDlg.lpszClassName = ICONNDWN_CLASS;
  2433. wcDlg.hIcon = pArgs->hIcon;
  2434. wcDlg.hIconSm = pArgs->hSmallIcon;
  2435. wcDlg.hInstance = pArgs->hInst;
  2436. pArgs->hIcon = NULL;
  2437. pArgs->hSmallIcon = NULL;
  2438. //
  2439. // We have our class data setup, register the class
  2440. //
  2441. ATOM aRes = RegisterClassEx(&wcDlg);
  2442. if (!aRes)
  2443. {
  2444. //
  2445. // We may have more than one instance, so check the error case
  2446. //
  2447. DWORD dwError = GetLastError();
  2448. if (ERROR_ALREADY_EXISTS != dwError)
  2449. {
  2450. MYDBG(("InitApplication() RegisterClassEx() failed, GLE=%u.",GetLastError()));
  2451. return (FALSE);
  2452. }
  2453. }
  2454. MYDBG(("InitApplication() Class %s is registered.", wcDlg.lpszClassName));
  2455. return TRUE;
  2456. }
  2457. static BOOL InitInstance(ArgsStruct *pArgs)
  2458. {
  2459. pArgs->nMsgId = RegisterWindowMessage(c_pszIConnDwnMsg);
  2460. if (!pArgs->nMsgId)
  2461. {
  2462. MYDBG(("InitInstance() RegisterWindowMessage() failed."));
  2463. return (FALSE);
  2464. }
  2465. return (TRUE);
  2466. }
  2467. //+----------------------------------------------------------------------------
  2468. //
  2469. // Func: InitLogging
  2470. //
  2471. // Desc: Initializes logging functionality for the CMDL32 module
  2472. //
  2473. // Args: [pArgs] - args struct to pick up stuff from
  2474. //
  2475. // Return: BOOL (TRUE for success)
  2476. //
  2477. // Notes: IMPORTANT: note that CMDL32 is compiled Ansi whereas CMUTIL, which
  2478. // contains the logging functionality, is Unicode. CmLogFile exposes both
  2479. // Ansi and Unicode variants for member functions that take strings.
  2480. // However, the arguments passed to the Log calls are Ansi - they are
  2481. // handled correctly by using %S (note, capital S) in the corresponding
  2482. // format strings in cmlog.rc.
  2483. //
  2484. // History: 11-Apr-2001 SumitC Created
  2485. //
  2486. //-----------------------------------------------------------------------------
  2487. static BOOL InitLogging(ArgsStruct * pArgs)
  2488. {
  2489. BOOL fAllUser = TRUE;
  2490. BOOL fEnabled = FALSE;
  2491. DWORD dwMaxSize = 0;
  2492. CHAR szFileDir[MAX_PATH + 1] = {0};
  2493. //
  2494. // First figure out if this profile is AllUsers or Single User
  2495. //
  2496. if (!OS_W9X)
  2497. {
  2498. HMODULE hShell32 = LoadLibraryExA("Shell32.dll", NULL, 0);
  2499. if (hShell32)
  2500. {
  2501. typedef DWORD (WINAPI *pfnSHGetSpecialFolderPathASpec)(HWND, CHAR*, int, BOOL);
  2502. pfnSHGetSpecialFolderPathASpec pfnSHGetSpecialFolderPathA;
  2503. pfnSHGetSpecialFolderPathA = (pfnSHGetSpecialFolderPathASpec)
  2504. GetProcAddress(hShell32,
  2505. "SHGetSpecialFolderPathA");
  2506. if (pfnSHGetSpecialFolderPathA)
  2507. {
  2508. CHAR szPath[MAX_PATH+1];
  2509. if (TRUE == pfnSHGetSpecialFolderPathA(NULL, szPath, CSIDL_APPDATA, FALSE))
  2510. {
  2511. CHAR szProfile[MAX_PATH + 1];
  2512. lstrcpyn(szProfile, pArgs->pszProfile, MAX_PATH);
  2513. szProfile[ lstrlen(szPath) ] = '\0';
  2514. if (0 == lstrcmpi(szProfile, szPath))
  2515. {
  2516. fAllUser = FALSE;
  2517. }
  2518. }
  2519. }
  2520. FreeLibrary(hShell32);
  2521. }
  2522. }
  2523. //
  2524. // To get Enabled, we have the code equivalent of IniBoth
  2525. //
  2526. fEnabled = c_fEnableLogging;
  2527. BOOL bGotValueFromReg = FALSE;
  2528. HKEY hkey;
  2529. CHAR szRegPath[2 * MAX_PATH];
  2530. lstrcpy(szRegPath, fAllUser ? "SOFTWARE\\Microsoft\\Connection Manager\\UserInfo\\" :
  2531. "SOFTWARE\\Microsoft\\Connection Manager\\SingleUserInfo\\");
  2532. if ( (lstrlen(szRegPath) + 1 + lstrlen(pArgs->pszServiceName) + 1) > (2 * MAX_PATH))
  2533. {
  2534. return FALSE;
  2535. }
  2536. lstrcat(szRegPath, "\\");
  2537. lstrcat(szRegPath, pArgs->pszServiceName);
  2538. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
  2539. szRegPath,
  2540. 0,
  2541. KEY_QUERY_VALUE,
  2542. &hkey))
  2543. {
  2544. DWORD dwType;
  2545. DWORD bEnabled;
  2546. DWORD dwSize = sizeof(DWORD);
  2547. if (ERROR_SUCCESS == RegQueryValueEx(hkey,
  2548. c_pszCmEntryEnableLogging,
  2549. NULL,
  2550. &dwType,
  2551. (PBYTE) &bEnabled,
  2552. &dwSize))
  2553. {
  2554. fEnabled = bEnabled ? TRUE : FALSE;
  2555. bGotValueFromReg = TRUE;
  2556. }
  2557. RegCloseKey(hkey);
  2558. }
  2559. //
  2560. // To *exactly* mimic pIniBoth we should check the .CMP here too. However,
  2561. // the moment the user brings up the UI we will write this value to the
  2562. // registry if it was in the .CMP. So, skip the CMP step.
  2563. //
  2564. if (FALSE == bGotValueFromReg)
  2565. {
  2566. fEnabled = (BOOL ) GetPrivateProfileInt(c_pszCmSection,
  2567. c_pszCmEntryEnableLogging,
  2568. c_fEnableLogging,
  2569. pArgs->pdaArgs->pszCMSFile);
  2570. }
  2571. //
  2572. // To get MaxSize, we have the code equivalent of IniService
  2573. //
  2574. dwMaxSize = GetPrivateProfileInt(c_pszCmSectionLogging,
  2575. c_pszCmEntryMaxLogFileSize,
  2576. c_dwMaxFileSize,
  2577. pArgs->pdaArgs->pszCMSFile);
  2578. //
  2579. // LogFileDirectory is also obtained via IniService
  2580. //
  2581. GetPrivateProfileString(c_pszCmSectionLogging,
  2582. c_pszCmEntryLogFileDirectory,
  2583. c_szLogFileDirectory,
  2584. szFileDir,
  2585. sizeof(szFileDir) / sizeof(TCHAR) - 1,
  2586. pArgs->pdaArgs->pszCMSFile);
  2587. //
  2588. // Use these values to initialize logging
  2589. //
  2590. pArgs->Log.Init(pArgs->hInst, fAllUser, pArgs->pszServiceName);
  2591. pArgs->Log.SetParams(fEnabled, dwMaxSize, szFileDir);
  2592. if (pArgs->Log.IsEnabled())
  2593. {
  2594. pArgs->Log.Start(FALSE); // FALSE => no banner
  2595. }
  2596. else
  2597. {
  2598. pArgs->Log.Stop();
  2599. }
  2600. return TRUE;
  2601. }
  2602. int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR , int )
  2603. {
  2604. MYDBG(("====================================================="));
  2605. MYDBG((" CMDL32.EXE - LOADING - Process ID is 0x%x ", GetCurrentProcessId()));
  2606. MYDBG(("====================================================="));
  2607. INT_PTR iRes = 1;
  2608. ArgsStruct asArgs;
  2609. DWORD dwIdx = 0;
  2610. BOOL bRes = FALSE;
  2611. //
  2612. // Initialize app-wide arguments
  2613. //
  2614. ZeroMemory(&asArgs,sizeof(asArgs));
  2615. //
  2616. // We can't use hInst param if we're not linked with libc.
  2617. // libc uses GetModuleHandle(NULL), so we will too.
  2618. //
  2619. asArgs.hInst = GetModuleHandleA(NULL); // hInst;
  2620. MYDBGTST(NULL == asArgs.hInst, ("WinMain - GetModuleHandle(NULL) returned 0x%x, GLE=%u.", asArgs.hInst, GetLastError()));
  2621. #ifdef EXTENDED_CAB_CONTENTS
  2622. asArgs.dwRebootCookie = MyNeedRebootInit(&asArgs); //must init flag or else will ask for reboot with no args or other errors
  2623. #endif // EXTENDED_CAB_CONTENTS
  2624. if (!InitArgs(&asArgs))
  2625. {
  2626. goto done;
  2627. }
  2628. ///////////////////////////////////////////////////////////////////////////////////
  2629. if (asArgs.dwAppFlags & AF_VPN)
  2630. {
  2631. iRes = UpdateVpnFileForProfile(asArgs.pszProfile);
  2632. goto done;
  2633. }
  2634. ///////////////////////////////////////////////////////////////////////////////////
  2635. // Set UPDATE flag
  2636. // if (asArgs.dwAppFlags & AF_NO_UPDATE)
  2637. // {
  2638. // MYDBG(("WinMain() user has disabled updates."));
  2639. // goto done;
  2640. // }
  2641. // Initialize the app.
  2642. if (!InitApplication(&asArgs))
  2643. {
  2644. goto done;
  2645. }
  2646. // Setup this instance
  2647. if (!InitInstance(&asArgs))
  2648. {
  2649. goto done;
  2650. }
  2651. InitCommonControls();
  2652. #ifdef EXTENDED_CAB_CONTENTS
  2653. asArgs.dwRebootCookie = MyNeedRebootInit(&asArgs);
  2654. #endif // EXTENDED_CAB_CONTENTS
  2655. //
  2656. // Initialize Logging
  2657. //
  2658. if (!InitLogging(&asArgs))
  2659. {
  2660. goto done;
  2661. }
  2662. iRes = DialogBoxParam(asArgs.hInst,MAKEINTRESOURCE(IDD_MAIN),NULL, (DLGPROC)MainDlgProc,(LPARAM) &asArgs);
  2663. MYDBGTST(iRes == -1, ("WinMain() - DialogBoxParam(0x%x, 0x%x, NULL, MainDlgProc, 0x%x) - failed",asArgs.hInst, MAKEINTRESOURCE(IDD_MAIN), &asArgs));
  2664. done:
  2665. // Close any handles created during WININET session
  2666. for (dwIdx=0;dwIdx<asArgs.dwArgsCnt;dwIdx++)
  2667. {
  2668. DownloadArgs *pdaArgs;
  2669. pdaArgs = asArgs.pdaArgs + dwIdx;
  2670. if (pdaArgs->hReq)
  2671. {
  2672. bRes = InternetCloseHandle(pdaArgs->hReq);
  2673. MYDBGTST(!bRes,("WinMain() InternetCloseHandle(asArgs.pdaArgs[%u].hReq) failed, GLE=%u.",dwIdx,GetLastError()));
  2674. pdaArgs->hReq = NULL;
  2675. }
  2676. if (pdaArgs->hConn)
  2677. {
  2678. bRes = InternetCloseHandle(pdaArgs->hConn);
  2679. MYDBGTST(!bRes,("WinMain() InternetCloseHandle(asArgs.pdaArgs[%u].hConn) failed, GLE=%u.",dwIdx,GetLastError()));
  2680. pdaArgs->hConn = NULL;
  2681. }
  2682. if (pdaArgs->hInet)
  2683. {
  2684. bRes = InternetCloseHandle(pdaArgs->hInet);
  2685. MYDBGTST(!bRes,("WinMain() InternetCloseHandle(asArgs.pdaArgs[%u].hInet) failed, GLE=%u.",dwIdx,GetLastError()));
  2686. pdaArgs->hInet = NULL;
  2687. }
  2688. }
  2689. // Wait for thread to terminate
  2690. if (asArgs.ahHandles[IDX_INETTHREAD_HANDLE])
  2691. {
  2692. long lRes;
  2693. lRes = WaitForSingleObject(asArgs.ahHandles[IDX_INETTHREAD_HANDLE],45*1000);
  2694. MYDBGTST(lRes!=WAIT_OBJECT_0,("WinMain() WaitForSingleObject() failed, GLE=%u.",lRes));
  2695. }
  2696. // Free profile and service data
  2697. if (asArgs.pszProfile)
  2698. {
  2699. CmFree(asArgs.pszProfile);
  2700. asArgs.pszProfile = NULL;
  2701. }
  2702. if (asArgs.pszServiceName)
  2703. {
  2704. CmFree(asArgs.pszServiceName);
  2705. asArgs.pszServiceName = NULL;
  2706. }
  2707. // Cleanup for each argument
  2708. for (dwIdx=0;dwIdx<asArgs.dwArgsCnt;dwIdx++)
  2709. {
  2710. DownloadArgs *pdaArgs;
  2711. UINT i;
  2712. pdaArgs = asArgs.pdaArgs + dwIdx;
  2713. CmFreeIndirect(&pdaArgs->pszCMSFile);
  2714. CmFreeIndirect(&pdaArgs->pszPbkFile);
  2715. CmFreeIndirect(&pdaArgs->pszPbrFile);
  2716. CmFreeIndirect(&pdaArgs->pszUrl);
  2717. CmFreeIndirect(&pdaArgs->pszVerCurr);
  2718. CmFreeIndirect(&pdaArgs->pszVerNew);
  2719. //CmFreeIndirect(&pdaArgs->pszNewPbrFile);
  2720. CmFreeIndirect(&pdaArgs->pszPhoneBookName);
  2721. if (pdaArgs->psUrl)
  2722. {
  2723. CmFree(pdaArgs->psUrl);
  2724. pdaArgs->psUrl = NULL;
  2725. }
  2726. for (i=0; i<pdaArgs->dwNumFilesToProcess; i++)
  2727. CmFree(pdaArgs->rgfpiFileProcessInfo[i].pszFile);
  2728. CmFree(pdaArgs->rgfpiFileProcessInfo);
  2729. // As long as AF_NO_DELETE is NOT set, clean up temp files and dirs
  2730. if (!(asArgs.dwAppFlags & AF_NO_DELETE))
  2731. {
  2732. if (pdaArgs->szFile[0])
  2733. {
  2734. bRes = DeleteFile(pdaArgs->szFile);
  2735. MYDBGTST(!bRes,("WinMain() DeleteFile(asArgs[pdaArgs[%lu].szFile=%s) failed, GLE=%u.",dwIdx,pdaArgs->szFile,GetLastError()));
  2736. }
  2737. if (pdaArgs->szCabDir[0])
  2738. {
  2739. ZapDir(pdaArgs->szCabDir);
  2740. }
  2741. }
  2742. }
  2743. // Release download args
  2744. if (asArgs.pdaArgs)
  2745. {
  2746. CmFree(asArgs.pdaArgs);
  2747. asArgs.pdaArgs = NULL;
  2748. }
  2749. for (dwIdx=0;dwIdx<sizeof(asArgs.ahHandles)/sizeof(asArgs.ahHandles[0]);dwIdx++)
  2750. {
  2751. if (asArgs.ahHandles[dwIdx])
  2752. {
  2753. bRes = CloseHandle(asArgs.ahHandles[dwIdx]);
  2754. MYDBGTST(!bRes,("WinMain() CloseHandle(asArgs.ahHandles[%u]) failed, GLE=%u.",dwIdx,GetLastError()));
  2755. asArgs.ahHandles[dwIdx] = NULL;
  2756. }
  2757. }
  2758. #ifdef EXTENDED_CAB_CONTENTS
  2759. // If we need a re-boot, prompt the user
  2760. if (MyNeedReboot(&asArgs,asArgs.dwRebootCookie))
  2761. {
  2762. LPTSTR pszCaption;
  2763. LPTSTR pszText;
  2764. int iMBRes;
  2765. pszText = CmFmtMsg(asArgs.hInst,IDMSG_REBOOT_TEXT);
  2766. pszCaption = CmFmtMsg(asArgs.hInst,IDMSG_REBOOT_CAPTION);
  2767. iMBRes = MessageBoxEx(NULL,pszText,pszCaption,MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2,LANG_USER_DEFAULT);
  2768. MYDBGTST(!iMBRes,("WinMain() MessageBoxEx() failed, GLE=%u.",GetLastError()));
  2769. CmFree(pszText);
  2770. CmFree(pszCaption);
  2771. if (iMBRes == IDYES)
  2772. {
  2773. bRes = ExitWindowsEx(EWX_REBOOT,0);
  2774. MYDBGTST(!bRes,("WinMain() ExitWindowsEx() failed, GLE=%u.",GetLastError()));
  2775. }
  2776. }
  2777. // If advpack was used, release it
  2778. if (asArgs.hAdvPack)
  2779. {
  2780. bRes = FreeLibrary(asArgs.hAdvPack);
  2781. MYDBGTST(!bRes,("WinMain() FreeLibrary() failed, GLE=%u.",GetLastError()));
  2782. asArgs.hAdvPack = NULL;
  2783. }
  2784. #endif // EXTENDED_CAB_CONTENTS
  2785. //
  2786. // Uninitialize logging
  2787. //
  2788. asArgs.Log.DeInit();
  2789. //
  2790. // the C runtine uses ExitProcess() to exit.
  2791. //
  2792. MYDBG(("====================================================="));
  2793. MYDBG((" CMDL32.EXE - UNLOADING - Process ID is 0x%x ", GetCurrentProcessId()));
  2794. MYDBG(("====================================================="));
  2795. ExitProcess((UINT)iRes);
  2796. return ((int)iRes);
  2797. }