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.

822 lines
21 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. ncadmin.C
  5. Abstract:
  6. Main entry point and application global functions
  7. for the Net Client Disk Utility.
  8. Author:
  9. Bob Watson (a-robw)
  10. Revision History:
  11. 17 Feb 94 Written
  12. --*/
  13. #include <windows.h>
  14. #include <stdio.h>
  15. #include <malloc.h>
  16. #include <tchar.h> // unicode macros
  17. //
  18. // App include files
  19. //
  20. #include "otnboot.h"
  21. #include "otnbtdlg.h"
  22. //
  23. // global variable initializations
  24. //
  25. PNCDU_DATA pAppInfo= NULL; // pointer to application data structure
  26. BOOL bDisplayExitMessages = FALSE; // TRUE allows exit messages to be
  27. // displayed when the app terminates
  28. POINT ptWndPos = {-1, -1}; // top left corner of window
  29. static HINSTANCE hNetMsg = NULL;
  30. #ifdef TERMSRV
  31. TCHAR szCommandLineVal[MAX_PATH]=TEXT("");
  32. TCHAR szHelpFileName[MAX_PATH]=TEXT("");
  33. BOOL bUseCleanDisks=FALSE;
  34. #endif
  35. #ifdef JAPAN
  36. USHORT usLangID;
  37. #endif
  38. LPCTSTR
  39. GetNetErrorMsg (
  40. IN LONG lNetErr
  41. )
  42. /*++
  43. Routine Description:
  44. formats an error message number using the NetMsg.DLL or the system
  45. message DLL if the message isn't found in the NetMsg.DLL. returns
  46. the string that correspond to the error message or an empty
  47. string if unable to find a matchin message.
  48. Arguments:
  49. IN LONG lNetErr
  50. error code to translate.
  51. Return Value:
  52. Pointer to string containing the error message or an empty string if
  53. no message was found.
  54. --*/
  55. {
  56. static TCHAR szBuffer[MAX_PATH];
  57. LPTSTR szTemp;
  58. DWORD dwError;
  59. // allocate temporary buffer
  60. szTemp = GlobalAlloc (GPTR, MAX_PATH_BYTES/2);
  61. if (szTemp != NULL) {
  62. // if allocation was successful, then format the error message
  63. if (FormatMessage (FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE,
  64. (LPCVOID)hNetMsg,
  65. (DWORD)lNetErr,
  66. GetUserDefaultLangID(),
  67. szTemp,
  68. MAX_PATH/2,
  69. NULL) == 0) {
  70. dwError = GetLastError();
  71. // try system message table
  72. if (FormatMessage (FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  73. NULL,
  74. (DWORD)lNetErr,
  75. GetUserDefaultLangID(),
  76. szTemp,
  77. MAX_PATH/2,
  78. NULL) == 0) {
  79. dwError = GetLastError();
  80. }
  81. }
  82. } else {
  83. // if allocation was not successful, then just use an empty string
  84. szTemp = (LPTSTR)cszEmptyString;
  85. }
  86. // now format the whole message for display
  87. _stprintf (szBuffer,
  88. GetStringResource (FMT_CREATE_SHARE_ERROR),
  89. lNetErr, szTemp);
  90. // free temp buffer
  91. FREE_IF_ALLOC (szTemp);
  92. return (LPCTSTR)&szBuffer[0];
  93. }
  94. BOOL
  95. SetSysMenuMinimizeEntryState (
  96. IN HWND hwnd,
  97. IN BOOL bState
  98. )
  99. /*++
  100. Routine Description:
  101. enables/disable the "Minimize" menu item of the system menu based
  102. on the value of bState.
  103. Arguments:
  104. IN HWND hwnd
  105. handle of window (the one to modify the system menu from)
  106. IN BOOL bState
  107. TRUE = enable item
  108. FALSE = disable (gray) item
  109. Return Value:
  110. previous state of menu item
  111. --*/
  112. {
  113. HMENU hSysMenu;
  114. BOOL bReturn;
  115. hSysMenu = GetSystemMenu (hwnd, FALSE);
  116. bReturn = EnableMenuItem (hSysMenu, SC_MINIMIZE,
  117. (MF_BYCOMMAND | (bState ? MF_ENABLED : MF_GRAYED)));
  118. if (bReturn == MF_ENABLED) {
  119. bReturn = TRUE;
  120. } else {
  121. bReturn = FALSE;
  122. }
  123. return bReturn;
  124. }
  125. BOOL
  126. RemoveMaximizeFromSysMenu (
  127. IN HWND hWnd // window handle
  128. )
  129. /*++
  130. Routine Description:
  131. modifies the system menu by:
  132. Removing the "Size" and "Maximize" entries
  133. inserting the "About" entry,
  134. Arguments:
  135. IN HWND hWnd
  136. window handle of window containing the system menu to modify
  137. Return Value:
  138. TRUE if successfully made changes, otherwise
  139. FALSE if error occurred
  140. --*/
  141. {
  142. HMENU hSysMenu;
  143. BOOL bReturn;
  144. hSysMenu = GetSystemMenu (hWnd, FALSE);
  145. bReturn = RemoveMenu (hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
  146. if (bReturn) {
  147. bReturn = RemoveMenu (hSysMenu, SC_SIZE, MF_BYCOMMAND);
  148. }
  149. if (bReturn) {
  150. // append to end of menu
  151. bReturn = InsertMenu (hSysMenu, 0xFFFFFFF,
  152. MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
  153. if (bReturn) {
  154. bReturn = InsertMenu (hSysMenu, 0xFFFFFFFF,
  155. MF_BYPOSITION | MF_STRING,
  156. NCDU_ID_ABOUT,
  157. GetStringResource (CSZ_ABOUT_ENTRY));
  158. }
  159. }
  160. return bReturn;
  161. }
  162. BOOL
  163. LoadClientList (
  164. IN HWND hwndDlg,
  165. IN int nListId,
  166. IN LPCTSTR szPath,
  167. IN UINT nListType,
  168. OUT LPTSTR mszDirList
  169. )
  170. /*++
  171. Routine Description:
  172. Load the specified list box with the names of the network clients
  173. in the specified list and write the corresponding directory
  174. names to the MSZ list buffer passed in. The ListItem Data
  175. value is used to store the element id in the MSZ list that
  176. contains the directory entry corresponding to the displayed
  177. list item.
  178. Arguments:
  179. IN HWND hwndDlg,
  180. handle of dialog box window that contains the list box to fill
  181. IN int nListId
  182. Dialog Item Id of List Box to fill
  183. IN LPCTSTR szPath
  184. distribution directory path (where NCADMIN.INF file is found)
  185. IN UINT nListType
  186. CLT_OTNBOOT_FLOPPY Make OTN Boot disk clients
  187. CLT_FLOPPY_INSTALL make install floppy clients
  188. OUT LPTSTR mszDirList
  189. pointer to buffer that will recieve list of client dirs
  190. the call must insure the buffer will be large enough!
  191. Return Value:
  192. TRUE if successful
  193. FALSE if error
  194. --*/
  195. {
  196. // list all subdirs under the distribution path Looking up the
  197. // text name if it's in the inf
  198. LPTSTR szInfName;
  199. LPTSTR szSearchList;
  200. LPTSTR szRealName;
  201. LPTSTR szFilterName;
  202. LPTSTR szThisDir;
  203. BOOL bReturn = FALSE;
  204. DWORD dwDirIndex = 0;
  205. int nItemIndex;
  206. DWORD dwReturn;
  207. LPTSTR szKey;
  208. szInfName = GlobalAlloc (GPTR, MAX_PATH_BYTES);
  209. szSearchList = GlobalAlloc (GPTR, SMALL_BUFFER_SIZE * sizeof(TCHAR));
  210. szRealName = GlobalAlloc (GPTR, MAX_PATH_BYTES);
  211. szFilterName = GlobalAlloc (GPTR, MAX_PATH_BYTES);
  212. if ((szInfName != NULL) &&
  213. (szSearchList != NULL) &&
  214. (szFilterName != NULL) &&
  215. (szRealName != NULL)) {
  216. // get key name to use
  217. if (nListType == CLT_OTNBOOT_FLOPPY) {
  218. szKey = (LPTSTR) cszOTN;
  219. } else {
  220. szKey = (LPTSTR) cszDiskSet;
  221. }
  222. // make .INF file name
  223. lstrcpy (szInfName, szPath);
  224. if (szInfName[lstrlen(szInfName)-1] != cBackslash) lstrcat(szInfName, cszBackslash);
  225. lstrcat (szInfName, cszAppInfName);
  226. // clear old contents and start over
  227. SendDlgItemMessage (hwndDlg, nListId,
  228. LB_RESETCONTENT, 0, 0);
  229. //clear "item data" buffer
  230. *(PDWORD)mszDirList = 0L; // clear first 4 bytes of string
  231. // get list of client dirs & names from INF
  232. // for each item, make sure there's a subdir
  233. // if so, then add the client to the list and the dir to the dir list
  234. dwReturn = QuietGetPrivateProfileString (szKey, NULL, cszEmptyString,
  235. szSearchList, SMALL_BUFFER_SIZE, szInfName);
  236. if (dwReturn > 0) {
  237. for (szThisDir = szSearchList;
  238. *szThisDir != 0;
  239. szThisDir += lstrlen(szThisDir) + 1) {
  240. // make dir path
  241. // is it real?
  242. lstrcpy (szRealName, szPath);
  243. if (szRealName[lstrlen(szRealName)-1] != cBackslash) lstrcat(szRealName, cszBackslash);
  244. lstrcat (szRealName, szThisDir);
  245. if (IsPathADir(szRealName)) {
  246. // this is a real path so
  247. // get string and load data to list box
  248. dwReturn = QuietGetPrivateProfileString (szKey,
  249. szThisDir, szThisDir, szFilterName, MAX_PATH,
  250. szInfName);
  251. // save dir name
  252. AddStringToMultiSz (mszDirList, szThisDir);
  253. // add tje display name to the list box
  254. SendDlgItemMessage (hwndDlg, nListId,
  255. LB_ADDSTRING, 0, (LPARAM)szFilterName);
  256. // find entry in list box
  257. nItemIndex = (int)SendDlgItemMessage (hwndDlg, nListId,
  258. LB_FINDSTRING, 0, (LPARAM)szFilterName);
  259. // item data indicates which entry in the msz the
  260. // corresponding dir name resides.
  261. SendDlgItemMessage (hwndDlg, nListId,
  262. LB_SETITEMDATA, nItemIndex, (LPARAM)dwDirIndex);
  263. dwDirIndex++;
  264. }
  265. } // end of for list
  266. }
  267. // Get information about whether to insist on clean diskettes
  268. dwReturn = QuietGetPrivateProfileString (cszDiskOptions, cszUseCleanDisk, cszEmptyString,
  269. szSearchList, SMALL_BUFFER_SIZE, szInfName);
  270. if (dwReturn > 0 && lstrcmpi(szSearchList, cszUseCleanDiskYes)==0) {
  271. bUseCleanDisks = TRUE;
  272. }
  273. else {
  274. bUseCleanDisks = FALSE;
  275. }
  276. } else {
  277. bReturn = FALSE;
  278. SetLastError (ERROR_OUTOFMEMORY);
  279. }
  280. FREE_IF_ALLOC (szInfName);
  281. FREE_IF_ALLOC (szSearchList);
  282. FREE_IF_ALLOC (szRealName);
  283. FREE_IF_ALLOC (szFilterName);
  284. return bReturn;
  285. }
  286. BOOL
  287. EnableExitMessage (
  288. IN BOOL bNewState
  289. )
  290. /*++
  291. Routine Description:
  292. Exported function to enable/disable the display of the "exit" messages
  293. Arguments:
  294. IN BOOL bNewState
  295. TRUE Enable display of exit messages
  296. FALSE disable display of exit messages
  297. Return Value:
  298. previous value of flag
  299. --*/
  300. {
  301. BOOL bReturn = bDisplayExitMessages;
  302. bDisplayExitMessages = (bNewState != 0 ? TRUE : FALSE);
  303. return bReturn;
  304. }
  305. BOOL
  306. AddMessageToExitList (
  307. IN PNCDU_DATA pData,
  308. IN UINT nMessage
  309. )
  310. /*++
  311. Routine Description:
  312. adds message to message list structure in global data block if message
  313. is unique (i.e. not already in list)
  314. Arguments:
  315. IN PNCDU_DATA pData
  316. data structure to add message to
  317. IN UINT nMessage
  318. ID of message to add (ID of string resource)
  319. Return Value:
  320. TRUE if message added
  321. FALSE if not
  322. --*/
  323. {
  324. DWORD dwIndex;
  325. dwIndex = 0;
  326. while (pData->uExitMessages[dwIndex] != 0) {
  327. if (pData->uExitMessages[dwIndex] == nMessage) {
  328. // if it's already in the list then leave now.
  329. return TRUE;
  330. }
  331. if (dwIndex < MAX_EXITMSG-1) {
  332. // if not at the end of the list then continue
  333. dwIndex++;
  334. } else {
  335. // if this is the end of the list, the leave now.
  336. return FALSE;
  337. }
  338. }
  339. pData->uExitMessages[dwIndex] = nMessage; // add it to the list
  340. return TRUE; // and leave
  341. }
  342. int
  343. PositionWindow (
  344. IN HWND hwnd
  345. )
  346. /*++
  347. Routine Description:
  348. function to locate top-left corner of window in arg list in the
  349. same position as the last window
  350. Arguments:
  351. IN HWND hwnd
  352. handle of window to position
  353. Return Value:
  354. value returned by window positioning function called
  355. --*/
  356. {
  357. POINT ptWndCorner;
  358. if ((ptWndPos.x == -1) || (ptWndPos.y == -1)) {
  359. // position has not been initialized so center in desktop
  360. return CenterWindow (hwnd, GetDesktopWindow());
  361. } else {
  362. ptWndCorner = ptWndPos;
  363. // move to new location
  364. return SetWindowPos (hwnd,
  365. NULL,
  366. ptWndCorner.x,
  367. ptWndCorner.y,
  368. 0,0,
  369. SWP_NOSIZE | SWP_NOZORDER);
  370. }
  371. }
  372. int
  373. DisplayMessageBox (
  374. IN HWND hWndOwner,
  375. IN UINT nMsgId,
  376. IN UINT nTitleId,
  377. IN UINT nStyle
  378. )
  379. /*++
  380. Routine Description:
  381. displays message box containing a resource string as the text and
  382. title rather than a static string.
  383. Arguments:
  384. IN HWND hWndOwner
  385. hwnd of owner window
  386. IN UINT nMsgId
  387. Resource String ID of message string
  388. IN UINT nTitleId
  389. Resource String ID of title, 0 = use app name
  390. IN UINT nStyle
  391. Message box style bits
  392. Return Value:
  393. value returned by MessageBox API function
  394. --*/
  395. {
  396. int nReturn;
  397. LPTSTR szMessageString;
  398. LPTSTR szTitleString;
  399. HINSTANCE hInst;
  400. // allocate string buffers
  401. szTitleString = (LPTSTR)GlobalAlloc(GPTR, (MAX_PATH_BYTES));
  402. szMessageString = (LPTSTR)GlobalAlloc(GPTR, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
  403. #ifdef TERMSRV
  404. if (_tcschr(GetCommandLine(),TEXT('/')) != NULL )
  405. {
  406. if ((szMessageString != NULL) &&
  407. (szTitleString != NULL)) {
  408. hInst = (HINSTANCE)GetWindowLongPtr(hWndOwner,GWLP_HINSTANCE);
  409. LoadString (hInst,
  410. ((nTitleId != 0) ? nTitleId : WFC_STRING_BASE),
  411. szTitleString,
  412. MAX_PATH);
  413. LoadString (hInst,
  414. nMsgId,
  415. szMessageString,
  416. SMALL_BUFFER_SIZE);
  417. nReturn = MessageBox (
  418. hWndOwner,
  419. szMessageString,
  420. szTitleString,
  421. nStyle);
  422. } else {
  423. nReturn = 0;
  424. }
  425. }
  426. else
  427. {
  428. #endif // TERMSRV
  429. if ((szMessageString != NULL) &&
  430. (szTitleString != NULL)) {
  431. hInst = (HINSTANCE)GetWindowLongPtr(hWndOwner,GWLP_HINSTANCE);
  432. LoadString (hInst,
  433. ((nTitleId != 0) ? nTitleId : STRING_BASE),
  434. szTitleString,
  435. MAX_PATH);
  436. LoadString (hInst,
  437. nMsgId,
  438. szMessageString,
  439. SMALL_BUFFER_SIZE);
  440. nReturn = MessageBox (
  441. hWndOwner,
  442. szMessageString,
  443. szTitleString,
  444. nStyle);
  445. } else {
  446. nReturn = 0;
  447. }
  448. #ifdef TERMSRV
  449. }
  450. #endif // TERMSRV
  451. FREE_IF_ALLOC (szMessageString);
  452. FREE_IF_ALLOC (szTitleString);
  453. return nReturn;
  454. }
  455. VOID
  456. InitAppData (
  457. IN PNCDU_DATA pData
  458. )
  459. /*++
  460. Routine Description:
  461. initializes the fields in the application data structure
  462. Arguments:
  463. pointer to structure to initialize
  464. Return Value:
  465. None
  466. --*/
  467. {
  468. pData->mtLocalMachine = UnknownSoftwareType;
  469. pData->hkeyMachine = HKEY_LOCAL_MACHINE;
  470. pData->itInstall = OverTheNetInstall;
  471. pData->bUseExistingPath = FALSE;
  472. pData->shShareType = ShareExisting;
  473. pData->szDistShowPath[0] = 0;
  474. pData->szDistPath[0] = 0;
  475. pData->szDestPath[0] = 0;
  476. pData->stDistPathType = SourceUndef;
  477. pData->mtBootDriveType = F3_1Pt44_512;
  478. pData->bRemoteBootReqd = FALSE;
  479. pData->niNetCard.szName[0] = 0;
  480. pData->niNetCard.szInf[0] = 0;
  481. pData->niNetCard.szInfKey[0] = 0;
  482. pData->szBootFilesPath[0] = 0;
  483. pData->piFloppyProtocol.szName[0] = 0;
  484. pData->piFloppyProtocol.szKey[0] = 0;
  485. pData->piFloppyProtocol.szDir[0] = 0;
  486. pData->piTargetProtocol.szName[0] = 0;
  487. pData->piTargetProtocol.szKey[0] = 0;
  488. pData->piTargetProtocol.szDir[0] = 0;
  489. pData->szUsername[0] = 0;
  490. pData->szDomain[0] = 0;
  491. pData->bUseDhcp = TRUE;
  492. pData->tiTcpIpInfo.IpAddr[0] = 0;
  493. pData->tiTcpIpInfo.IpAddr[1] = 0;
  494. pData->tiTcpIpInfo.IpAddr[2] = 0;
  495. pData->tiTcpIpInfo.IpAddr[3] = 0;
  496. pData->tiTcpIpInfo.SubNetMask[0] = 0;
  497. pData->tiTcpIpInfo.SubNetMask[1] = 0;
  498. pData->tiTcpIpInfo.SubNetMask[2] = 0;
  499. pData->tiTcpIpInfo.SubNetMask[3] = 0;
  500. pData->tiTcpIpInfo.DefaultGateway[0] = 0;
  501. pData->tiTcpIpInfo.DefaultGateway[1] = 0;
  502. pData->tiTcpIpInfo.DefaultGateway[2] = 0;
  503. pData->tiTcpIpInfo.DefaultGateway[3] = 0;
  504. pData->szFloppyClientName[0] = 0;
  505. pData->uExitMessages[0] = 0;
  506. }
  507. int APIENTRY
  508. WinMain(
  509. IN HINSTANCE hInstance,
  510. IN HINSTANCE hPrevInstance,
  511. IN LPSTR szCmdLine,
  512. IN int nCmdShow
  513. )
  514. /*++
  515. Routine Description:
  516. Program entry point for LoadAccount application. Initializes Windows
  517. data structures and begins windows message processing loop.
  518. Arguments:
  519. Standard WinMain arguments
  520. ReturnValue:
  521. 0 if unable to initialize correctly, or
  522. wParam from WM_QUIT message if messages processed
  523. --*/
  524. {
  525. HWND hWnd; // Main window handle.
  526. MSG msg;
  527. LPTSTR szCaption;
  528. HANDLE hMap;
  529. #ifdef TERMSRV
  530. LPTSTR lpszCommandStr;
  531. TCHAR szProfilename[MAX_PATH + 1];
  532. DWORD dwLen;
  533. #endif // TERMSRV
  534. hMap = CreateFileMapping(INVALID_HANDLE_VALUE,
  535. NULL, PAGE_READONLY, 0, 32,
  536. szAppName);
  537. if(hMap)
  538. {
  539. if( GetLastError() == ERROR_ALREADY_EXISTS )
  540. {
  541. HWND hwnd = FindWindow(szAppName, NULL);
  542. if(IsIconic(hwnd))
  543. {
  544. ShowWindow(hwnd, SW_SHOWNORMAL);
  545. }
  546. SetForegroundWindow(hwnd);
  547. CloseHandle(hMap);
  548. hMap = NULL;
  549. return FALSE; // Other instance of the app running?
  550. }
  551. }
  552. if (!RegisterMainWindowClass(hInstance)) {
  553. return FALSE;
  554. }
  555. szCaption = GlobalAlloc (GPTR, (MAX_PATH * sizeof(TCHAR)));
  556. if (szCaption != NULL) {
  557. #ifdef TERMSRV
  558. if (_tcschr(GetCommandLine(),TEXT('/')) != NULL ) {
  559. LoadString (hInstance, WFC_STRING_BASE, szCaption, MAX_PATH);
  560. }
  561. else {
  562. return FALSE; // only allow terminal server client creator works.
  563. }
  564. #else // TERMSRV
  565. LoadString (hInstance, STRING_BASE, szCaption, MAX_PATH);
  566. #endif // TERMSRV
  567. } else {
  568. // not worth bailing out here, yet...
  569. szCaption = (LPTSTR)cszEmptyString;
  570. }
  571. hNetMsg = LoadLibrary (cszNetMsgDll);
  572. // initialize application data structure
  573. pAppInfo = GlobalAlloc (GPTR, sizeof(NCDU_DATA));
  574. if (pAppInfo != NULL) {
  575. InitAppData (pAppInfo);
  576. } else {
  577. // unable to allocate memory for applicattion data so bail out
  578. return FALSE;
  579. }
  580. #ifdef JAPAN
  581. usLangID = PRIMARYLANGID(GetSystemDefaultLangID());
  582. #endif
  583. // Create a main window for this application instance.
  584. // and position it off the screen
  585. hWnd = CreateWindowEx(
  586. 0L, // No extended attributes
  587. szAppName, // See RegisterClass() call.
  588. szCaption, // caption
  589. (DWORD)(WS_OVERLAPPEDWINDOW), // Window style.
  590. CW_USEDEFAULT, // Size is set later
  591. CW_USEDEFAULT,
  592. CW_USEDEFAULT,
  593. CW_USEDEFAULT,
  594. (HWND)NULL, // Overlapped windows have no parent.
  595. (HMENU)NULL, // Use the window class menu.
  596. hInstance, // This instance owns this window.
  597. NULL // We don't use any data in our WM_CREATE
  598. );
  599. // If window could not be created, return "failure"
  600. if (!hWnd) {
  601. return (FALSE);
  602. }
  603. // This application never shows it's main window but it's still
  604. // active!
  605. ShowWindow(hWnd, SW_SHOW); // Show the window
  606. SetWindowText (hWnd, szCaption); // update caption bar
  607. UpdateWindow(hWnd); // Sends WM_PAINT message
  608. #ifdef TERMSRV
  609. /* If using a command line parameter go get the path */
  610. lpszCommandStr = _tcschr(GetCommandLine(),TEXT('/'));
  611. if (lpszCommandStr != NULL ) {
  612. _tcscpy(szCommandLineVal, lpszCommandStr+1);
  613. }
  614. //
  615. // get help file name.
  616. //
  617. _tcscpy( szProfilename, szCommandLineVal );
  618. dwLen = _tcslen(szProfilename);
  619. if( szProfilename[dwLen - 1] != _T('\\') ) {
  620. szProfilename[dwLen++] = _T('\\');
  621. szProfilename[dwLen] = _T('\0');
  622. }
  623. _tcscat( szProfilename, cszOtnBootInf );
  624. dwLen =
  625. QuietGetPrivateProfileString(
  626. cszHelpSession,
  627. cszHelpFileNameKey,
  628. cszHelpFile,
  629. szHelpFileName,
  630. MAX_PATH,
  631. szProfilename );
  632. if( _tcscmp( szHelpFileName, cszHelpFile ) == 0 ) {
  633. szHelpFileName[0] = _T('\0');
  634. }
  635. #endif // TERMSRV
  636. /* Acquire and dispatch messages until a WM_QUIT message is received. */
  637. while (GetMessage(&msg, // message structure
  638. NULL, // handle of window receiving the message
  639. 0, // lowest message to examine
  640. 0)) // highest message to examine
  641. {
  642. TranslateMessage(&msg);// Translates virtual key codes
  643. DispatchMessage(&msg); // Dispatches message to window
  644. }
  645. if (szCaption != cszEmptyString) FREE_IF_ALLOC (szCaption);
  646. FREE_IF_ALLOC (pAppInfo);
  647. if (hNetMsg != NULL) FreeLibrary (hNetMsg);
  648. return (int)(msg.wParam); // Returns the value from PostQuitMessage
  649. }