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.

675 lines
17 KiB

  1. /* File: D:\WACKER\tdll\autosave.c (Created: 19-Mar-1994)
  2. *
  3. * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 19 $
  7. * $Date: 7/12/02 1:06p $
  8. */
  9. #include <windows.h>
  10. #pragma hdrstop
  11. #include "features.h"
  12. #include "stdtyp.h"
  13. #include "sf.h"
  14. #include "mc.h"
  15. #include "term.h"
  16. #include "assert.h"
  17. #include "globals.h"
  18. #include "sess_ids.h"
  19. #include "load_res.h"
  20. #include "open_msc.h"
  21. #include "file_msc.h"
  22. #include <term\res.h>
  23. #include "session.h"
  24. #include "session.hh"
  25. #include "errorbox.h"
  26. #include "tdll.h"
  27. #include "htchar.h"
  28. #include "misc.h"
  29. #include <emu\emu.h>
  30. //
  31. // Static function prototypes...
  32. //
  33. STATIC_FUNC BOOL asCreateFullFileName(const HSESSION hSession,
  34. const int iSize,
  35. LPTSTR acFile,
  36. BOOL fExplicit);
  37. STATIC_FUNC int asOverwriteExistingFile(HWND hwnd, LPTSTR pacName);
  38. STATIC_FUNC void asBadSessionFileMsg(HSESSION hSession, LPTSTR pacName);
  39. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  40. * FUNCTION:
  41. * SilentSaveSession
  42. *
  43. * DESCRIPTION:
  44. * This function is called whenever the user selects SAVE from the menus.
  45. * We will prompt to overwrite if a file with same name already exists.
  46. * If the file doen't exist, save it in the defult directory, with the file
  47. * name corresponding to the session name the user gave us.
  48. * NOTE: This function can also be called from SaveSession to do the
  49. * saving work.
  50. *
  51. * ARGUEMENTS:
  52. * hSession -- the session handle
  53. * hwnd -- handle of parent window
  54. * fExplicit -- TRUE if the user selected "Save", false otherwise.
  55. *
  56. * RETURNS:
  57. * Nothing.
  58. *
  59. */
  60. void SilentSaveSession(const HSESSION hSession, HWND hwnd, BOOL fExplicit)
  61. {
  62. const HHSESSION hhSess = VerifySessionHandle(hSession);
  63. TCHAR acName[FNAME_LEN];
  64. TCHAR acOldFile[FNAME_LEN];
  65. BOOL fNameChanged = FALSE;
  66. if (hhSess == NULL)
  67. {
  68. assert(hhSess);
  69. return;
  70. }
  71. // We don't want to silent save the default session. This can happen
  72. // wen the user cancels the first New Connection Dialog, then quits
  73. // the program. jcm 2-22-95
  74. //
  75. if (fExplicit == 0)
  76. {
  77. acName[0] = TEXT('\0');
  78. sessQueryName(hSession, acName, sizeof(acName) / sizeof(TCHAR));
  79. if (sessIsSessNameDefault(acName))
  80. return;
  81. }
  82. acName[0] = TEXT('\0');
  83. sfGetSessionFileName(hhSess->hSysFile,
  84. sizeof(acName) / sizeof(TCHAR), acName);
  85. acOldFile[0] = TEXT('\0');
  86. if (StrCharCmp(hhSess->achOldSessName, hhSess->achSessName) != 0)
  87. {
  88. StrCharCopyN(acOldFile, acName, FNAME_LEN);
  89. fNameChanged = TRUE;
  90. }
  91. // This file hasn't been saved yet or the user has changed the session
  92. // name, in either case we will need to come up with the new fully
  93. // qualified file name.
  94. //
  95. if (acName[0] == TEXT('\0') || fNameChanged)
  96. {
  97. if (!asCreateFullFileName(hSession,
  98. sizeof(acName) / sizeof(TCHAR), acName, fExplicit))
  99. {
  100. // If asCreateFullFileName failed, it is because the fully qualified
  101. // file name is too long. In this case, call save as, and let the
  102. // common dialog in that routine restrict the users name length.
  103. //
  104. SaveAsSession(hSession, hwnd);
  105. return;
  106. }
  107. sfReleaseSessionFile(hhSess->hSysFile);
  108. hhSess->hSysFile = CreateSysFileHdl();
  109. assert(hhSess->hSysFile);
  110. sfOpenSessionFile(hhSess->hSysFile, acName);
  111. if (!asOverwriteExistingFile(hwnd, acName))
  112. {
  113. SaveAsSession(hSession, hwnd);
  114. return;
  115. }
  116. }
  117. // Now we have the user's OK and a correct path/file name so
  118. // let's save it.
  119. //
  120. sessSaveSessionStuff(hSession); // Commit changes if any
  121. sfFlushSessionFile(hhSess->hSysFile); // Write info to disk
  122. // Make sure the name is shadowed, before this was handled by re-reading
  123. // the session file back in, now we don't do that.
  124. //
  125. StrCharCopyN(hhSess->achOldSessName, hhSess->achSessName, FNAME_LEN+1);
  126. if (hhSess->fIsNewSession)
  127. hhSess->fIsNewSession = 0;
  128. else
  129. {
  130. if (acOldFile[0] != TEXT('\0') && fNameChanged)
  131. {
  132. // If the user changed the file name for an existing session
  133. // now is the time to delete the old one... since we have already
  134. // saved the new one.
  135. //
  136. DeleteFile(acOldFile);
  137. }
  138. }
  139. }
  140. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  141. * FUNCTION:
  142. * SaveSession
  143. *
  144. * DESCRIPTION:
  145. * This function is called whenever the user selects "New Connection", "Open",
  146. * "Exit" from the menus or closed the app. If this session has never been
  147. * saved before then we will warn the user and prompt them to save. Otherwise
  148. * save the current settings silently.
  149. *
  150. * ARGUEMENTS:
  151. * hSession -- the session handle
  152. * hwnd -- handle of parent window
  153. *
  154. * RETURNS:
  155. * TRUE - if all went ok with saving or the user didn't want to save.
  156. * FALSE - if the user canceled the operation that brought this to action.
  157. *
  158. */
  159. BOOL SaveSession(const HSESSION hSession, HWND hwnd)
  160. {
  161. TCHAR achText[MAX_PATH],
  162. achSessName[MAX_PATH],
  163. ach[MAX_PATH * 2];
  164. int nRet;
  165. if (sessQueryIsNewSession(hSession) == TRUE)
  166. {
  167. TCHAR_Fill(achSessName, TEXT('\0'), sizeof(achSessName) / sizeof(TCHAR));
  168. TCHAR_Fill(achText, TEXT('\0'), sizeof(achText) / sizeof(TCHAR));
  169. LoadString(glblQueryDllHinst(), IDS_GNRL_CNFRM_SAVE, achText,
  170. sizeof(achText) / sizeof(TCHAR));
  171. sessQueryName(hSession, achSessName, sizeof(achSessName));
  172. if (sessIsSessNameDefault(achSessName))
  173. {
  174. // For now ignore sessions with a default name...
  175. //
  176. return TRUE;
  177. }
  178. wsprintf(ach, achText, TEXT("\""), achSessName, TEXT("\""));
  179. // Warn the user that they haven't saved the session...
  180. //
  181. LoadString(glblQueryDllHinst(), IDS_MB_TITLE_WARN, achText,
  182. sizeof(achText) / sizeof(TCHAR));
  183. if ((nRet = TimedMessageBox(hwnd, ach, achText,
  184. MB_YESNOCANCEL | MB_ICONEXCLAMATION, 0)) != IDYES)
  185. return (nRet == IDNO);
  186. }
  187. SilentSaveSession(hSession, hwnd, FALSE);
  188. return TRUE;
  189. }
  190. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  191. * FUNCTION:
  192. * OpenSession
  193. *
  194. * DESCRIPTION:
  195. * This function will open a session file.
  196. * If there is an opened, unsaved, new session then the user will be prompted
  197. * to save it, otherwise the opened session will be saved silently only after
  198. * the user has pressed the OK button.
  199. *
  200. * ARGUEMENTS:
  201. * hSession -- the session handle
  202. * hwnd -- handle of parent window
  203. *
  204. * RETURNS:
  205. * Nothing.
  206. *
  207. */
  208. int OpenSession(const HSESSION hSession, HWND hwnd)
  209. {
  210. int iRet = 0;
  211. const HHSESSION hhSess = VerifySessionHandle(hSession);
  212. LPTSTR pszStr;
  213. TCHAR acMask[64], acTitle[64];
  214. TCHAR acDir[FNAME_LEN], acName[FNAME_LEN];
  215. TCHAR_Fill(acMask, TEXT('\0'), sizeof(acMask) / sizeof(TCHAR));
  216. TCHAR_Fill(acName, TEXT('\0'), sizeof(acName) / sizeof(TCHAR));
  217. TCHAR_Fill(acTitle, TEXT('\0'), sizeof(acTitle) / sizeof(TCHAR));
  218. resLoadFileMask(glblQueryDllHinst(), IDS_CMM_HAS_FILES1, 2, acMask,
  219. sizeof(acMask) / sizeof(TCHAR));
  220. LoadString(glblQueryDllHinst(), IDS_CMM_LOAD_SESS, acTitle,
  221. sizeof(acTitle) / sizeof(TCHAR));
  222. #ifdef NT_EDITION
  223. //mpt:07-30-97
  224. if ( IsNT() )
  225. #endif
  226. GetUserDirectory(acDir, FNAME_LEN);
  227. #ifdef NT_EDITION
  228. else
  229. {
  230. GetModuleFileName(glblQueryHinst(), acDir, FNAME_LEN);
  231. mscStripName(acDir);
  232. }
  233. #endif
  234. pszStr = gnrcFindFileDialog(hwnd, acTitle, acDir, acMask);
  235. if (pszStr)
  236. {
  237. // If a session is opened then prompt to save it now or just
  238. // save silently in SaveSession()
  239. //
  240. if (SaveSession(hSession, hwnd))
  241. {
  242. if (ReinitializeSessionHandle(hSession, TRUE) == FALSE)
  243. {
  244. assert(0);
  245. free(pszStr);
  246. pszStr = NULL;
  247. return -1;
  248. }
  249. StrCharCopyN(acName, pszStr, FNAME_LEN);
  250. free(pszStr);
  251. pszStr = NULL;
  252. }
  253. else
  254. {
  255. free(pszStr);
  256. pszStr = NULL;
  257. return -2;
  258. }
  259. }
  260. else
  261. {
  262. return -4; // mrw:4/21/95
  263. }
  264. if (StrCharGetByteCount(acName) > 0)
  265. {
  266. if (fTestOpenOldTrmFile(hhSess, acName) != 0)
  267. {
  268. if (sfOpenSessionFile(hhSess->hSysFile, acName) < SF_OK)
  269. {
  270. asBadSessionFileMsg(hSession, acName);
  271. return -3;
  272. }
  273. // If there was a command line we should get rid of it.
  274. //
  275. TCHAR_Fill(hhSess->achSessCmdLn,
  276. TEXT('\0'),
  277. sizeof(hhSess->achSessCmdLn) / sizeof(TCHAR));
  278. if (sessLoadSessionStuff(hSession) == FALSE)
  279. iRet = -4;
  280. emuHomeHostCursor(hhSess->hEmu);
  281. emuEraseTerminalScreen(hhSess->hEmu);
  282. hhSess->fIsNewSession = FALSE;
  283. }
  284. sessUpdateAppTitle(hSession);
  285. PostMessage(hhSess->hwndSess, WM_SETICON, (WPARAM)TRUE,
  286. (LPARAM)hhSess->hIcon);
  287. }
  288. return iRet;
  289. }
  290. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  291. * FUNCTION:
  292. * SaveAsSession
  293. *
  294. * DESCRIPTION:
  295. * This function is called whenever the user selects SAVEAS from the menus.
  296. *
  297. * ARGUEMENTS:
  298. * hSession -- the session handle
  299. * hwnd -- handle of parent window
  300. *
  301. * RETURNS:
  302. * Nothing.
  303. *
  304. */
  305. void SaveAsSession(const HSESSION hSession, HWND hwnd)
  306. {
  307. const HHSESSION hhSess = VerifySessionHandle(hSession);
  308. long lValue = -1;
  309. unsigned long lSize = 0;
  310. LPTSTR pszStr;
  311. TCHAR acMask[64];
  312. TCHAR acTitle[64];
  313. TCHAR acFileName[FNAME_LEN * 2];
  314. TCHAR acDir[FNAME_LEN];
  315. TCHAR ach[FNAME_LEN];
  316. if (hhSess == NULL)
  317. {
  318. assert(hhSess);
  319. return;
  320. }
  321. resLoadFileMask(glblQueryDllHinst(), IDS_CMM_HAS_FILES1, 1, acMask,
  322. sizeof(acMask) / sizeof(TCHAR));
  323. LoadString(glblQueryDllHinst(), IDS_CMM_SAVE_AS, acTitle,
  324. sizeof(acTitle) / sizeof(TCHAR));
  325. if (sfGetSessionFileName(sessQuerySysFileHdl(hSession),
  326. FNAME_LEN * 2, acFileName) != SF_OK ||
  327. sfGetSessionFileName(sessQuerySysFileHdl(hSession),
  328. FNAME_LEN, acDir) != SF_OK)
  329. {
  330. acFileName[0] = TEXT('\0');
  331. if (asCreateFullFileName(hSession,
  332. FNAME_LEN * 2,
  333. acFileName,
  334. TRUE) == TRUE)
  335. {
  336. StrCharCopyN(acDir, acFileName, FNAME_LEN);
  337. acDir[FNAME_LEN - 1] = TEXT('\0');
  338. mscStripName(acDir);
  339. }
  340. else
  341. {
  342. //Changed from current directory to user directory - mpt 8-18-99
  343. if ( !GetUserDirectory(acDir, FNAME_LEN) )
  344. {
  345. GetCurrentDirectory(FNAME_LEN, acDir);
  346. }
  347. sessQueryName(hSession, acFileName, FNAME_LEN * 2);
  348. }
  349. }
  350. else
  351. {
  352. mscStripName(acDir);
  353. }
  354. pszStr = StrCharLast(acDir);
  355. // Remove trailing backslash from the directory name if there is one.
  356. //
  357. if (pszStr && *pszStr == TEXT('\\'))
  358. {
  359. *pszStr = TEXT('\0');
  360. }
  361. pszStr = gnrcSaveFileDialog(hwnd, acTitle, acDir, acMask, acFileName);
  362. if (pszStr)
  363. {
  364. sfReleaseSessionFile(hhSess->hSysFile);
  365. hhSess->hSysFile = CreateSysFileHdl();
  366. sfOpenSessionFile(hhSess->hSysFile, pszStr);
  367. // In the "SaveAs" operation we take the file name and make it the
  368. // session name.
  369. //
  370. TCHAR_Fill(ach, TEXT('\0'), sizeof(ach) / sizeof(TCHAR));
  371. StrCharCopyN(ach, pszStr, FNAME_LEN);
  372. StrCharCopyN(hhSess->achSessName, mscStripExt(mscStripPath(ach)),
  373. FNAME_LEN+1);
  374. StrCharCopyN(hhSess->achOldSessName, hhSess->achSessName,
  375. FNAME_LEN+1);
  376. /* A "SaveAs" operation requires that the file actually be saved.
  377. * To do this, we fiddle with a special reserve item in the file. DLW
  378. */
  379. if (sfGetSessionItem(hhSess->hSysFile, SFID_INTERNAL_TAG, &lSize, &lValue) != 0 ||
  380. lValue == (-1))
  381. {
  382. lValue = 0x12345678;
  383. /* We only write it if we don't have it */
  384. sfPutSessionItem(hhSess->hSysFile, SFID_INTERNAL_TAG,
  385. sizeof(long), &lValue);
  386. }
  387. // Save the new session file...
  388. //
  389. sessSaveSessionStuff(hSession); // Commit changes if any
  390. sfFlushSessionFile(hhSess->hSysFile); // Write info to disk
  391. sessUpdateAppTitle(hSession); // Show name in title
  392. // Since we just saved it's not a new session anymore...
  393. //
  394. hhSess->fIsNewSession = FALSE;
  395. }
  396. free(pszStr);
  397. pszStr = NULL;
  398. return;
  399. }
  400. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  401. * FUNCTION:
  402. * asCreateFullFileName
  403. *
  404. * DESCRIPTION:
  405. * This function will either make up a fully qualified session name using
  406. * the current directory and the session name for NEW sessions, or change
  407. * the existing file name to the user given file name.
  408. *
  409. * ARGUMENTS:
  410. * hSession - the session handle.
  411. * iSize - the size of the following buffer.
  412. * acFile - the old file path and name.
  413. * fExplicit - TRUE if the user selected "Save" from the menus.
  414. *
  415. * RETURNS:
  416. * void
  417. *
  418. */
  419. STATIC_FUNC BOOL asCreateFullFileName(const HSESSION hSession,
  420. const int iSize,
  421. LPTSTR acFile,
  422. BOOL fExplicit)
  423. {
  424. const HHSESSION hhSess = VerifySessionHandle(hSession);
  425. TCHAR acSessName[FNAME_LEN],
  426. acDir[MAX_PATH],
  427. acExt[FNAME_LEN];
  428. LPTSTR pszStr;
  429. int iDirLen,
  430. iNameLen,
  431. iExtLen;
  432. acDir[0] = TEXT('\0');
  433. if (acFile[0] == TEXT('\0'))
  434. {
  435. // This is a brand new session.
  436. //
  437. #ifdef NT_EDITION
  438. // mpt:07-30-97
  439. if ( IsNT() )
  440. #endif
  441. GetUserDirectory(acDir, MAX_PATH);
  442. #ifdef NT_EDITION
  443. else
  444. {
  445. GetModuleFileName(glblQueryHinst(), acDir, MAX_PATH);
  446. mscStripName(acDir);
  447. }
  448. #endif
  449. }
  450. else
  451. {
  452. // The user has changed the session name.
  453. //
  454. StrCharCopyN(acDir, acFile, MAX_PATH);
  455. mscStripName(acDir);
  456. }
  457. // See if we need to append a trailing backslash to the
  458. // directory name.
  459. //
  460. pszStr = StrCharLast(acDir);
  461. if (pszStr && *pszStr != TEXT('\\'))
  462. {
  463. StrCharCat(acDir, TEXT("\\"));
  464. }
  465. // Save the length of the path information. We'll use this below.
  466. //
  467. iDirLen = StrCharGetByteCount(acDir);
  468. // Get the session name given by the user...
  469. //
  470. acSessName[0] = TEXT('\0');
  471. sessQueryName(hSession, acSessName, sizeof(acSessName));
  472. if (sessIsSessNameDefault(acSessName))
  473. {
  474. // We ignore a session with a default name if the user hasn't
  475. // explicitly selected "Save" off of the menus.
  476. //
  477. if (!fExplicit)
  478. return FALSE;
  479. // This seems little odd from the user's perspective, maybe a whole
  480. // new dialog would make more sense?
  481. //
  482. if (DialogBoxParam(glblQueryDllHinst(),
  483. MAKEINTRESOURCE(IDD_NEWCONNECTION),
  484. sessQueryHwnd(hSession),
  485. NewConnectionDlg, (LPARAM)hSession) == FALSE)
  486. {
  487. return FALSE;
  488. }
  489. sessQueryName(hSession, acSessName, sizeof(acSessName));
  490. }
  491. iNameLen = StrCharGetByteCount(acSessName);
  492. // Get the extension we are using from the resource file.
  493. //
  494. acExt[0] = TEXT('\0');
  495. LoadString(glblQueryDllHinst(), IDS_GNRL_HAS, acExt, sizeof(acExt) / sizeof(TCHAR));
  496. iExtLen = StrCharGetByteCount(acExt);
  497. // We're about to put a fully qualified file name together. Let's make
  498. // sure that the combined component length is valid.
  499. //
  500. if ( (iDirLen + iNameLen + iExtLen) > 254)
  501. {
  502. return(FALSE);
  503. }
  504. if ( (iDirLen + iNameLen + iExtLen) > iSize)
  505. {
  506. assert(FALSE);
  507. return(FALSE);
  508. }
  509. // Put the pieces together, now that we know it's going to work.
  510. //
  511. StrCharCopyN(acFile, acDir, iDirLen);
  512. StrCharCat(acFile, acSessName);
  513. StrCharCat(acFile, acExt);
  514. sfSetSessionFileName(hhSess->hSysFile, acFile);
  515. return TRUE;
  516. }
  517. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  518. * FUNCTION:
  519. * asOverwriteExistingFile
  520. *
  521. * DESCRIPTION:
  522. * If a file exists prompt the user to overwrite the file.
  523. *
  524. * ARGUMENTS:
  525. * pacName - the session file name.
  526. *
  527. * RETURNS:
  528. * TRUE - if file doesn't exist or it's ok to overwrite.
  529. * FALSE - if the user doesn't want to overwrite.
  530. *
  531. */
  532. STATIC_FUNC int asOverwriteExistingFile(HWND hwnd, LPTSTR pacName)
  533. {
  534. TCHAR ach[256], achTitle[256], achText[256];
  535. int nRet = 0;
  536. if (GetFileSizeFromName(pacName, NULL))
  537. {
  538. // Warn the user that a file with that name already exists...
  539. //
  540. LoadString(glblQueryDllHinst(), IDS_GNRL_CNFRM_OVER, achText,
  541. sizeof(achText) / sizeof(TCHAR));
  542. wsprintf(ach, achText, pacName);
  543. LoadString(glblQueryDllHinst(), IDS_MB_TITLE_WARN, achTitle,
  544. sizeof(achTitle) / sizeof(TCHAR));
  545. nRet = TimedMessageBox(hwnd, ach, achTitle,
  546. MB_YESNO | MB_ICONEXCLAMATION, 0);
  547. return (nRet == IDYES);
  548. }
  549. return 1;
  550. }
  551. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  552. * FUNCTION:
  553. * asBadSessionFileMsg
  554. *
  555. * DESCRIPTION:
  556. * Display a message if a bad session file is found.
  557. *
  558. * ARGUMENTS:
  559. * hSession - the session handle.
  560. * pacName - the session file name.
  561. *
  562. * RETURNS:
  563. * TRUE - if file doesn't exist or it's ok to overwrite.
  564. * FALSE - if the user doesn't want to overwrite.
  565. *
  566. */
  567. STATIC_FUNC void asBadSessionFileMsg(HSESSION hSession, LPTSTR pacName)
  568. {
  569. const HHSESSION hhSess = VerifySessionHandle(hSession);
  570. TCHAR acFormat[64], acTitle[256], ach[256];
  571. TCHAR_Fill(acFormat, TEXT('\0'), sizeof(acFormat) / sizeof(TCHAR));
  572. TCHAR_Fill(acTitle, TEXT('\0'), sizeof(acTitle) / sizeof(TCHAR));
  573. LoadString(glblQueryDllHinst(), IDS_CMM_LOAD_SESS, acTitle,
  574. sizeof(acTitle) / sizeof(TCHAR));
  575. LoadString(glblQueryDllHinst(), IDS_ER_BAD_SESSION, acFormat,
  576. sizeof(acFormat) / sizeof(TCHAR));
  577. wsprintf(ach, acFormat, pacName);
  578. TimedMessageBox(sessQueryHwnd(hSession), ach, acTitle,
  579. MB_OK | MB_ICONEXCLAMATION, sessQueryTimeout(hSession));
  580. sfSetSessionFileName(hhSess->hSysFile, TEXT(""));
  581. }