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.

836 lines
21 KiB

  1. /* File: D:\WACKER\tdll\tdll.c (Created: 26-Nov-1993)
  2. *
  3. * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 22 $
  7. * $Date: 4/23/02 8:31a $
  8. */
  9. #include <windows.h>
  10. #pragma hdrstop
  11. #include <commctrl.h>
  12. #include "stdtyp.h"
  13. #include <term\res.h>
  14. #include "globals.h"
  15. #include "session.h"
  16. #include "assert.h"
  17. #include "misc.h"
  18. #include "tdll.h"
  19. #include "tdll\htchar.h"
  20. #include "vu_meter.h"
  21. #include "banner.h"
  22. #include "mc.h"
  23. #include "open_msc.h"
  24. #ifdef INCL_DEFAULT_TELNET_APP
  25. #include "telnetck.h"
  26. #endif
  27. #ifdef INCL_NAG_SCREEN
  28. #include "nagdlg.h"
  29. #include "register.h"
  30. #endif
  31. #include "term.h"
  32. #define SESSION_CLASS TEXT("SESSION_WINDOW")
  33. static BOOL InitDll(const HINSTANCE hInstance);
  34. static BOOL DetachDll(const HINSTANCE hInstance);
  35. static int HTCheckInstance(TCHAR *pachCmdLine);
  36. BOOL WINAPI TDllEntry(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpReserved);
  37. BOOL WINAPI _CRT_INIT(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpReserved);
  38. #if defined(INCL_PRIVATE_EDITION_BANNER)
  39. static HINSTANCE gRTFInstanceHandle = NULL;
  40. #if !defined(NT_EDITION)
  41. BOOL RegisterBannerAboutClass(HANDLE hInstance); // see aboutdlg.c
  42. BOOL UnregisterBannerAboutClass(HANDLE hInstance); // see aboutdlg.c
  43. #endif
  44. #endif
  45. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  46. * FUNCTION:
  47. * TDllEntry
  48. *
  49. * DESCRIPTION:
  50. * Currently, just initializes the C-Runtime library but may be used
  51. * for other things later.
  52. *
  53. * ARGUMENTS:
  54. * hInstDll - Instance of this DLL
  55. * fdwReason - Why this entry point is called
  56. * lpReserved - reserved
  57. *
  58. * RETURNS:
  59. * BOOL
  60. *
  61. */
  62. BOOL WINAPI TDllEntry(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpReserved)
  63. {
  64. /* --- Docs say to call _CRT_INIT before any of our code - mrw --- */
  65. if (_CRT_INIT(hInstDll, fdwReason, lpReserved) == FALSE)
  66. return FALSE;
  67. switch (fdwReason)
  68. {
  69. case DLL_PROCESS_ATTACH:
  70. if (!InitDll(hInstDll))
  71. {
  72. return FALSE;
  73. }
  74. break;
  75. case DLL_PROCESS_DETACH:
  76. if (!DetachDll(hInstDll))
  77. {
  78. return FALSE;
  79. }
  80. break;
  81. case DLL_THREAD_ATTACH:
  82. case DLL_THREAD_DETACH:
  83. default:
  84. break;
  85. }
  86. return TRUE;
  87. }
  88. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  89. * FUNCTION:
  90. * InitDll
  91. *
  92. * DESCRIPTION:
  93. * Intializes the application. Done only for the first instance.
  94. *
  95. */
  96. static BOOL InitDll(const HINSTANCE hInstance)
  97. {
  98. WNDCLASSEX wc;
  99. // Documentation says this should be called once per application
  100. // If we use any of the common controls which we do.
  101. if(GetDllVersion(TEXT("comctl32.dll")) >= PACKVERSION(4,70))
  102. {
  103. INITCOMMONCONTROLSEX sInit;
  104. sInit.dwSize = sizeof(INITCOMMONCONTROLSEX);
  105. sInit.dwICC = ICC_BAR_CLASSES | ICC_USEREX_CLASSES | ICC_WIN95_CLASSES;
  106. InitCommonControlsEx(&sInit);
  107. }
  108. else
  109. {
  110. InitCommonControls();
  111. }
  112. memset(&wc, 0, sizeof(WNDCLASSEX));
  113. wc.cbSize = sizeof(WNDCLASSEX);
  114. if (GetClassInfoEx(hInstance, SESSION_CLASS, &wc) == FALSE)
  115. {
  116. glblSetDllHinst(hInstance);
  117. // Read program's help file name from the resource file.
  118. // REV: 3/26/2002 Moved here so the shell extension
  119. // could use its context help.
  120. //
  121. glblSetHelpFileName();
  122. // Session Class
  123. wc.style = CS_HREDRAW | CS_VREDRAW;
  124. wc.lpfnWndProc = SessProc;
  125. wc.cbClsExtra = 0;
  126. wc.cbWndExtra = 0;
  127. wc.hInstance = hInstance;
  128. wc.hIcon = extLoadIcon(MAKEINTRESOURCE(IDI_PROG));
  129. wc.hCursor = LoadCursor(0, IDC_ARROW);
  130. wc.hbrBackground = NULL;
  131. wc.lpszMenuName = TEXT("MainMenu");
  132. wc.lpszClassName = SESSION_CLASS;
  133. wc.hIconSm = extLoadIcon(MAKEINTRESOURCE(IDI_PROG));
  134. if (RegisterClassEx(&wc) == FALSE)
  135. {
  136. assert(FALSE);
  137. return FALSE;
  138. }
  139. if (RegisterTerminalClass(hInstance) == FALSE)
  140. {
  141. assert(FALSE);
  142. return FALSE;
  143. }
  144. if (RegisterVuMeterClass(hInstance) == FALSE)
  145. {
  146. assert(FALSE);
  147. return FALSE;
  148. }
  149. if (RegisterSidebarClass(hInstance) == FALSE)
  150. {
  151. assert(FALSE);
  152. return FALSE;
  153. }
  154. #if !defined(NT_EDITION)
  155. #if defined(INCL_PRIVATE_EDITION_BANNER)
  156. if (RegisterBannerAboutClass(hInstance) == FALSE)
  157. {
  158. assert(FALSE);
  159. return FALSE;
  160. }
  161. #endif
  162. #endif
  163. }
  164. #if defined(INCL_PRIVATE_EDITION_BANNER)
  165. gRTFInstanceHandle = LoadLibrary("RICHED32");
  166. #endif
  167. return TRUE;
  168. }
  169. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  170. * FUNCTION:
  171. * InitInstance
  172. *
  173. * DESCRIPTION:
  174. * Creates the session window. Does instance specific stuff.
  175. *
  176. * ARGUMENTS:
  177. * HINSTANCE hInstance - apps instance handle.
  178. * LPTSTR lpCmdLine - copy of the command line.
  179. * int nCmdShow - passed from WinMain arg list.
  180. *
  181. */
  182. BOOL InitInstance(const HINSTANCE hInstance,
  183. const LPTSTR lpCmdLine,
  184. const int nCmdShow)
  185. {
  186. HWND hwnd;
  187. TCHAR ach[100];
  188. HACCEL hAccel;
  189. #if !defined(NT_EDITION)
  190. HWND hwndBanner;
  191. DWORD dwStart, dwNow;
  192. #endif
  193. #if !defined(NDEBUG)
  194. #if !defined(NO_SMARTHEAP)
  195. MemRegisterTask();
  196. #endif
  197. #endif
  198. // Save program's instance handle
  199. glblSetHinst(hInstance);
  200. if (HTCheckInstance(lpCmdLine) == TRUE)
  201. return FALSE;
  202. // Get program title
  203. LoadString(glblQueryDllHinst(),
  204. IDS_GNRL_APPNAME,
  205. ach,
  206. sizeof(ach) / sizeof(TCHAR));
  207. // Read program's help file name from the resource file.
  208. // JMH 12/12/96 Moved up here so the default telnet dialog
  209. // could use its context help.
  210. //
  211. // Now done in InitDLL() so that the help file is available
  212. // to the shell extension. REV: 3/26/2002
  213. //
  214. // glblSetHelpFileName();
  215. #ifdef INCL_NAG_SCREEN
  216. // Do the nag screen stuff
  217. //
  218. if ( IsEval() && IsTimeToNag() )
  219. {
  220. DoDialog(glblQueryDllHinst(),
  221. MAKEINTRESOURCE(IDD_NAG_SCREEN),
  222. 0,
  223. DefaultNagDlgProc,
  224. 0);
  225. }
  226. #ifdef NDEBUG
  227. // Display the registration reminder dialog if needed...
  228. //
  229. if (!IsRegisteredUser())
  230. {
  231. if (IsInitialRun())
  232. {
  233. DoRegister();
  234. SetLastReminderDate();
  235. }
  236. else if (IsWillingToBeReminded())
  237. {
  238. if (IsTimeToRemind())
  239. DoRegistrationReminderDlg(0);
  240. }
  241. }
  242. #endif // NDEBUG
  243. #endif // INCL_NAG_SCREEN
  244. #ifdef INCL_DEFAULT_TELNET_APP
  245. // Do the default telnet app stuff
  246. //
  247. if ( !IsHyperTerminalDefaultTelnetApp() && QueryTelnetCheckFlag() )
  248. {
  249. #ifndef NT_EDITION
  250. //ask the user if they want HT to be the default telnet app
  251. DoDialog(glblQueryDllHinst(), MAKEINTRESOURCE(IDD_DEFAULT_TELNET),
  252. 0, DefaultTelnetAppDlgProc, 0);
  253. #else
  254. //
  255. // Change back to always prompt per MS request. REV: 12/04/2000.
  256. //
  257. #if 0
  258. //mpt:8-9-97 MS asked us to make HT the default telnet app without asking - yippee!
  259. SetTelnetCheckFlag(FALSE); //so we don't check again
  260. SetDefaultTelnetApp(); //just do it without asking
  261. #endif
  262. //ask the user if they want HT to be the default telnet app
  263. DoDialog(glblQueryDllHinst(), MAKEINTRESOURCE(IDD_DEFAULT_TELNET),
  264. 0, DefaultTelnetAppDlgProc, 0);
  265. #endif // NT_EDITION
  266. }
  267. #endif // INCL_DEFAULT_TELNET_APP
  268. // Setup and display the banner
  269. #if !defined(NT_EDITION)
  270. bannerRegisterClass(glblQueryDllHinst());
  271. hwndBanner = bannerCreateBanner(glblQueryDllHinst(), ach);
  272. UpdateWindow(hwndBanner);
  273. glblSetHwndBanner(hwndBanner);
  274. dwStart = GetTickCount();
  275. #endif // !NT_EDITION
  276. // Load accerator table for program.
  277. hAccel = LoadAccelerators(glblQueryDllHinst(), MAKEINTRESOURCE(IDA_WACKER));
  278. if (hAccel == 0)
  279. {
  280. assert(FALSE);
  281. return FALSE;
  282. }
  283. glblSetAccelHdl(hAccel);
  284. // mpt:07-30-97
  285. if ( IsNT() )
  286. CreateUserDirectory();
  287. // Create a main window for this application instance. Pass command
  288. // line string as user data to be stored and acted on later.
  289. hwnd = CreateWindowEx(
  290. WS_EX_WINDOWEDGE,
  291. SESSION_CLASS,
  292. ach,
  293. WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  294. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  295. 0,
  296. 0,
  297. glblQueryDllHinst(),
  298. lpCmdLine
  299. );
  300. if (!IsWindow(hwnd))
  301. {
  302. assert(FALSE);
  303. return FALSE;
  304. }
  305. // Needed in the message loop unfortunately
  306. //
  307. glblSetHwndFrame(hwnd);
  308. #if !defined(NT_EDITION)
  309. // Leave banner up at least BANNER_TIME
  310. //
  311. if (!glblQueryProgramStatus())
  312. {
  313. dwNow = GetTickCount();
  314. if ( (dwNow - dwStart) < BANNER_TIME)
  315. {
  316. #ifdef USE_PRIVATE_EDITION_3_BANNER
  317. // The HTPE 3.0 banner has a button on it. If we just sleep,
  318. // no Windows messages will be processed, so you can't push
  319. // the button. We need to sleep, but we also need to pump
  320. // messages as well. - cab:11/29/96
  321. //
  322. Rest(BANNER_TIME - (dwNow - dwStart));
  323. #else
  324. Sleep(BANNER_TIME - (dwNow - dwStart));
  325. #endif
  326. }
  327. }
  328. #endif // !NT_EDITION
  329. // Post a message to size and show the window.
  330. //
  331. PostMessage(hwnd, WM_SESS_SIZE_SHOW, (WPARAM)nCmdShow, 0);
  332. // Posting this next messages kicks off the connection stuff
  333. //
  334. PostMessage(hwnd, WM_CMDLN_DIAL, (WPARAM)nCmdShow, 0);
  335. return TRUE;
  336. }
  337. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  338. * FUNCTION:
  339. * MessageLoop
  340. *
  341. * DESCRIPTION:
  342. * Wackers main message loop
  343. *
  344. * ARGUMENTS:
  345. * void
  346. *
  347. * RETURNS:
  348. * void
  349. *
  350. */
  351. int MessageLoop(void)
  352. {
  353. MSG msg;
  354. while (GetMessage(&msg, 0, 0, 0))
  355. {
  356. if (!CheckModelessMessage(&msg))
  357. ProcessMessage(&msg);
  358. }
  359. return (int)msg.wParam;
  360. }
  361. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  362. * FUNCTION:
  363. * GetFileNameFromCmdLine
  364. *
  365. * DESCRIPTION:
  366. * Extracts the file name, if any, from the command line and fully
  367. * qualifies it.
  368. *
  369. * ARGUMENTS:
  370. * pachCmdLine Copy of command line
  371. * pachFileName Place to put the result
  372. * nSize Size of buffer pointed to by pachFileName (in TCHARs)
  373. *
  374. * RETURNS:
  375. *
  376. *
  377. */
  378. int GetFileNameFromCmdLine(TCHAR *pachCmdLine, TCHAR *pachFileName, int nSize)
  379. {
  380. int nIdx = 0;
  381. TCHAR * pszStr;
  382. TCHAR acName[FNAME_LEN];
  383. TCHAR acPath[FNAME_LEN];
  384. TCHAR ach[_MAX_EXT];
  385. TCHAR * pachFile;
  386. TCHAR * pszTelnet = TEXT("telnet:"); //jmh 3/24/97
  387. int fTelnetCmdLnDial = FALSE;
  388. DWORD dwFile;
  389. // Make sure all the filename buffers are nulled out. REV: 11/14/2000.
  390. //
  391. TCHAR_Fill(pachFileName, TEXT('\0'), nSize);
  392. TCHAR_Fill(acName, TEXT('\0'), FNAME_LEN);
  393. TCHAR_Fill(acPath, TEXT('\0'), FNAME_LEN);
  394. nIdx = 0;
  395. //Just in case there is no command line. This happened when one specified '/t'
  396. //with no hostname on the command line - mpt 05/28/99
  397. if ( pachCmdLine[0] == TEXT('\0') )
  398. {
  399. return 0;
  400. }
  401. for (pszStr = pachCmdLine;
  402. *pszStr != TEXT('\0') && nIdx < nSize;
  403. pszStr = StrCharNext(pszStr))
  404. {
  405. /*
  406. * This works because we only allow certain characters as switches
  407. */
  408. if (*pszStr == TEXT('/'))
  409. {
  410. /* Process as a switch */
  411. pszStr = StrCharNext(pszStr); // skip the switch char
  412. //JMH 03-24-97 Test for special case here...
  413. if (*pszStr == TEXT('\0'))
  414. {
  415. break;
  416. }
  417. else if (*pszStr == TEXT('T') || *pszStr == TEXT('t'))
  418. {
  419. fTelnetCmdLnDial = TRUE;
  420. }
  421. }
  422. else
  423. {
  424. /* Copy all non switch stuff to the buffer */
  425. if (nIdx < (FNAME_LEN - 1))
  426. {
  427. // JFH:6/9/95 acName[nIdx++] = *pszStr;
  428. if (IsDBCSLeadByte(*pszStr))
  429. {
  430. MemCopy(&acName[nIdx], pszStr, (size_t)2 * sizeof(TCHAR));
  431. nIdx += 2;
  432. }
  433. else
  434. {
  435. acName[nIdx++] = *pszStr;
  436. }
  437. }
  438. }
  439. }
  440. if (nIdx == nSize)
  441. {
  442. acName[nIdx - 1] = TEXT('\0');
  443. }
  444. else
  445. {
  446. acName[nIdx] = TEXT('\0');
  447. }
  448. /* Trim leading and trailing spaces */
  449. pszStr = TCHAR_Trim(acName);
  450. //jmh 3/24/97 Needed to copy this from sessCheckAndLoadCmdLn(), and modify it
  451. // slightly. This needs to be here because it affects the filename, and we want
  452. // to make sure we're comparing the same name as in other instances.
  453. #if defined(INCL_WINSOCK)
  454. // If this is a telnet address from the browser, it will usually be preceeded
  455. // by the string telnet: If so, we must remove it or it will confuse some of
  456. // the code to follow jkh, 03/22/1997
  457. if (fTelnetCmdLnDial)
  458. {
  459. nIdx = StrCharGetStrLength(pszTelnet);
  460. if (StrCharCmpiN(acName, pszTelnet, nIdx) == 0)
  461. {
  462. // Remove the telnet string from the front of acName
  463. memmove(acName, &acName[nIdx], (StrCharGetStrLength(acName) - nIdx) + 1);
  464. }
  465. }
  466. // See if URL contains a port number. This will take the form of
  467. // addr:nnn where nnn is the port number i.e. culine.colorado.edu:860
  468. // or there might be the name of an assigned port like hilgraeve.com:finger.
  469. // We support numeric port right now, may add port names later. jkh, 3/22/1997
  470. pszStr = StrCharFindFirst(acName, TEXT(':'));
  471. if (pszStr && isdigit(pszStr[1]))
  472. {
  473. *pszStr = TEXT('\0');
  474. }
  475. #endif // defined(INCL_WINSOCK)
  476. // Now that the parsing is done, open the session file if one
  477. // was supplied. A session name that is not fully qualified may have
  478. // been passed in on the command line. Fully qulaify that name, then
  479. // carry on.
  480. //
  481. dwFile = GetFullPathName(acName, FNAME_LEN, acPath, &pachFile);
  482. if (dwFile > 0 && dwFile <= FNAME_LEN)
  483. {
  484. StrCharCopyN(acName, acPath, FNAME_LEN);
  485. }
  486. #if !defined(NDEBUG)
  487. else
  488. {
  489. DWORD dwLastError = GetLastError();
  490. assert(FALSE);
  491. }
  492. #endif //!defined(NDEBUG)
  493. // Get hypertrm extension
  494. //
  495. TCHAR_Fill(ach, TEXT('\0'), _MAX_EXT);
  496. LoadString(glblQueryDllHinst(), IDS_GNRL_HAS, ach, _MAX_EXT);
  497. // For now, lets assume all session files end in HT. If it
  498. // doesn't append the .HT. John Hile and I have discussed
  499. // this and feel it should be otherwise but don't want to
  500. // make a change this late in the ball game. - mrw,3/2/95
  501. //
  502. if ((pszStr = StrCharFindLast(acName, '.')))
  503. {
  504. if (StrCharCmpi(pszStr, ach) != 0 && StrCharCmpi(pszStr, ".TRM") != 0)
  505. {
  506. nIdx = StrCharGetStrLength(acName) + StrCharGetStrLength(ach);
  507. if(nIdx > nSize)
  508. {
  509. ach[nSize - StrCharGetStrLength(ach) - 1] = TEXT('\0');
  510. }
  511. StrCharCat(acName, ach);
  512. }
  513. }
  514. else
  515. {
  516. nIdx = StrCharGetStrLength(acName) + StrCharGetStrLength(ach);
  517. if(nIdx > nSize)
  518. {
  519. acName[nSize - StrCharGetStrLength(ach) - 1] = TEXT('\0');
  520. }
  521. StrCharCat(acName, ach);
  522. }
  523. if (acName[0] != TEXT('\0'))
  524. {
  525. // Convert the possible short file name (i.e., the 8.3 format)
  526. // to the long file name and save it.
  527. //
  528. dwFile = GetFullPathName(acName, FNAME_LEN, acPath, &pachFile);
  529. if (dwFile > 0 && dwFile <= FNAME_LEN)
  530. {
  531. StrCharCopyN(acName, acPath, FNAME_LEN);
  532. }
  533. #if !defined(NDEBUG)
  534. else
  535. {
  536. DWORD dwLastError = GetLastError();
  537. assert(FALSE);
  538. }
  539. #endif //!defined(NDEBUG)
  540. }
  541. StrCharCopyN(pachFileName, acName, nSize);
  542. pachFileName[nSize - 1] = TEXT('\0');
  543. return 0;
  544. }
  545. // Used for CheckInstCallback and HTCheckInstance
  546. //
  547. static int fKillTheApp;
  548. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  549. * FUNCTION:
  550. * CheckInstCallback
  551. *
  552. * DESCRIPTION:
  553. * Callback for EnumWindows
  554. *
  555. * ARGUMENTS:
  556. * hwnd - window handle from EmuWindows
  557. * lPar - optional data parameter (file name in this case)
  558. *
  559. * RETURNS:
  560. * FALSE if it finds another instance using the same file name.
  561. * TRUE if is doesn't
  562. *
  563. * AUTHOR: Mike Ward, 27-Jan-1995
  564. */
  565. BOOL CALLBACK CheckInstCallback(HWND hwnd, LPARAM lPar)
  566. {
  567. BOOL fRet = TRUE;
  568. TCHAR szClass[256];
  569. GetClassName(hwnd, szClass, sizeof(szClass));
  570. if (StrCharCmpi(szClass, SESSION_CLASS) == 0) // mrw, 2/12/95
  571. {
  572. ATOM aFile = GlobalAddAtom((TCHAR *)lPar);
  573. if (SendMessage(hwnd, WM_HT_QUERYOPENFILE, 0, (LPARAM)aFile))
  574. {
  575. if (!IsZoomed(hwnd))
  576. ShowWindow(hwnd, SW_RESTORE);
  577. SetForegroundWindow(hwnd);
  578. fKillTheApp = TRUE;
  579. fRet = FALSE;
  580. }
  581. GlobalDeleteAtom(aFile);
  582. }
  583. return fRet;
  584. }
  585. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  586. * FUNCTION:
  587. * CheckInstance
  588. *
  589. * DESCRIPTION:
  590. * Checks if another instance of HyperTerminal is using this file.
  591. *
  592. * ARGUMENTS:
  593. * pachFile - filename this guy is trying to open
  594. *
  595. * RETURNS:
  596. * TRUE=yes, another HT using it.
  597. * FALSE=nope
  598. *
  599. * AUTHOR: Mike Ward, 27-Jan-1995
  600. */
  601. static int HTCheckInstance(TCHAR *pachCmdLine)
  602. {
  603. TCHAR achPath[FNAME_LEN];
  604. // Make sure the filename buffer is nulled out. REV: 11/14/2000.
  605. //
  606. TCHAR_Fill(achPath, TEXT('\0'), FNAME_LEN);
  607. // Get the filename
  608. //
  609. GetFileNameFromCmdLine(pachCmdLine, achPath, FNAME_LEN);
  610. // If EnumWindows callback (CheckInstCallback) matches the given
  611. // path, it will set the fKillApp guy to TRUE
  612. //
  613. fKillTheApp = FALSE;
  614. // EnumWindows will give our callback toplevel windows one at a time
  615. //
  616. EnumWindows(CheckInstCallback, (LPARAM)achPath);
  617. return fKillTheApp;
  618. }
  619. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  620. * FUNCTION:
  621. * Rest
  622. *
  623. * DESCRIPTION:
  624. * This function causes the current thread to sleep for the given
  625. * number of milliseconds. However, it will still process Windows
  626. * messages.
  627. *
  628. * ARGUMENTS:
  629. * dwMilliSecs - Number of milliseconds to sleep for.
  630. *
  631. * AUTHOR: C. Baumgartner, 11/29/96
  632. */
  633. void Rest(DWORD dwMilliSecs)
  634. {
  635. MSG msg;
  636. DWORD dwStart = GetTickCount();
  637. DWORD dwStop = dwStart + dwMilliSecs;
  638. while( dwStop > GetTickCount() )
  639. {
  640. if ( GetMessage(&msg, NULL, 0, 0) )
  641. {
  642. TranslateMessage(&msg);
  643. DispatchMessage(&msg);
  644. }
  645. }
  646. }
  647. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  648. * FUNCTION:
  649. * DetachDll
  650. *
  651. * DESCRIPTION:
  652. * Intializes the application. Done only for the first instance.
  653. *
  654. */
  655. static BOOL DetachDll(const HINSTANCE hInstance)
  656. {
  657. BOOL lReturn = TRUE;
  658. #if !defined(NDEBUG)
  659. TCHAR acError[80];
  660. #endif // !defined(NDEBUG)
  661. // Release the RICHED32 library if it was loaded. REV: 11/09/2000.
  662. //
  663. #if defined(INCL_PRIVATE_EDITION_BANNER)
  664. if (gRTFInstanceHandle)
  665. {
  666. FreeLibrary(gRTFInstanceHandle);
  667. gRTFInstanceHandle = NULL;
  668. }
  669. #endif
  670. if (UnregisterClass(SESSION_CLASS, hInstance) == FALSE)
  671. {
  672. assert(FALSE);
  673. lReturn = FALSE;
  674. #if !defined(NDEBUG)
  675. wsprintf(acError, TEXT("UnregisterClass returned error %d"),
  676. GetLastError());
  677. MessageBox(NULL, acError, NULL, MB_OK);
  678. #endif // !defined(NDEBUG)
  679. }
  680. if (UnregisterTerminalClass(hInstance) == FALSE)
  681. {
  682. assert(FALSE);
  683. lReturn = FALSE;
  684. #if !defined(NDEBUG)
  685. wsprintf(acError, TEXT("UnregisterTerminalClass returned error %d"),
  686. GetLastError());
  687. MessageBox(NULL, acError, NULL, MB_OK);
  688. #endif // !defined(NDEBUG)
  689. }
  690. if (UnregisterVuMeterClass(hInstance) == FALSE)
  691. {
  692. assert(FALSE);
  693. lReturn = FALSE;
  694. #if !defined(NDEBUG)
  695. wsprintf(acError, TEXT("UnregisterVuMeterClass returned error %d"),
  696. GetLastError());
  697. MessageBox(NULL, acError, NULL, MB_OK);
  698. #endif // !defined(NDEBUG)
  699. }
  700. if (UnregisterSidebarClass(hInstance) == FALSE)
  701. {
  702. assert(FALSE);
  703. lReturn = FALSE;
  704. #if !defined(NDEBUG)
  705. wsprintf(acError, TEXT("UnregisterSidebarClass returned error %d"),
  706. GetLastError());
  707. MessageBox(NULL, acError, NULL, MB_OK);
  708. #endif // !defined(NDEBUG)
  709. }
  710. #if !defined(NT_EDITION)
  711. #if defined(INCL_PRIVATE_EDITION_BANNER)
  712. if (UnregisterBannerAboutClass(hInstance) == FALSE)
  713. {
  714. assert(FALSE);
  715. lReturn = FALSE;
  716. #if !defined(NDEBUG)
  717. wsprintf(acError, TEXT("UnregisterBannerAboutClass returned error %d"),
  718. GetLastError());
  719. MessageBox(NULL, acError, NULL, MB_OK);
  720. #endif // !defined(NDEBUG)
  721. }
  722. #endif
  723. #endif
  724. return lReturn;
  725. }