Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1181 lines
43 KiB

  1. //*********************************************************************
  2. //* Microsoft Windows **
  3. //* Copyright(c) Microsoft Corp., 1994 **
  4. //*********************************************************************
  5. //
  6. // ISPPAGE.CPP - Functions for
  7. //
  8. // HISTORY:
  9. //
  10. // 05/13/98 donaldm Created.
  11. //
  12. //*********************************************************************
  13. #include "pre.h"
  14. #include "shlobj.h"
  15. #include "webvwids.h"
  16. TCHAR szHTMLFile[MAX_PATH]; //Name of html file
  17. BOOL bOKToPersist = TRUE;
  18. DWORD g_dwPageType = 0;
  19. BOOL g_bWebGateCheck = TRUE;
  20. BOOL g_bConnectionErr = FALSE;
  21. //PROTOTYPES
  22. BOOL SaveISPFile( HWND hwndParent, TCHAR* szSrcFileName, DWORD dwFileType);
  23. #if defined (DBG)
  24. BOOL HtmlSaveAs( HWND hwndParent, TCHAR* szFileName, TCHAR* szTargetFileName);
  25. void AskSaveISPHTML(HWND hWnd, LPTSTR lpszHTMLFile)
  26. {
  27. HKEY hKey = NULL;
  28. DWORD dwTemp = 0;
  29. DWORD dwType = 0;
  30. DWORD dwSize = sizeof(dwTemp);
  31. RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\ISignup\\Debug"), &hKey);
  32. if (hKey)
  33. {
  34. RegQueryValueEx(hKey,TEXT("SaveIspHtmLocally"),0,&dwType,(LPBYTE)&dwTemp, &dwSize);
  35. if (dwTemp)
  36. {
  37. if (IDYES == MessageBox(hWnd, TEXT("Would you like to save this ISP HTML file?"), TEXT("ICW -- DEBUG"), MB_YESNO | MB_ICONQUESTION | MB_APPLMODAL))
  38. HtmlSaveAs(hWnd, lpszHTMLFile, NULL);
  39. }
  40. }
  41. }
  42. #endif // dbg
  43. void InitPageControls
  44. (
  45. HWND hDlg,
  46. DWORD dwPageType,
  47. DWORD dwPageFlag
  48. )
  49. {
  50. TCHAR szTemp[MAX_MESSAGE_LEN];
  51. switch (dwPageType)
  52. {
  53. // TOS, has the Accept, Don't Accept UI
  54. case PAGETYPE_ISP_TOS:
  55. {
  56. // Show the TOS controls
  57. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSINSTRT), SW_SHOW);
  58. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSHTML), SW_SHOW);
  59. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSSAVE), SW_SHOW);
  60. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSACCEPT), SW_SHOW);
  61. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSDECLINE), SW_SHOW);
  62. ShowWindow(GetDlgItem(hDlg, IDC_TOS_TOSSAVE), SW_SHOW);
  63. //hide "normal weboc"
  64. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_HTML), SW_HIDE);
  65. //hide the save check box controls
  66. ShowWindow(GetDlgItem(hDlg, IDC_SAVE_DESKTOP_TEXT), SW_HIDE);
  67. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_CUSTHTML), SW_HIDE);
  68. // Reset the TOS page
  69. Button_SetCheck(GetDlgItem(hDlg, IDC_ISPDATA_TOSACCEPT), BST_UNCHECKED);
  70. Button_SetCheck(GetDlgItem(hDlg, IDC_ISPDATA_TOSDECLINE),BST_UNCHECKED);
  71. // Set tab focus
  72. SetWindowLong(GetDlgItem(hDlg, IDC_ISPDATA_TOSACCEPT), GWL_STYLE, GetWindowLong(GetDlgItem(hDlg, IDC_ISPDATA_TOSACCEPT),GWL_STYLE)|WS_TABSTOP);
  73. EnableWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSDECLINE), TRUE);
  74. EnableWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSACCEPT), TRUE);
  75. EnableWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSSAVE), TRUE);
  76. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
  77. break;
  78. }
  79. // Finish, Custom Finish, and Normal are the same from a UI perspective (Also default)
  80. case PAGETYPE_ISP_CUSTOMFINISH:
  81. case PAGETYPE_ISP_FINISH:
  82. case PAGETYPE_ISP_NORMAL:
  83. default:
  84. {
  85. BOOL bIsQuickFinish = FALSE;
  86. // Need to see if this is a Quick Finish page
  87. gpWizardState->pHTMLWalker->get_IsQuickFinish(&bIsQuickFinish);
  88. // Hide the TOS controls
  89. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSINSTRT), SW_HIDE);
  90. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSHTML), SW_HIDE);
  91. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSACCEPT), SW_HIDE);
  92. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSDECLINE), SW_HIDE);
  93. ShowWindow(GetDlgItem(hDlg, IDC_TOS_TOSSAVE), SW_HIDE);
  94. if (dwPageFlag & PAGEFLAG_SAVE_CHKBOX)
  95. {
  96. // Show check box controls
  97. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_CUSTHTML), SW_SHOW);
  98. ShowWindow(GetDlgItem(hDlg, IDC_SAVE_DESKTOP_TEXT), SW_SHOW);
  99. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSSAVE), SW_SHOW);
  100. // Hide the normal controls
  101. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_HTML), SW_HIDE);
  102. //Reenable the UI
  103. EnableWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSSAVE), TRUE);
  104. }
  105. else
  106. {
  107. //show "normal" web oc
  108. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_HTML), SW_SHOW);
  109. // Hide the Checkbox controls
  110. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSSAVE), SW_HIDE);
  111. ShowWindow(GetDlgItem(hDlg, IDC_SAVE_DESKTOP_TEXT), SW_HIDE);
  112. ShowWindow(GetDlgItem(hDlg, IDC_ISPDATA_CUSTHTML), SW_HIDE);
  113. }
  114. //set the wizard buttons
  115. // If we are on a Custom Finish, or Quick finish page then
  116. // use Active the Finish button
  117. PropSheet_SetWizButtons(GetParent(hDlg),
  118. ((bIsQuickFinish || (PAGETYPE_ISP_CUSTOMFINISH == dwPageType)) ? PSWIZB_FINISH : PSWIZB_NEXT) | PSWIZB_BACK);
  119. break;
  120. }
  121. }
  122. // Change the title for the finish page
  123. if (gpWizardState->cmnStateData.dwFlags & ICW_CFGFLAG_AUTOCONFIG)
  124. {
  125. LoadString(ghInstanceResDll, IDS_STEP3_TITLE, szTemp, MAX_MESSAGE_LEN);
  126. }
  127. else
  128. {
  129. if((PAGETYPE_ISP_CUSTOMFINISH == dwPageType ) || (PAGETYPE_ISP_FINISH == dwPageType))
  130. LoadString(ghInstanceResDll, IDS_STEP3_TITLE, szTemp, MAX_MESSAGE_LEN);
  131. else
  132. LoadString(ghInstanceResDll, IDS_STEP2_TITLE, szTemp, MAX_MESSAGE_LEN);
  133. }
  134. PropSheet_SetHeaderTitle(GetParent(hDlg), EXE_NUM_WIZARD_PAGES + ORD_PAGE_ISPDATA, szTemp);
  135. }
  136. HRESULT InitForPageType
  137. (
  138. HWND hDlg
  139. )
  140. {
  141. DWORD dwPageType = 0;
  142. DWORD dwPageFlag = 0;
  143. BOOL bRetVal = FALSE;
  144. HRESULT hRes = E_FAIL;
  145. BSTR bstrPageID = NULL;
  146. BSTR bstrHTMLFile = NULL;
  147. //make sure these are disabled here incase getpagetype fails
  148. EnableWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSDECLINE), FALSE);
  149. EnableWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSACCEPT), FALSE);
  150. EnableWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSSAVE), FALSE);
  151. // Get webgate to dump the HTML into a file
  152. gpWizardState->pWebGate->DumpBufferToFile(&bstrHTMLFile, &bRetVal);
  153. // Use the Walker to get the page type
  154. gpWizardState->pHTMLWalker->AttachToMSHTML(bstrHTMLFile);
  155. gpWizardState->pHTMLWalker->Walk();
  156. // Setup the controls based on the page type
  157. if (FAILED(hRes = gpWizardState->pHTMLWalker->get_PageType(&dwPageType)))
  158. {
  159. gpWizardState->pRefDial->DoHangup();
  160. g_bMalformedPage = TRUE; //used by server error to get correct msg
  161. }
  162. else
  163. {
  164. if (dwPageType == PAGETYPE_ISP_TOS)
  165. {
  166. if(gpWizardState->cmnStateData.bOEMCustom)
  167. {
  168. gpWizardState->pICWWebView->SetHTMLBackgroundBitmap(NULL, NULL);
  169. }
  170. gpWizardState->pICWWebView->ConnectToWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSHTML), PAGETYPE_ISP_TOS);
  171. }
  172. else
  173. {
  174. RECT rcHTML;
  175. HWND hWndHTML;
  176. gpWizardState->pHTMLWalker->get_PageFlag(&dwPageFlag);
  177. if (dwPageFlag & PAGEFLAG_SAVE_CHKBOX)
  178. {
  179. hWndHTML = GetDlgItem(hDlg, IDC_ISPDATA_CUSTHTML);
  180. // See if we need to display the app background bitmap in the HTML
  181. // window
  182. if(gpWizardState->cmnStateData.bOEMCustom)
  183. {
  184. GetWindowRect(hWndHTML, &rcHTML);
  185. MapWindowPoints(NULL, gpWizardState->cmnStateData.hWndApp, (LPPOINT)&rcHTML, 2);
  186. gpWizardState->pICWWebView->SetHTMLBackgroundBitmap(gpWizardState->cmnStateData.hbmBkgrnd, &rcHTML);
  187. }
  188. gpWizardState->pICWWebView->ConnectToWindow(hWndHTML, PAGETYPE_ISP_NORMAL);
  189. }
  190. else
  191. {
  192. hWndHTML = GetDlgItem(hDlg, IDC_ISPDATA_HTML);
  193. // See if we need to display the app background bitmap in the HTML
  194. // window
  195. if(gpWizardState->cmnStateData.bOEMCustom)
  196. {
  197. GetWindowRect(hWndHTML, &rcHTML);
  198. MapWindowPoints(NULL, gpWizardState->cmnStateData.hWndApp, (LPPOINT)&rcHTML, 2);
  199. gpWizardState->pICWWebView->SetHTMLBackgroundBitmap(gpWizardState->cmnStateData.hbmBkgrnd, &rcHTML);
  200. }
  201. gpWizardState->pICWWebView->ConnectToWindow(hWndHTML, PAGETYPE_ISP_NORMAL);
  202. }
  203. }
  204. // Custom finish means that the ISP wants us to show some special text
  205. // and then finish the wizard
  206. if (dwPageType == PAGETYPE_ISP_CUSTOMFINISH)
  207. {
  208. BOOL bRetVal;
  209. // Show the page. no need to cache it
  210. bOKToPersist = FALSE;
  211. lstrcpy(szHTMLFile, W2A(bstrHTMLFile));
  212. gpWizardState->pICWWebView->DisplayHTML(szHTMLFile);
  213. // Kill the idle timer and connection, since there are no more pages
  214. ASSERT(gpWizardState->pRefDial);
  215. KillIdleTimer();
  216. gpWizardState->pRefDial->DoHangup();
  217. gpWizardState->pRefDial->RemoveConnectoid(&bRetVal);
  218. gpWizardState->bDialExact = FALSE;
  219. }
  220. else
  221. {
  222. // In order to persist data entered by the user, we have to
  223. // effectivly "cache" the pages, so that when the user goes back
  224. // we make MSHTML think that we are loading a page that it has seen
  225. // before, and it will then reload the persisted history.
  226. // This will be done by using the PAGEID value in the HTML to form a
  227. // temp file name, so that we can re-load the page date from that file
  228. // each time we see the same page ID value.
  229. // Get the Page ID.
  230. gpWizardState->pHTMLWalker->get_PageID(&bstrPageID);
  231. if (bOKToPersist && SUCCEEDED( gpWizardState->lpSelectedISPInfo->CopyFiletoISPPageCache(bstrPageID, W2A(bstrHTMLFile))))
  232. {
  233. // We have a "cache" file, so we can use it and persist data
  234. // Get the cache file name now, since we will need it later
  235. gpWizardState->lpSelectedISPInfo->GetCacheFileNameFromPageID(bstrPageID, szHTMLFile, sizeof(szHTMLFile));
  236. }
  237. else
  238. {
  239. bOKToPersist = FALSE;
  240. lstrcpy(szHTMLFile, W2A(bstrHTMLFile));
  241. }
  242. // Display the page we just "cached"
  243. gpWizardState->pICWWebView->DisplayHTML(szHTMLFile);
  244. if (bOKToPersist)
  245. {
  246. // Restore any persisted data on this page.
  247. gpWizardState->lpSelectedISPInfo->LoadHistory(bstrPageID);
  248. }
  249. // Cleanup
  250. SysFreeString(bstrPageID);
  251. }
  252. #if defined(DBG)
  253. AskSaveISPHTML(hDlg, szHTMLFile);
  254. #endif
  255. InitPageControls(hDlg, dwPageType, dwPageFlag);
  256. g_dwPageType = dwPageType;
  257. }
  258. // Detach the walker
  259. gpWizardState->pHTMLWalker->Detach();
  260. HideProgressAnimation();
  261. SysFreeString(bstrHTMLFile);
  262. return hRes;
  263. }
  264. /*******************************************************************
  265. NAME: ISPPageInitProc
  266. SYNOPSIS: Called when page is displayed
  267. ENTRY: hDlg - dialog window
  268. fFirstInit - TRUE if this is the first time the dialog
  269. is initialized, FALSE if this InitProc has been called
  270. before (e.g. went past this page and backed up)
  271. ********************************************************************/
  272. BOOL CALLBACK ISPPageInitProc
  273. (
  274. HWND hDlg,
  275. BOOL fFirstInit,
  276. UINT *puNextPage
  277. )
  278. {
  279. if (fFirstInit)
  280. {
  281. // Setup an Event Handler for RefDial and Webgate
  282. CINSHandlerEvent *pINSHandlerEvent;
  283. pINSHandlerEvent = new CINSHandlerEvent(hDlg);
  284. if (NULL != pINSHandlerEvent)
  285. {
  286. HRESULT hr;
  287. gpWizardState->pINSHandlerEvents = pINSHandlerEvent;
  288. gpWizardState->pINSHandlerEvents->AddRef();
  289. hr = ConnectToConnectionPoint((IUnknown *)gpWizardState->pINSHandlerEvents,
  290. DIID__INSHandlerEvents,
  291. TRUE,
  292. (IUnknown *)gpWizardState->pINSHandler,
  293. &gpWizardState->pINSHandlerEvents->m_dwCookie,
  294. NULL);
  295. }
  296. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
  297. }
  298. else
  299. {
  300. if (FAILED(InitForPageType(hDlg)))
  301. {
  302. //The page type isn't recognized which means there's a problem
  303. //with the data. goto the serverr page
  304. gpWizardState->pRefDial->DoHangup();
  305. *puNextPage = ORD_PAGE_SERVERR;
  306. }
  307. // if we've travelled through external apprentice pages,
  308. // it's easy for our current page pointer to get munged,
  309. // so reset it here for sanity's sake.
  310. gpWizardState->uCurrentPage = ORD_PAGE_ISPDATA;
  311. }
  312. return TRUE;
  313. }
  314. // Returns FALSE if we should stay on this page, TRUE if we should change pages
  315. // the param bError indicates we should proceed to the server Error Page.
  316. BOOL ProcessNextBackPage
  317. (
  318. HWND hDlg,
  319. BOOL fForward,
  320. BOOL *pfError
  321. )
  322. {
  323. BOOL bRet = FALSE;
  324. TCHAR szURL[2*INTERNET_MAX_URL_LENGTH + 1] = TEXT("\0");
  325. *pfError = FALSE;
  326. gpWizardState->pHTMLWalker->get_URL(szURL, fForward);
  327. // See if a URL is Specified
  328. if (lstrcmp(szURL, TEXT("")) == 0)
  329. {
  330. //Stop the animation
  331. HideProgressAnimation();
  332. //Reenable the UI
  333. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT | PSWIZB_BACK);
  334. // If forward, we want to force our way to the server error page,
  335. // since we cannot go forward to a blank URL
  336. if (fForward)
  337. {
  338. KillIdleTimer();
  339. gpWizardState->pRefDial->DoHangup();
  340. *pfError = TRUE;
  341. }
  342. else
  343. {
  344. // We are backing out of ISP page land, so lets hangup.
  345. if(gpWizardState->pRefDial)
  346. {
  347. BOOL bRetVal;
  348. KillIdleTimer();
  349. gpWizardState->pRefDial->DoHangup();
  350. gpWizardState->pRefDial->RemoveConnectoid(&bRetVal);
  351. gpWizardState->bDialExact = FALSE;
  352. }
  353. }
  354. // We will need to navigate away from the ISP page
  355. bRet = TRUE;
  356. }
  357. else
  358. {
  359. BOOL bRetWebGate;
  360. BOOL bConnected = FALSE;
  361. g_bWebGateCheck = TRUE;
  362. g_bConnectionErr = FALSE;
  363. // Do not go to the next page. Also valid for the cancel case
  364. bRet = FALSE;
  365. // Kill the idle Timer
  366. KillIdleTimer();
  367. // Tell webgate to go fetch the page
  368. gpWizardState->pWebGate->put_Path(A2W(szURL));
  369. gpWizardState->pWebGate->FetchPage(0,0,&bRetWebGate);
  370. //This flag is only to be used by ICWDEBUG.EXE
  371. if (gpWizardState->cmnStateData.dwFlags & ICW_CFGFLAG_MODEMOVERRIDE)
  372. bConnected = TRUE;
  373. else
  374. gpWizardState->pRefDial->get_RasGetConnectStatus(&bConnected);
  375. if (bConnected)
  376. {
  377. WaitForEvent(gpWizardState->hEventWebGateDone);
  378. }
  379. else
  380. {
  381. g_bConnectionErr = TRUE;
  382. }
  383. // See if the user canceled. If so we want to force the wizard to bail.
  384. // this can be hacked by forcing the return value to be FALSE and
  385. // setting the gfQuitWizard flag to TRUE. Gendlg will check this flag
  386. // when the OK proc returns, and process appropriatly
  387. if (!gfUserCancelled)
  388. {
  389. if (g_bConnectionErr)
  390. {
  391. // Make it go to server error page
  392. bRet = TRUE;
  393. *pfError = TRUE;
  394. }
  395. else
  396. {
  397. // Restart the Idle Timer
  398. StartIdleTimer();
  399. // detach the walker, since Init for page type needs it
  400. gpWizardState->pHTMLWalker->Detach();
  401. // Setup for this page
  402. if (FAILED(InitForPageType(hDlg)))
  403. {
  404. //The page type isn't recognized which means there's a problem
  405. //with the data. goto the serverr page
  406. *pfError = TRUE;
  407. bRet = TRUE;
  408. }
  409. }
  410. }
  411. else
  412. {
  413. // Force the wizard to quit, since the user canceled
  414. gfQuitWizard = TRUE;
  415. }
  416. }
  417. return bRet;
  418. }
  419. /*******************************************************************
  420. NAME: ISPPageOKProc
  421. SYNOPSIS: Called when Next or Back btns pressed from page
  422. ENTRY: hDlg - dialog window
  423. fForward - TRUE if 'Next' was pressed, FALSE if 'Back'
  424. puNextPage - if 'Next' was pressed,
  425. proc can fill this in with next page to go to. This
  426. parameter is ingored if 'Back' was pressed.
  427. pfKeepHistory - page will not be kept in history if
  428. proc fills this in with FALSE.
  429. EXIT: returns TRUE to allow page to be turned, FALSE
  430. to keep the same page.
  431. ********************************************************************/
  432. BOOL CALLBACK ISPPageOKProc
  433. (
  434. HWND hDlg,
  435. BOOL fForward,
  436. UINT *puNextPage,
  437. BOOL *pfKeepHistory
  438. )
  439. {
  440. ASSERT(puNextPage);
  441. DWORD dwPageType;
  442. TCHAR szURL[2*INTERNET_MAX_URL_LENGTH + 1] = TEXT("\0");
  443. BOOL bRetVal = TRUE;
  444. BSTR bstrPageID = NULL;
  445. IWebBrowser2 *lpWebBrowser;
  446. // We don't want to keep any of the ISP pages in the history list
  447. *pfKeepHistory = FALSE;
  448. // If we are going forward, and if the user has been autodisconnected, then
  449. // we want to automatically navigate to the server error page.
  450. if (fForward && gpWizardState->bAutoDisconnected)
  451. {
  452. gpWizardState->bAutoDisconnected = FALSE;
  453. *puNextPage = ORD_PAGE_SERVERR;
  454. return TRUE;
  455. }
  456. // Attach the walker to the curent page to get the page type
  457. gpWizardState->pICWWebView->get_BrowserObject(&lpWebBrowser);
  458. gpWizardState->pHTMLWalker->AttachToDocument(lpWebBrowser);
  459. gpWizardState->pHTMLWalker->Walk();
  460. gpWizardState->pHTMLWalker->get_PageType(&dwPageType);
  461. // Custom finish means we just exit, so we just need to return TRUE
  462. if (PAGETYPE_ISP_CUSTOMFINISH == dwPageType)
  463. {
  464. gpWizardState->pHTMLWalker->Detach();
  465. return TRUE;
  466. }
  467. // Check the TOS settings. If the users decline, don't allow them to proceed
  468. if (IsWindowVisible(GetDlgItem(hDlg, IDC_ISPDATA_TOSDECLINE)) )
  469. {
  470. if (fForward)
  471. {
  472. if (Button_GetCheck(GetDlgItem(hDlg, IDC_ISPDATA_TOSDECLINE)))
  473. {
  474. if (MsgBox(hDlg,IDS_ERR_TOS_DECLINE,MB_ICONSTOP,MB_OKCANCEL) != IDOK)
  475. {
  476. gfQuitWizard = TRUE;
  477. }
  478. Button_SetCheck(GetDlgItem(hDlg, IDC_ISPDATA_TOSACCEPT), 0);
  479. Button_SetCheck(GetDlgItem(hDlg, IDC_ISPDATA_TOSDECLINE), 0);
  480. // Set tab focus
  481. SetWindowLong(GetDlgItem(hDlg, IDC_ISPDATA_TOSACCEPT), GWL_STYLE, GetWindowLong(GetDlgItem(hDlg, IDC_ISPDATA_TOSACCEPT),GWL_STYLE)|WS_TABSTOP);
  482. SetFocus(GetDlgItem(hDlg, IDC_ISPDATA_TOSHTML));
  483. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
  484. return FALSE;
  485. }
  486. }
  487. EnableWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSDECLINE), FALSE);
  488. EnableWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSACCEPT), FALSE);
  489. EnableWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSSAVE), FALSE);
  490. }
  491. //Show the progress animation
  492. ShowProgressAnimation();
  493. //Disable the UI
  494. PropSheet_SetWizButtons(GetParent(hDlg), 0);
  495. if (bOKToPersist)
  496. {
  497. // Persist any data on this page.
  498. gpWizardState->pHTMLWalker->get_PageID(&bstrPageID);
  499. gpWizardState->lpSelectedISPInfo->SaveHistory(bstrPageID);
  500. SysFreeString(bstrPageID);
  501. }
  502. // User going back?
  503. if (fForward)
  504. {
  505. // Depending on the page type, we do different things
  506. switch (dwPageType)
  507. {
  508. // The finish page types, mean that what we fetch next is an INS file
  509. case PAGETYPE_ISP_FINISH:
  510. {
  511. BSTR bstrINSFile;
  512. BSTR bstrStartURL;
  513. BOOL bRet;
  514. BOOL bIsQuickFinish = FALSE;
  515. long lBrandingFlags;
  516. gpWizardState->pHTMLWalker->get_URL(szURL, TRUE);
  517. // Kill the idle timer
  518. KillIdleTimer();
  519. gpWizardState->pHTMLWalker->get_IsQuickFinish(&bIsQuickFinish);
  520. if(!bIsQuickFinish)
  521. {
  522. BOOL bConnected = FALSE;
  523. g_bWebGateCheck = TRUE;
  524. g_bConnectionErr = FALSE;
  525. // Tell webgate to go fetch the page
  526. gpWizardState->pWebGate->put_Path(A2W(szURL));
  527. gpWizardState->pWebGate->FetchPage(1,0,&bRet);
  528. //This flag is only to be used by ICWDEBUG.EXE
  529. if (gpWizardState->cmnStateData.dwFlags & ICW_CFGFLAG_MODEMOVERRIDE)
  530. bConnected = TRUE;
  531. else
  532. // Check for connection status before proceed
  533. gpWizardState->pRefDial->get_RasGetConnectStatus(&bConnected);
  534. if (bConnected)
  535. {
  536. WaitForEvent(gpWizardState->hEventWebGateDone);
  537. }
  538. else
  539. {
  540. bConnected = TRUE;
  541. }
  542. if (g_bConnectionErr)
  543. {
  544. gpWizardState->pRefDial->DoHangup();
  545. *puNextPage = ORD_PAGE_SERVERR;
  546. break;
  547. }
  548. // Can't allow the user to cancel now
  549. PropSheet_CancelToClose(GetParent(hDlg));
  550. PropSheet_SetWizButtons(GetParent(hDlg),0);
  551. UpdateWindow(GetParent(hDlg));
  552. //Stop the animation
  553. HideProgressAnimation();
  554. // See if the user canceled while downloading the INS file
  555. if (!gfUserCancelled)
  556. {
  557. // OK process the INS file.
  558. gpWizardState->pWebGate->get_DownloadFname(&bstrINSFile);
  559. // Get the Branding flags
  560. gpWizardState->pRefDial->get_BrandingFlags(&lBrandingFlags);
  561. // Tell the INSHandler about the branding flags
  562. gpWizardState->pINSHandler->put_BrandingFlags(lBrandingFlags);
  563. // Process the inf file.
  564. gpWizardState->pINSHandler->ProcessINS(bstrINSFile, &bRet);
  565. //hang on to whether or not this failed.
  566. gpWizardState->cmnStateData.ispInfo.bFailedIns = !bRet;
  567. // Get the Start URL from INS file.
  568. gpWizardState->pINSHandler->get_DefaultURL(&bstrStartURL);
  569. lstrcpy(gpWizardState->cmnStateData.ispInfo.szStartURL,
  570. W2A(bstrStartURL));
  571. // Time to retun to the main wizard
  572. *puNextPage = g_uExternUINext;
  573. // Detach the walker before we go
  574. gpWizardState->pHTMLWalker->Detach();
  575. //Copy over the isp name and support number for the last page.
  576. lstrcpy(gpWizardState->cmnStateData.ispInfo.szISPName,
  577. gpWizardState->lpSelectedISPInfo->get_szISPName());
  578. BSTR bstrSupportPhoneNum;
  579. gpWizardState->pRefDial->get_ISPSupportNumber(&bstrSupportPhoneNum);
  580. lstrcpy(gpWizardState->cmnStateData.ispInfo.szSupportNumber,
  581. W2A(bstrSupportPhoneNum));
  582. }
  583. else
  584. {
  585. // The user canceled while we were donwloading the INS, so lets bail
  586. gpWizardState->pHTMLWalker->Detach();
  587. gfQuitWizard = TRUE;
  588. bRetVal = FALSE;
  589. }
  590. }
  591. else
  592. HideProgressAnimation();
  593. // Let the wizard Continue/Finish
  594. break;
  595. }
  596. // These page types mean that we need to form a new URL, and get the next page
  597. case PAGETYPE_ISP_TOS:
  598. case PAGETYPE_ISP_NORMAL:
  599. {
  600. BOOL bError;
  601. bRetVal = ProcessNextBackPage(hDlg, TRUE, &bError);
  602. if (bError)
  603. {
  604. // Go to the server error page
  605. gpWizardState->pRefDial->DoHangup();
  606. *puNextPage = ORD_PAGE_SERVERR;
  607. }
  608. break;
  609. }
  610. default:
  611. {
  612. //Stop the animation
  613. HideProgressAnimation();
  614. gpWizardState->pRefDial->DoHangup();
  615. // Goto the server error page, since we surely did not recognize this page type
  616. *puNextPage = ORD_PAGE_SERVERR;
  617. break;
  618. }
  619. }
  620. }
  621. else
  622. {
  623. // Going Backwards.
  624. BOOL bError;
  625. bRetVal = ProcessNextBackPage(hDlg, FALSE, &bError);
  626. if (bError)
  627. {
  628. // Go to the server error page
  629. *puNextPage = ORD_PAGE_SERVERR;
  630. }
  631. }
  632. return bRetVal;
  633. }
  634. /*******************************************************************
  635. NAME: ISPCmdProc
  636. ********************************************************************/
  637. BOOL CALLBACK ISPCmdProc
  638. (
  639. HWND hDlg,
  640. WPARAM wParam,
  641. LPARAM lParam
  642. )
  643. {
  644. switch (GET_WM_COMMAND_CMD(wParam, lParam))
  645. {
  646. case BN_CLICKED:
  647. {
  648. switch (GET_WM_COMMAND_ID(wParam, lParam))
  649. {
  650. case IDC_ISPDATA_TOSACCEPT:
  651. case IDC_ISPDATA_TOSDECLINE:
  652. {
  653. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT | PSWIZB_BACK);
  654. break;
  655. }
  656. case IDC_ISPDATA_TOSSAVE:
  657. {
  658. if (SaveISPFile(hDlg, szHTMLFile, g_dwPageType))
  659. {
  660. SetFocus(GetDlgItem(hDlg, IDC_ISPDATA_TOSHTML));
  661. EnableWindow(GetDlgItem(hDlg, IDC_ISPDATA_TOSSAVE), FALSE);
  662. }
  663. break;
  664. }
  665. default:
  666. break;
  667. }
  668. break;
  669. }
  670. case BN_DBLCLK:
  671. {
  672. switch (GET_WM_COMMAND_ID(wParam, lParam))
  673. {
  674. case IDC_ISPDATA_TOSACCEPT:
  675. case IDC_ISPDATA_TOSDECLINE:
  676. {
  677. // somebody double-clicked a radio button
  678. // auto-advance to the next page
  679. PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
  680. break;
  681. }
  682. default:
  683. break;
  684. }
  685. break;
  686. }
  687. case BN_SETFOCUS:
  688. {
  689. if ((GET_WM_COMMAND_ID(wParam, lParam) == IDC_ISPDATA_TOSACCEPT) )
  690. {
  691. CheckDlgButton(hDlg, IDC_ISPDATA_TOSACCEPT, BST_CHECKED);
  692. // Uncheck the decline checkbox make sure no two radio button
  693. // selected at the same time.
  694. CheckDlgButton(hDlg, IDC_ISPDATA_TOSDECLINE, BST_UNCHECKED);
  695. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT | PSWIZB_BACK);
  696. }
  697. break;
  698. }
  699. default:
  700. break;
  701. }
  702. return 1;
  703. }
  704. /*******************************************************************
  705. NAME: DisplayConfirmationDialog
  706. SYNOPSIS: Display a confirmation dialog for the file being written
  707. ENTRY: hwndParent - dialog window
  708. dwFileType - current isp page type
  709. szFileName - source file name
  710. EXIT: returns TRUE when save successfully; FALSE otherwise.
  711. ********************************************************************/
  712. BOOL DisplayConfirmationDialog(HWND hwndParent, DWORD dwFileType, TCHAR* szFileName)
  713. {
  714. TCHAR szFinal [MAX_MESSAGE_LEN] = TEXT("\0");
  715. TCHAR szFmt [MAX_MESSAGE_LEN];
  716. TCHAR *args [1];
  717. LPVOID pszIntro;
  718. BOOL bRet = TRUE;
  719. UINT uMsgID;
  720. args[0] = (LPTSTR) szFileName;
  721. if (PAGETYPE_ISP_TOS == dwFileType)
  722. {
  723. uMsgID = IDS_SAVE_COPY_CONFIRM_MSG;
  724. }
  725. else
  726. {
  727. uMsgID = IDS_SAVE_ISP_CONFIRM_MSG;
  728. }
  729. LoadString(ghInstanceResDll, uMsgID, szFmt, ARRAYSIZE(szFmt));
  730. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  731. szFmt,
  732. 0,
  733. 0,
  734. (LPTSTR)&pszIntro,
  735. 0,
  736. (va_list*)args);
  737. lstrcpy(szFinal, (LPTSTR)pszIntro);
  738. LoadString(ghInstanceResDll, IDS_APPNAME, szFmt, ARRAYSIZE(szFmt));
  739. MessageBox(hwndParent, szFinal, szFmt, MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
  740. LocalFree(pszIntro);
  741. return(bRet);
  742. }
  743. /*******************************************************************
  744. NAME: SaveISPFile
  745. SYNOPSIS: Called want to save html file to desktop without dialog
  746. ENTRY: hwndParent - dialog window
  747. szSrcFileName - source file name
  748. uFileType - Type of files embedded in the htm file
  749. EXIT: returns TRUE when save successfully; FALSE otherwise.
  750. ********************************************************************/
  751. BOOL SaveISPFile( HWND hwndParent, TCHAR* szSrcFileName, DWORD dwFileType)
  752. {
  753. TCHAR szNewFileBuff [MAX_PATH + 1];
  754. TCHAR szWorkingDir [MAX_PATH + 1];
  755. TCHAR szDesktopPath [MAX_PATH + 1];
  756. TCHAR szLocalFile [MAX_PATH + 1];
  757. TCHAR szISPName [MAX_ISP_NAME + 1];
  758. TCHAR szFmt [MAX_MESSAGE_LEN];
  759. TCHAR szNumber [MAX_MESSAGE_LEN];
  760. TCHAR *args [2];
  761. DWORD dwFileFormatOrig;
  762. DWORD dwFileFormatCopy;
  763. LPTSTR pszInvalideChars = TEXT("\\/:*?\"<>|");
  764. LPVOID pszIntro = NULL;
  765. LPITEMIDLIST lpItemDList = NULL;
  766. HRESULT hr = E_FAIL; //don't assume success
  767. IMalloc *pMalloc = NULL;
  768. BOOL ret = FALSE;
  769. ASSERT(hwndParent);
  770. ASSERT(szFileName);
  771. // Validate page type, return false if page type is unknown
  772. if (PAGETYPE_ISP_TOS == dwFileType)
  773. {
  774. dwFileFormatOrig = IDS_TERMS_FILENAME;
  775. dwFileFormatCopy = IDS_TERMS_FILENAME_COPY;
  776. }
  777. else if ((PAGETYPE_ISP_CUSTOMFINISH == dwFileType) ||
  778. (PAGETYPE_ISP_FINISH == dwFileType) ||
  779. (PAGETYPE_ISP_NORMAL == dwFileType))
  780. {
  781. dwFileFormatOrig = IDS_ISPINFO_FILENAME;
  782. dwFileFormatCopy = IDS_ISPINFO_FILENAME_COPY;
  783. }
  784. else
  785. {
  786. return FALSE;
  787. }
  788. GetCurrentDirectory(ARRAYSIZE(szWorkingDir), szWorkingDir);
  789. hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP,&lpItemDList);
  790. //Get the "DESKTOP" dir
  791. ASSERT(SUCCEEDED(hr));
  792. if (SUCCEEDED(hr))
  793. {
  794. SHGetPathFromIDList(lpItemDList, szDesktopPath);
  795. // Free up the memory allocated for LPITEMIDLIST
  796. if (SUCCEEDED (SHGetMalloc (&pMalloc)))
  797. {
  798. pMalloc->Free (lpItemDList);
  799. pMalloc->Release ();
  800. }
  801. }
  802. // Replace invalid file name char in ISP name with underscore
  803. lstrcpy(szISPName, gpWizardState->lpSelectedISPInfo->get_szISPName());
  804. for( int i = 0; szISPName[i]; i++ )
  805. {
  806. if(_tcschr(pszInvalideChars, szISPName[i]))
  807. {
  808. szISPName[i] = '_';
  809. }
  810. }
  811. // Load the default file name
  812. args[0] = (LPTSTR) szISPName;
  813. args[1] = NULL;
  814. LoadString(ghInstanceResDll, dwFileFormatOrig, szFmt, ARRAYSIZE(szFmt));
  815. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  816. szFmt,
  817. 0,
  818. 0,
  819. (LPTSTR)&pszIntro,
  820. 0,
  821. (va_list*)args);
  822. lstrcat(szDesktopPath, TEXT("\\"));
  823. wsprintf(szLocalFile, TEXT("\"%s\""), (LPTSTR)pszIntro);
  824. lstrcpy(szNewFileBuff, szDesktopPath);
  825. lstrcat(szNewFileBuff, (LPTSTR)pszIntro);
  826. LocalFree(pszIntro);
  827. // Check if file already exists
  828. if (0xFFFFFFFF != GetFileAttributes(szNewFileBuff))
  829. {
  830. // If file exists, create new filename with paranthesis
  831. int nCurr = 1;
  832. do
  833. {
  834. wsprintf(szNumber, TEXT("%d"), nCurr++);
  835. args[1] = (LPTSTR) szNumber;
  836. LoadString(ghInstanceResDll, dwFileFormatCopy, szFmt, ARRAYSIZE(szFmt));
  837. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  838. szFmt,
  839. 0,
  840. 0,
  841. (LPTSTR)&pszIntro,
  842. 0,
  843. (va_list*)args);
  844. lstrcpy(szNewFileBuff, szDesktopPath);
  845. wsprintf(szLocalFile, TEXT("\"%s\""), (LPTSTR)pszIntro);
  846. lstrcat(szNewFileBuff, (LPTSTR)pszIntro);
  847. LocalFree(pszIntro);
  848. } while ((0xFFFFFFFF != GetFileAttributes(szNewFileBuff)) && (nCurr <= 100));
  849. }
  850. // Copy the file to permanent location
  851. HANDLE hFile = CreateFile(szNewFileBuff, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  852. if (hFile != INVALID_HANDLE_VALUE)
  853. {
  854. IICWWalker* pHTMLWalker = NULL;
  855. BSTR bstrText = NULL;
  856. DWORD dwByte = 0;
  857. if (SUCCEEDED(CoCreateInstance(CLSID_ICWWALKER,NULL,CLSCTX_INPROC_SERVER,
  858. IID_IICWWalker,(LPVOID*)&pHTMLWalker)))
  859. {
  860. pHTMLWalker->InitForMSHTML();
  861. pHTMLWalker->AttachToMSHTML(A2W(szSrcFileName));
  862. if (SUCCEEDED(pHTMLWalker->ExtractUnHiddenText(&bstrText)) && bstrText)
  863. {
  864. #ifdef UNICODE
  865. BYTE UNICODE_BYTE_ORDER_MARK[] = {0xFF, 0xFE};
  866. WriteFile(hFile,
  867. UNICODE_BYTE_ORDER_MARK,
  868. sizeof(UNICODE_BYTE_ORDER_MARK),
  869. &dwByte,
  870. NULL);
  871. #endif
  872. ret = WriteFile(hFile, W2A(bstrText), lstrlen(W2A(bstrText))* sizeof(TCHAR), &dwByte, NULL);
  873. SysFreeString(bstrText);
  874. }
  875. pHTMLWalker->TermForMSHTML();
  876. pHTMLWalker->Release();
  877. }
  878. CloseHandle(hFile);
  879. }
  880. // Display message according to the state of CopyFile
  881. if (!ret)
  882. {
  883. DeleteFile(szNewFileBuff);
  884. //let the user know there was not enough disk space
  885. TCHAR szTemp [MAX_RES_LEN] = TEXT("\0");
  886. TCHAR szCaption [MAX_RES_LEN] = TEXT("\0");
  887. LoadString(ghInstanceResDll, IDS_NOT_ENOUGH_DISKSPACE, szTemp, ARRAYSIZE(szTemp));
  888. LoadString(ghInstanceResDll, IDS_APPNAME, szCaption, ARRAYSIZE(szCaption));
  889. MessageBox(hwndParent, szTemp, szCaption, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
  890. }
  891. else
  892. {
  893. // Display the confirmation
  894. DisplayConfirmationDialog(hwndParent, dwFileType, szLocalFile);
  895. }
  896. return ret;
  897. }
  898. #if defined (DBG)
  899. BOOL HtmlSaveAs( HWND hwndParent, TCHAR* szFileName, TCHAR* szTargetFileName)
  900. {
  901. ASSERT(hwndParent);
  902. ASSERT(szFileName);
  903. OPENFILENAME ofn;
  904. TCHAR szNewFileBuff [MAX_PATH + 1];
  905. TCHAR szDesktopPath [MAX_PATH + 1] = TEXT("\0");
  906. TCHAR szWorkingDir [MAX_PATH + 1] = TEXT("\0");
  907. TCHAR szFilter [255] = TEXT("\0");
  908. LPITEMIDLIST lpItemDList = NULL;
  909. HRESULT hr = E_FAIL; //don't assume success
  910. IMalloc *pMalloc = NULL;
  911. BOOL ret = TRUE;
  912. GetCurrentDirectory(ARRAYSIZE(szWorkingDir), szWorkingDir);
  913. hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP,&lpItemDList);
  914. //Get the "DESKTOP" dir
  915. ASSERT(SUCCEEDED(hr));
  916. if (SUCCEEDED(hr))
  917. {
  918. SHGetPathFromIDList(lpItemDList, szDesktopPath);
  919. // Free up the memory allocated for LPITEMIDLIST
  920. if (SUCCEEDED (SHGetMalloc (&pMalloc)))
  921. {
  922. pMalloc->Free (lpItemDList);
  923. pMalloc->Release ();
  924. }
  925. }
  926. if (szTargetFileName != NULL)
  927. {
  928. lstrcpy(szNewFileBuff, szDesktopPath);
  929. lstrcat(szNewFileBuff, TEXT("\\"));
  930. lstrcat(szNewFileBuff, szTargetFileName);
  931. // Copy temporary file to permanent location
  932. ret = CopyFile(szFileName, szNewFileBuff, FALSE);
  933. }
  934. else
  935. {
  936. //Setup the filter
  937. LoadString(ghInstanceResDll, IDS_DEFAULT_TOS_FILTER, szFilter, ARRAYSIZE(szFilter)); // "HTML Files"
  938. //Setup the default file name
  939. if(!LoadString(ghInstanceResDll, IDS_DEFAULT_TOS_FILENAME, szNewFileBuff, ARRAYSIZE(szNewFileBuff))) // "terms"
  940. lstrcpy(szNewFileBuff, TEXT("terms"));
  941. lstrcat(szNewFileBuff, TEXT(".htm"));
  942. //init the filename struct
  943. ofn.lStructSize = sizeof(OPENFILENAME);
  944. ofn.hwndOwner = hwndParent;
  945. ofn.lpstrFilter = szFilter;
  946. ofn.lpstrFile = szNewFileBuff;
  947. ofn.nMaxFile = sizeof(szNewFileBuff);
  948. ofn.lpstrFileTitle = NULL;
  949. ofn.lpstrInitialDir = szDesktopPath;
  950. ofn.lpstrTitle = NULL;
  951. ofn.lpstrCustomFilter = (LPTSTR) NULL;
  952. ofn.nMaxCustFilter = 0L;
  953. ofn.nFileOffset = 0;
  954. ofn.nFileExtension = 0;
  955. ofn.lpstrDefExt = TEXT("*.htm");
  956. ofn.lCustData = 0;
  957. ofn.nFilterIndex = 1L;
  958. ofn.nMaxFileTitle = 0;
  959. ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY |
  960. OFN_EXPLORER | OFN_LONGNAMES | OFN_OVERWRITEPROMPT;
  961. //Call the SaveAs common dlg
  962. if(TRUE == GetSaveFileName(&ofn))
  963. {
  964. HANDLE hFile = CreateFile(ofn.lpstrFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  965. if (hFile != INVALID_HANDLE_VALUE)
  966. {
  967. IICWWalker* pHTMLWalker = NULL;
  968. BSTR bstrText = NULL;
  969. DWORD dwByte = 0;
  970. if (SUCCEEDED(CoCreateInstance(CLSID_ICWWALKER,NULL,CLSCTX_INPROC_SERVER,
  971. IID_IICWWalker,(LPVOID*)&pHTMLWalker)))
  972. {
  973. pHTMLWalker->InitForMSHTML();
  974. pHTMLWalker->AttachToMSHTML(A2W(szFileName));
  975. if (SUCCEEDED(pHTMLWalker->ExtractUnHiddenText(&bstrText)) && bstrText)
  976. {
  977. ret = WriteFile(hFile, W2A(bstrText), lstrlen(W2A(bstrText)), &dwByte, NULL);
  978. SysFreeString(bstrText);
  979. }
  980. pHTMLWalker->TermForMSHTML();
  981. pHTMLWalker->Release();
  982. }
  983. CloseHandle(hFile);
  984. }
  985. if (!ret)
  986. {
  987. DeleteFile(ofn.lpstrFile);
  988. //let the user know there was not enough disk space
  989. TCHAR szTemp [MAX_RES_LEN] = TEXT("\0");
  990. TCHAR szCaption [MAX_RES_LEN] = TEXT("\0");
  991. LoadString(ghInstanceResDll, IDS_NOT_ENOUGH_DISKSPACE, szTemp, ARRAYSIZE(szTemp));
  992. LoadString(ghInstanceResDll, IDS_APPNAME, szCaption, ARRAYSIZE(szCaption));
  993. MessageBox(hwndParent, szTemp, szCaption, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
  994. }
  995. }
  996. }
  997. SetCurrentDirectory(szWorkingDir);
  998. return ret;
  999. }
  1000. #endif