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.

867 lines
20 KiB

  1. /* File: D:\WACKER\tdll\misc.c (Created: 27-Nov-1993)
  2. *
  3. * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 14 $
  7. * $Date: 7/12/02 12:29p $
  8. */
  9. #include <windows.h>
  10. #pragma hdrstop
  11. #include <Shlwapi.h>
  12. #include "stdtyp.h"
  13. #include "misc.h"
  14. #include "tdll.h"
  15. #include "htchar.h"
  16. #include "globals.h"
  17. #include "assert.h"
  18. #include <term\res.h>
  19. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  20. * FUNCTION:
  21. * mscCenterWindowOnWindow
  22. *
  23. * DESCRIPTION:
  24. * Center's first window on the second window. Assumes hwndChild is
  25. * a direct descendant of hwndParent
  26. *
  27. * ARGUMENTS:
  28. * hwndChild - window to center
  29. * hwndParent - window to center on
  30. *
  31. * RETURNS:
  32. * BOOL
  33. *
  34. */
  35. BOOL mscCenterWindowOnWindow(const HWND hwndChild, const HWND hwndParent)
  36. {
  37. RECT rChild, rParent;
  38. int wChild, hChild, wParent, hParent;
  39. int xNew, yNew;
  40. int iMaxPos;
  41. if (!IsWindow(hwndParent))
  42. return FALSE;
  43. if (!IsWindow(hwndChild))
  44. return FALSE;
  45. /* --- Get the Height and Width of the child window --- */
  46. GetWindowRect(hwndChild, &rChild);
  47. wChild = rChild.right - rChild.left;
  48. hChild = rChild.bottom - rChild.top;
  49. /* --- Get the Height and Width of the parent window --- */
  50. GetWindowRect(hwndParent, &rParent);
  51. wParent = rParent.right - rParent.left;
  52. hParent = rParent.bottom - rParent.top;
  53. /* --- Calculate new X position, then adjust for screen --- */
  54. xNew = rParent.left + ((wParent - wChild) / 2);
  55. /* --- Calculate new Y position, then adjust for screen --- */
  56. // Let's display the dialog so that the title bar is visible.
  57. //
  58. iMaxPos = GetSystemMetrics(SM_CYSCREEN);
  59. yNew = min(iMaxPos, rParent.top + ((hParent - hChild) / 2));
  60. //mpt:3-13-98 Need to make sure dialog is not off the screen
  61. if (yNew < 0)
  62. {
  63. yNew = 0;
  64. }
  65. if (xNew < 0)
  66. {
  67. xNew = 0;
  68. }
  69. // Set it, and return
  70. //
  71. return SetWindowPos(hwndChild, 0, xNew, yNew, 0, 0,
  72. SWP_NOSIZE | SWP_NOZORDER);
  73. }
  74. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  75. * FUNCTION:
  76. * mscStripPath
  77. *
  78. * DESCRIPTION:
  79. * Strip off the path from the file name.
  80. *
  81. * ARGUMENTS:
  82. * pszStr - pointer to a null terminated string.
  83. *
  84. * RETURNS:
  85. * void.
  86. */
  87. LPTSTR mscStripPath(LPTSTR pszStr)
  88. {
  89. LPTSTR pszStart, psz;
  90. if (pszStr == 0)
  91. {
  92. return 0;
  93. }
  94. for (psz = pszStart = pszStr; *psz ; psz = StrCharNext(psz))
  95. {
  96. if (*psz == TEXT('\\') || *psz == TEXT(':'))
  97. pszStart = StrCharNext(psz);
  98. }
  99. StrCharCopyN(pszStr, pszStart, StrCharGetStrLength(pszStr));
  100. return pszStr;
  101. }
  102. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  103. * FUNCTION:
  104. * mscStripName
  105. *
  106. * DESCRIPTION:
  107. * Strip off the name of the file, leave just the path.
  108. *
  109. * ARGUMENTS:
  110. * pszStr - pointer to a null terminated string.
  111. *
  112. * RETURNS:
  113. * void.
  114. */
  115. LPTSTR mscStripName(LPTSTR pszStr)
  116. {
  117. LPTSTR pszEnd, pszStart = pszStr;
  118. if (pszStr == 0)
  119. return 0;
  120. for (pszEnd = pszStr; *pszStr; pszStr = StrCharNext(pszStr))
  121. {
  122. if (*pszStr == TEXT('\\') || *pszStr == TEXT(':'))
  123. pszEnd = StrCharNext(pszStr);
  124. }
  125. *pszEnd = TEXT('\0');
  126. return (pszStart);
  127. }
  128. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  129. * FUNCTION:
  130. * mscStripExt
  131. *
  132. * DESCRIPTION:
  133. * Strip off the file extension. The parameter string can be a full-path
  134. * or just a file name.
  135. *
  136. * ARGUMENTS:
  137. * pszStr - pointer to a null terminated string.
  138. *
  139. * RETURNS:
  140. * void.
  141. */
  142. LPTSTR mscStripExt(LPTSTR pszStr)
  143. {
  144. LPTSTR pszEnd, pszStart = pszStr;
  145. for (pszEnd = pszStr; *pszStr; pszStr = StrCharNext(pszStr))
  146. {
  147. // Need to check for both '.' and '\\' because directory names
  148. // can have extensions as well.
  149. //
  150. if (*pszStr == TEXT('.') || *pszStr == TEXT('\\'))
  151. pszEnd = pszStr;
  152. }
  153. if (*pszEnd == TEXT('.'))
  154. *pszEnd = TEXT('\0');
  155. return pszStart;
  156. }
  157. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  158. * FUNCTION:
  159. * mscModifyToFit
  160. *
  161. * DESCRIPTION:
  162. * If a string won't fit in a given window then chop-off as much as possible
  163. * to be able to display a part of the string with ellipsis concatanated to
  164. * the end of it.
  165. *
  166. * NOTE: I've attempted to make this code DBCS aware.
  167. *
  168. * ARGUMENTS:
  169. * hwnd - control window, where the text is to be displayed.
  170. * pszStr - pointer to the string to be displayed.
  171. * style - The control style for ellipsis.
  172. *
  173. * RETURNS:
  174. * lpszStr - pointer to the modified string.
  175. *
  176. */
  177. LPTSTR mscModifyToFit(HWND hwnd, LPTSTR pszStr, DWORD style)
  178. {
  179. if (!IsWindow(hwnd) || pszStr == NULL)
  180. {
  181. assert(FALSE);
  182. }
  183. else if (IsNT())
  184. {
  185. DWORD ExStyle;
  186. ExStyle = (DWORD)GetWindowLongPtr(hwnd, GWL_STYLE);
  187. if (!(ExStyle & style))
  188. {
  189. SetWindowLongPtr(hwnd, GWL_STYLE, (LONG_PTR)(ExStyle | style));
  190. }
  191. }
  192. else
  193. {
  194. HDC hDC;
  195. SIZE sz;
  196. HFONT hFontSave, hFont;
  197. RECT rc;
  198. int nWidth = 0;
  199. memset(&hFont, 0, sizeof(HFONT));
  200. memset(&hFontSave, 0, sizeof(HFONT));
  201. memset(&rc, 0, sizeof(RECT));
  202. GetWindowRect(hwnd, &rc);
  203. nWidth = rc.right - rc.left;
  204. hDC = GetDC(hwnd);
  205. hFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0);
  206. if (hFont)
  207. {
  208. hFontSave = SelectObject(hDC, hFont);
  209. }
  210. // TODO: I think here the string pszStr would have to be "deflated"
  211. // before we continue. The rest of the code should stay the same.
  212. //
  213. GetTextExtentPoint(hDC, (LPCTSTR)pszStr, StrCharGetStrLength(pszStr), &sz);
  214. if (sz.cx > nWidth)
  215. {
  216. int nEllipsisLength = 0;
  217. int i = 0;
  218. TCHAR ach[512];
  219. TCHAR achEllipsis[10];
  220. TCHAR_Fill(ach, TEXT('\0'), 512);
  221. TCHAR_Fill(achEllipsis, TEXT('\0'), 10);
  222. LoadString(glblQueryDllHinst(), IDS_GNRL_ELLIPSIS,
  223. achEllipsis, 10);
  224. nEllipsisLength = StrCharGetStrLength(achEllipsis);
  225. StrCharCopyN(ach, pszStr, (sizeof(ach) - nEllipsisLength) / sizeof(TCHAR));
  226. StrCharCat(ach, achEllipsis);
  227. i = StrCharGetStrLength(ach);
  228. while ((i > nEllipsisLength) && (sz.cx > nWidth))
  229. {
  230. GetTextExtentPoint(hDC, ach, i, &sz);
  231. i -= 1;
  232. ach[i - nEllipsisLength] = TEXT('\0');
  233. StrCharCat(ach, achEllipsis);
  234. }
  235. // Now copy the temporary string back into the original buffer.
  236. //
  237. StrCharCopyN(pszStr, ach, sizeof(ach) / sizeof(TCHAR));
  238. }
  239. // Select the previously selected font, release DC.
  240. //
  241. if (hFontSave)
  242. {
  243. SelectObject(hDC, hFontSave);
  244. }
  245. ReleaseDC(hwnd, hDC);
  246. }
  247. return pszStr;
  248. }
  249. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  250. * FUNCTION:
  251. * mscResetComboBox
  252. *
  253. * DESCRIPTION:
  254. * The modem combobox allocates memory to store info about each item.
  255. * This routine will free those allocated chunks.
  256. *
  257. * ARGUMENTS:
  258. * hwnd - window handle to combobox
  259. *
  260. * RETURNS:
  261. * void
  262. *
  263. */
  264. void mscResetComboBox(const HWND hwnd)
  265. {
  266. void *pv = NULL;
  267. LRESULT lr, i;
  268. if (!IsWindow(hwnd))
  269. {
  270. return;
  271. }
  272. if ((lr = SendMessage(hwnd, CB_GETCOUNT, 0, 0)) != CB_ERR)
  273. {
  274. for (i = 0 ; i < lr ; ++i)
  275. {
  276. if (((LRESULT)pv = SendMessage(hwnd, CB_GETITEMDATA, (WPARAM)i, 0))
  277. != CB_ERR)
  278. {
  279. if (pv)
  280. {
  281. free(pv);
  282. pv = NULL;
  283. }
  284. }
  285. }
  286. }
  287. SendMessage(hwnd, CB_RESETCONTENT, 0, 0);
  288. return;
  289. }
  290. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  291. * FUNCTION:
  292. * extLoadIcon
  293. *
  294. * DESCRIPTION:
  295. * Gets the icon from the hticons.dll. The extension handlers use
  296. * this dll for icons and need to not link load anything more than
  297. * absolutely necessary, otherwise, this function would go in the
  298. * icon handler code.
  299. *
  300. * ARGUMENTS:
  301. * id - string id of resource (can be MAKEINTRESOURCE)
  302. *
  303. * RETURNS:
  304. * HICON or zero on error.
  305. *
  306. */
  307. HICON extLoadIcon(LPCSTR id)
  308. {
  309. static HINSTANCE hInstance;
  310. if (hInstance == 0)
  311. {
  312. if ((hInstance = LoadLibrary("hticons")) == 0)
  313. {
  314. assert(FALSE);
  315. return 0;
  316. }
  317. }
  318. return LoadIcon(hInstance, id);
  319. }
  320. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  321. * FUNCTION:
  322. * mscCreatePath
  323. *
  324. * DESCRIPTION:
  325. * Creates the given path. This function is somewhat tricky so study
  326. * it carefully before modifying it. Despite it's simplicity, it
  327. * accounts for all boundary conditions. - mrw
  328. *
  329. * ARGUMENTS:
  330. * pszPath - path to create
  331. *
  332. * RETURNS:
  333. * 0=OK,else error
  334. *
  335. */
  336. int mscCreatePath(const TCHAR *pszPath)
  337. {
  338. TCHAR ach[512];
  339. TCHAR *pachTok;
  340. if (pszPath == 0)
  341. return -1;
  342. StrCharCopyN(ach, pszPath, sizeof(ach) / sizeof(TCHAR));
  343. pachTok = ach;
  344. // Basicly, we march along the string until we encounter a '\', flip
  345. // it to a NULL and try to create the path up to that point.
  346. // It would have been nice if CreateDirectory() could
  347. // create sub/sub directories, but it don't. - mrw
  348. //
  349. while (1)
  350. {
  351. if ((pachTok = StrCharFindFirst(pachTok, TEXT('\\'))) == 0)
  352. {
  353. if (!mscIsDirectory(ach) && !CreateDirectory(ach, 0))
  354. return -2;
  355. break;
  356. }
  357. if (pachTok != ach)
  358. {
  359. *pachTok = TEXT('\0');
  360. if (!mscIsDirectory(ach) && !CreateDirectory(ach, 0))
  361. return -3;
  362. *pachTok = TEXT('\\');
  363. }
  364. pachTok = StrCharNext(pachTok);
  365. }
  366. return 0;
  367. }
  368. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  369. * FUNCTION:
  370. * mscIsDirectory
  371. *
  372. * DESCRIPTION:
  373. * Checks to see if a string is a valid directory or not.
  374. *
  375. * PARAMETERS:
  376. * pszName -- the string to test
  377. *
  378. * RETURNS:
  379. * TRUE if the string is a valid directory, otherwise FALSE.
  380. *
  381. */
  382. int mscIsDirectory(LPCTSTR pszName)
  383. {
  384. DWORD dw;
  385. dw = GetFileAttributes(pszName);
  386. if ((dw != (DWORD)-1) && (dw & FILE_ATTRIBUTE_DIRECTORY))
  387. return TRUE;
  388. return FALSE;
  389. }
  390. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  391. * FUNCTION:
  392. * mscAskWizardQuestionAgain
  393. *
  394. * DESCRIPTION:
  395. * Reads a value from the Registry. This value represents how many times
  396. * the user responded "NO" to the question: "Do you want to run the
  397. * New Modem Wizard?". We won't ask this question any more if the
  398. * user responded no, twice.
  399. *
  400. * PARAMETERS:
  401. * None
  402. *
  403. * RETURNS:
  404. * TRUE if the modem wizard question should be asked again, otherwize
  405. * FALSE.
  406. *
  407. */
  408. int mscAskWizardQuestionAgain(void)
  409. {
  410. long lResult;
  411. DWORD dwKeyValue = 0;
  412. DWORD dwSize;
  413. DWORD dwType;
  414. TCHAR *pszAppKey = "HYPERTERMINAL";
  415. dwSize = sizeof(DWORD);
  416. lResult = RegQueryValueEx(HKEY_CLASSES_ROOT, (LPTSTR)pszAppKey, 0,
  417. &dwType, (LPBYTE)&dwKeyValue, &dwSize);
  418. // If we are able to read a value from the registry and that value
  419. // is 1, there is no need to ask the question again, so return
  420. // a false value.
  421. //
  422. if ( (lResult == ERROR_SUCCESS) && (dwKeyValue >= 1) )
  423. return (FALSE);
  424. return (TRUE);
  425. }
  426. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  427. * FUNCTION:
  428. * mscUpdateRegistryValue
  429. *
  430. * DESCRIPTION:
  431. * See mscAskWizardQuestionAgain. If the user responds "NO" to this
  432. * question, we update a counter in the registry.
  433. *
  434. * PARAMETERS:
  435. * None
  436. *
  437. * RETURNS:
  438. * void
  439. *
  440. */
  441. void mscUpdateRegistryValue(void)
  442. {
  443. long lResult;
  444. DWORD dwKeyValue = 0;
  445. DWORD dwSize;
  446. DWORD dwType;
  447. TCHAR *pszAppKey = "HYPERTERMINAL";
  448. dwSize = sizeof(DWORD);
  449. lResult = RegQueryValueEx(HKEY_CLASSES_ROOT, (LPTSTR)pszAppKey, 0,
  450. &dwType, (LPBYTE)&dwKeyValue, &dwSize);
  451. dwKeyValue += 1;
  452. lResult = RegSetValueEx(HKEY_CLASSES_ROOT, pszAppKey, 0,
  453. REG_BINARY, (LPBYTE)&dwKeyValue, dwSize);
  454. assert(lResult == ERROR_SUCCESS);
  455. return;
  456. }
  457. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  458. * FUNCTION:
  459. * mscMessageBeep
  460. *
  461. * DESCRIPTION:
  462. * Play a MessageBeep
  463. *
  464. * ARGUMENTS:
  465. * aBeep - the Beep sound to play
  466. *
  467. * RETURNS:
  468. * return value from MessageBeep().
  469. *
  470. */
  471. INT_PTR mscMessageBeep(UINT aBeep)
  472. {
  473. //
  474. // Play the system exclamation sound. If this session is running
  475. // in a Terminal Service session (Remote Desktop Connection) then
  476. // issue MessageBeep((UINT)-1) so that the sound is transfered to
  477. // the remote machine. REV: 3/25/2002
  478. //
  479. return (MessageBeep((IsTerminalServicesEnabled() == TRUE) ?
  480. (UINT)-1 :
  481. aBeep));
  482. }
  483. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  484. * FUNCTION:
  485. * IsNT
  486. *
  487. * DESCRIPTION: Determines if we are running under Windows NT
  488. *
  489. * ARGUMENTS:
  490. * None.
  491. *
  492. * RETURNS:
  493. * True if NT
  494. *
  495. * Author: MPT 7-31-97
  496. */
  497. INT_PTR IsNT(void)
  498. {
  499. static BOOL bChecked = FALSE; // We have not made this check yet.
  500. static BOOL bResult = FALSE; // assume we are not NT/Win2K/XP
  501. if (bChecked == FALSE)
  502. {
  503. #if DEADWOOD
  504. OSVERSIONINFO stOsVersion;
  505. stOsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  506. if (GetVersionEx(&stOsVersion))
  507. {
  508. bResult = ( stOsVersion.dwPlatformId == VER_PLATFORM_WIN32_NT );
  509. }
  510. #else // DEADWOOD
  511. DWORD dwVersion = GetVersion();
  512. bResult = ( !( dwVersion & 0x80000000 ) );
  513. #endif // DEADWOOD
  514. bChecked = TRUE;
  515. }
  516. return bResult;
  517. }
  518. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  519. * FUNCTION:
  520. * GetWindowsMajorVersion
  521. *
  522. * DESCRIPTION: Returns the major version of Windows we are running.
  523. *
  524. * ARGUMENTS:
  525. * None.
  526. *
  527. * RETURNS:
  528. * True if NT
  529. *
  530. * Author: MPT 7-31-97
  531. */
  532. DWORD GetWindowsMajorVersion(void)
  533. {
  534. OSVERSIONINFO stOsVersion;
  535. stOsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  536. if (GetVersionEx(&stOsVersion))
  537. {
  538. return stOsVersion.dwMajorVersion;
  539. }
  540. return 0;
  541. }
  542. //
  543. // The following two functions are from code obtained directly
  544. // from MSDN for determining if you are currently running as a
  545. // remote session (Terminal Service). REV: 10/03/2001
  546. //
  547. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  548. * FUNCTION:
  549. * ValidateProductSuite
  550. *
  551. * DESCRIPTION:
  552. * This function compares the passed in "suite name" string
  553. * to the product suite information stored in the registry.
  554. * This only works on the Terminal Server 4.0 platform.
  555. *
  556. * ARGUMENTS:
  557. * SuiteName - Suite name.
  558. *
  559. * RETURNS:
  560. * BOOL
  561. *
  562. */
  563. BOOL ValidateProductSuite ( LPSTR SuiteName )
  564. {
  565. BOOL rVal = FALSE;
  566. LONG Rslt;
  567. HKEY hKey = NULL;
  568. DWORD Type = 0;
  569. DWORD Size = 0;
  570. LPSTR ProductSuite = NULL;
  571. LPSTR p;
  572. Rslt = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  573. "System\\CurrentControlSet\\Control\\ProductOptions",
  574. 0, KEY_READ,
  575. &hKey );
  576. if ( Rslt != ERROR_SUCCESS )
  577. {
  578. goto exit;
  579. }
  580. Rslt = RegQueryValueEx( hKey, "ProductSuite", NULL, &Type, NULL, &Size );
  581. if ( Rslt != ERROR_SUCCESS || !Size )
  582. {
  583. goto exit;
  584. }
  585. ProductSuite = (LPSTR) LocalAlloc( LPTR, Size );
  586. if ( !ProductSuite )
  587. {
  588. goto exit;
  589. }
  590. Rslt = RegQueryValueEx( hKey, "ProductSuite", NULL, &Type,
  591. (LPBYTE) ProductSuite, &Size );
  592. if ( Rslt != ERROR_SUCCESS || Type != REG_MULTI_SZ )
  593. {
  594. goto exit;
  595. }
  596. p = ProductSuite;
  597. while ( *p )
  598. {
  599. if ( lstrcmp( p, SuiteName ) == 0 )
  600. {
  601. rVal = TRUE;
  602. break;
  603. }
  604. p += ( lstrlen( p ) + 1 );
  605. }
  606. exit:
  607. if ( ProductSuite )
  608. {
  609. LocalFree( ProductSuite );
  610. }
  611. if ( hKey )
  612. {
  613. RegCloseKey( hKey );
  614. }
  615. return rVal;
  616. }
  617. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  618. * FUNCTION:
  619. * IsTerminalServicesEnabled
  620. *
  621. * DESCRIPTION:
  622. * This function performs the basic check to see if
  623. * the platform on which it is running is Terminal
  624. * services enabled. Note, this code is compatible on
  625. * all Win32 platforms. For the Windows 2000 platform
  626. * we perform a "lazy" bind to the new product suite
  627. * APIs that were first introduced on that platform.
  628. *
  629. * ARGUMENTS:
  630. * VOID
  631. *
  632. * RETURNS:
  633. * BOOL
  634. *
  635. */
  636. INT_PTR IsTerminalServicesEnabled( void )
  637. {
  638. static BOOL checked = FALSE; // We have not made this check yet.
  639. static BOOL bResult = FALSE; // assume Terminal Services is not enabled
  640. if (!checked)
  641. {
  642. DWORD dwVersion = GetVersion();
  643. // are we running NT ?
  644. if ( !( dwVersion & 0x80000000 ) )
  645. {
  646. // Is it Windows 2000 (NT 5.0) or greater ?
  647. if ( LOBYTE( LOWORD( dwVersion ) ) > 4 )
  648. {
  649. #if(WINVER >= 0x0500)
  650. bResult = GetSystemMetrics( SM_REMOTESESSION );
  651. checked = TRUE;
  652. #else // (WINVER >= 0x0500)
  653. // In Windows 2000 we need to use the Product Suite APIs
  654. // Don�t static link because it won�t load on non-Win2000 systems
  655. OSVERSIONINFOEXA osVersionInfo;
  656. DWORDLONG dwlConditionMask = 0;
  657. HMODULE hmodK32 = NULL;
  658. HMODULE hmodNtDll = NULL;
  659. typedef ULONGLONG (*PFnVerSetConditionMask)(ULONGLONG,ULONG,UCHAR);
  660. typedef BOOL (*PFnVerifyVersionInfoA) ( POSVERSIONINFOEXA, DWORD, DWORDLONG );
  661. PFnVerSetConditionMask pfnVerSetConditionMask;
  662. PFnVerifyVersionInfoA pfnVerifyVersionInfoA;
  663. hmodNtDll = GetModuleHandleA( "ntdll.dll" );
  664. if ( hmodNtDll != NULL )
  665. {
  666. pfnVerSetConditionMask =
  667. ( PFnVerSetConditionMask )GetProcAddress( hmodNtDll, "VerSetConditionMask");
  668. if ( pfnVerSetConditionMask != NULL )
  669. {
  670. dwlConditionMask =
  671. (*pfnVerSetConditionMask)( dwlConditionMask, VER_SUITENAME, VER_AND );
  672. hmodK32 = GetModuleHandleA( "KERNEL32.DLL" );
  673. if ( hmodK32 != NULL )
  674. {
  675. pfnVerifyVersionInfoA =
  676. (PFnVerifyVersionInfoA)GetProcAddress( hmodK32, "VerifyVersionInfoA" ) ;
  677. if ( pfnVerifyVersionInfoA != NULL )
  678. {
  679. ZeroMemory( &osVersionInfo, sizeof(osVersionInfo) );
  680. osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
  681. osVersionInfo.wSuiteMask = VER_SUITE_TERMINAL;
  682. bResult = (*pfnVerifyVersionInfoA)( &osVersionInfo,
  683. VER_SUITENAME,
  684. dwlConditionMask );
  685. checked = TRUE;
  686. }
  687. }
  688. }
  689. }
  690. #endif(WINVER >= 0x0500)
  691. }
  692. else
  693. {
  694. // This is NT 4.0 or older
  695. bResult = ValidateProductSuite( "Terminal Server" );
  696. checked = TRUE;
  697. }
  698. }
  699. }
  700. return bResult;
  701. }
  702. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  703. * FUNCTION:
  704. * GetDllVersion
  705. *
  706. * DESCRIPTION: Returns the version of a given DLL.
  707. *
  708. * ARGUMENTS:
  709. * lpszDllName - Name of the DLL to check the version number of.
  710. *
  711. * RETURNS:
  712. * The DLL's version number.
  713. *
  714. * Author: REV 4-16-2002
  715. */
  716. DWORD GetDllVersion(LPCTSTR lpszDllName)
  717. {
  718. HINSTANCE hinstDll;
  719. DWORD dwVersion = 0;
  720. hinstDll = LoadLibrary(lpszDllName);
  721. if(hinstDll)
  722. {
  723. DLLGETVERSIONPROC pDllGetVersion;
  724. pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion");
  725. /*Because some DLLs might not implement this function, you
  726. must test for it explicitly. Depending on the particular
  727. DLL, the lack of a DllGetVersion function can be a useful
  728. indicator of the version.
  729. */
  730. if(pDllGetVersion)
  731. {
  732. DLLVERSIONINFO dvi;
  733. HRESULT hr;
  734. ZeroMemory(&dvi, sizeof(dvi));
  735. dvi.cbSize = sizeof(dvi);
  736. hr = (*pDllGetVersion)(&dvi);
  737. if(SUCCEEDED(hr))
  738. {
  739. dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion);
  740. }
  741. }
  742. FreeLibrary(hinstDll);
  743. }
  744. return dwVersion;
  745. }