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

/* File: D:\WACKER\tdll\misc.c (Created: 27-Nov-1993)
*
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 14 $
* $Date: 7/12/02 12:29p $
*/
#include <windows.h>
#pragma hdrstop
#include <Shlwapi.h>
#include "stdtyp.h"
#include "misc.h"
#include "tdll.h"
#include "htchar.h"
#include "globals.h"
#include "assert.h"
#include <term\res.h>
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* mscCenterWindowOnWindow
*
* DESCRIPTION:
* Center's first window on the second window. Assumes hwndChild is
* a direct descendant of hwndParent
*
* ARGUMENTS:
* hwndChild - window to center
* hwndParent - window to center on
*
* RETURNS:
* BOOL
*
*/
BOOL mscCenterWindowOnWindow(const HWND hwndChild, const HWND hwndParent)
{
RECT rChild, rParent;
int wChild, hChild, wParent, hParent;
int xNew, yNew;
int iMaxPos;
if (!IsWindow(hwndParent))
return FALSE;
if (!IsWindow(hwndChild))
return FALSE;
/* --- Get the Height and Width of the child window --- */
GetWindowRect(hwndChild, &rChild);
wChild = rChild.right - rChild.left;
hChild = rChild.bottom - rChild.top;
/* --- Get the Height and Width of the parent window --- */
GetWindowRect(hwndParent, &rParent);
wParent = rParent.right - rParent.left;
hParent = rParent.bottom - rParent.top;
/* --- Calculate new X position, then adjust for screen --- */
xNew = rParent.left + ((wParent - wChild) / 2);
/* --- Calculate new Y position, then adjust for screen --- */
// Let's display the dialog so that the title bar is visible.
//
iMaxPos = GetSystemMetrics(SM_CYSCREEN);
yNew = min(iMaxPos, rParent.top + ((hParent - hChild) / 2));
//mpt:3-13-98 Need to make sure dialog is not off the screen
if (yNew < 0)
{
yNew = 0;
}
if (xNew < 0)
{
xNew = 0;
}
// Set it, and return
//
return SetWindowPos(hwndChild, 0, xNew, yNew, 0, 0,
SWP_NOSIZE | SWP_NOZORDER);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* mscStripPath
*
* DESCRIPTION:
* Strip off the path from the file name.
*
* ARGUMENTS:
* pszStr - pointer to a null terminated string.
*
* RETURNS:
* void.
*/
LPTSTR mscStripPath(LPTSTR pszStr)
{
LPTSTR pszStart, psz;
if (pszStr == 0)
{
return 0;
}
for (psz = pszStart = pszStr; *psz ; psz = StrCharNext(psz))
{
if (*psz == TEXT('\\') || *psz == TEXT(':'))
pszStart = StrCharNext(psz);
}
StrCharCopyN(pszStr, pszStart, StrCharGetStrLength(pszStr));
return pszStr;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* mscStripName
*
* DESCRIPTION:
* Strip off the name of the file, leave just the path.
*
* ARGUMENTS:
* pszStr - pointer to a null terminated string.
*
* RETURNS:
* void.
*/
LPTSTR mscStripName(LPTSTR pszStr)
{
LPTSTR pszEnd, pszStart = pszStr;
if (pszStr == 0)
return 0;
for (pszEnd = pszStr; *pszStr; pszStr = StrCharNext(pszStr))
{
if (*pszStr == TEXT('\\') || *pszStr == TEXT(':'))
pszEnd = StrCharNext(pszStr);
}
*pszEnd = TEXT('\0');
return (pszStart);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* mscStripExt
*
* DESCRIPTION:
* Strip off the file extension. The parameter string can be a full-path
* or just a file name.
*
* ARGUMENTS:
* pszStr - pointer to a null terminated string.
*
* RETURNS:
* void.
*/
LPTSTR mscStripExt(LPTSTR pszStr)
{
LPTSTR pszEnd, pszStart = pszStr;
for (pszEnd = pszStr; *pszStr; pszStr = StrCharNext(pszStr))
{
// Need to check for both '.' and '\\' because directory names
// can have extensions as well.
//
if (*pszStr == TEXT('.') || *pszStr == TEXT('\\'))
pszEnd = pszStr;
}
if (*pszEnd == TEXT('.'))
*pszEnd = TEXT('\0');
return pszStart;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* mscModifyToFit
*
* DESCRIPTION:
* If a string won't fit in a given window then chop-off as much as possible
* to be able to display a part of the string with ellipsis concatanated to
* the end of it.
*
* NOTE: I've attempted to make this code DBCS aware.
*
* ARGUMENTS:
* hwnd - control window, where the text is to be displayed.
* pszStr - pointer to the string to be displayed.
* style - The control style for ellipsis.
*
* RETURNS:
* lpszStr - pointer to the modified string.
*
*/
LPTSTR mscModifyToFit(HWND hwnd, LPTSTR pszStr, DWORD style)
{
if (!IsWindow(hwnd) || pszStr == NULL)
{
assert(FALSE);
}
else if (IsNT())
{
DWORD ExStyle;
ExStyle = (DWORD)GetWindowLongPtr(hwnd, GWL_STYLE);
if (!(ExStyle & style))
{
SetWindowLongPtr(hwnd, GWL_STYLE, (LONG_PTR)(ExStyle | style));
}
}
else
{
HDC hDC;
SIZE sz;
HFONT hFontSave, hFont;
RECT rc;
int nWidth = 0;
memset(&hFont, 0, sizeof(HFONT));
memset(&hFontSave, 0, sizeof(HFONT));
memset(&rc, 0, sizeof(RECT));
GetWindowRect(hwnd, &rc);
nWidth = rc.right - rc.left;
hDC = GetDC(hwnd);
hFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0);
if (hFont)
{
hFontSave = SelectObject(hDC, hFont);
}
// TODO: I think here the string pszStr would have to be "deflated"
// before we continue. The rest of the code should stay the same.
//
GetTextExtentPoint(hDC, (LPCTSTR)pszStr, StrCharGetStrLength(pszStr), &sz);
if (sz.cx > nWidth)
{
int nEllipsisLength = 0;
int i = 0;
TCHAR ach[512];
TCHAR achEllipsis[10];
TCHAR_Fill(ach, TEXT('\0'), 512);
TCHAR_Fill(achEllipsis, TEXT('\0'), 10);
LoadString(glblQueryDllHinst(), IDS_GNRL_ELLIPSIS,
achEllipsis, 10);
nEllipsisLength = StrCharGetStrLength(achEllipsis);
StrCharCopyN(ach, pszStr, (sizeof(ach) - nEllipsisLength) / sizeof(TCHAR));
StrCharCat(ach, achEllipsis);
i = StrCharGetStrLength(ach);
while ((i > nEllipsisLength) && (sz.cx > nWidth))
{
GetTextExtentPoint(hDC, ach, i, &sz);
i -= 1;
ach[i - nEllipsisLength] = TEXT('\0');
StrCharCat(ach, achEllipsis);
}
// Now copy the temporary string back into the original buffer.
//
StrCharCopyN(pszStr, ach, sizeof(ach) / sizeof(TCHAR));
}
// Select the previously selected font, release DC.
//
if (hFontSave)
{
SelectObject(hDC, hFontSave);
}
ReleaseDC(hwnd, hDC);
}
return pszStr;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* mscResetComboBox
*
* DESCRIPTION:
* The modem combobox allocates memory to store info about each item.
* This routine will free those allocated chunks.
*
* ARGUMENTS:
* hwnd - window handle to combobox
*
* RETURNS:
* void
*
*/
void mscResetComboBox(const HWND hwnd)
{
void *pv = NULL;
LRESULT lr, i;
if (!IsWindow(hwnd))
{
return;
}
if ((lr = SendMessage(hwnd, CB_GETCOUNT, 0, 0)) != CB_ERR)
{
for (i = 0 ; i < lr ; ++i)
{
if (((LRESULT)pv = SendMessage(hwnd, CB_GETITEMDATA, (WPARAM)i, 0))
!= CB_ERR)
{
if (pv)
{
free(pv);
pv = NULL;
}
}
}
}
SendMessage(hwnd, CB_RESETCONTENT, 0, 0);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* extLoadIcon
*
* DESCRIPTION:
* Gets the icon from the hticons.dll. The extension handlers use
* this dll for icons and need to not link load anything more than
* absolutely necessary, otherwise, this function would go in the
* icon handler code.
*
* ARGUMENTS:
* id - string id of resource (can be MAKEINTRESOURCE)
*
* RETURNS:
* HICON or zero on error.
*
*/
HICON extLoadIcon(LPCSTR id)
{
static HINSTANCE hInstance;
if (hInstance == 0)
{
if ((hInstance = LoadLibrary("hticons")) == 0)
{
assert(FALSE);
return 0;
}
}
return LoadIcon(hInstance, id);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* mscCreatePath
*
* DESCRIPTION:
* Creates the given path. This function is somewhat tricky so study
* it carefully before modifying it. Despite it's simplicity, it
* accounts for all boundary conditions. - mrw
*
* ARGUMENTS:
* pszPath - path to create
*
* RETURNS:
* 0=OK,else error
*
*/
int mscCreatePath(const TCHAR *pszPath)
{
TCHAR ach[512];
TCHAR *pachTok;
if (pszPath == 0)
return -1;
StrCharCopyN(ach, pszPath, sizeof(ach) / sizeof(TCHAR));
pachTok = ach;
// Basicly, we march along the string until we encounter a '\', flip
// it to a NULL and try to create the path up to that point.
// It would have been nice if CreateDirectory() could
// create sub/sub directories, but it don't. - mrw
//
while (1)
{
if ((pachTok = StrCharFindFirst(pachTok, TEXT('\\'))) == 0)
{
if (!mscIsDirectory(ach) && !CreateDirectory(ach, 0))
return -2;
break;
}
if (pachTok != ach)
{
*pachTok = TEXT('\0');
if (!mscIsDirectory(ach) && !CreateDirectory(ach, 0))
return -3;
*pachTok = TEXT('\\');
}
pachTok = StrCharNext(pachTok);
}
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION:
* mscIsDirectory
*
* DESCRIPTION:
* Checks to see if a string is a valid directory or not.
*
* PARAMETERS:
* pszName -- the string to test
*
* RETURNS:
* TRUE if the string is a valid directory, otherwise FALSE.
*
*/
int mscIsDirectory(LPCTSTR pszName)
{
DWORD dw;
dw = GetFileAttributes(pszName);
if ((dw != (DWORD)-1) && (dw & FILE_ATTRIBUTE_DIRECTORY))
return TRUE;
return FALSE;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION:
* mscAskWizardQuestionAgain
*
* DESCRIPTION:
* Reads a value from the Registry. This value represents how many times
* the user responded "NO" to the question: "Do you want to run the
* New Modem Wizard?". We won't ask this question any more if the
* user responded no, twice.
*
* PARAMETERS:
* None
*
* RETURNS:
* TRUE if the modem wizard question should be asked again, otherwize
* FALSE.
*
*/
int mscAskWizardQuestionAgain(void)
{
long lResult;
DWORD dwKeyValue = 0;
DWORD dwSize;
DWORD dwType;
TCHAR *pszAppKey = "HYPERTERMINAL";
dwSize = sizeof(DWORD);
lResult = RegQueryValueEx(HKEY_CLASSES_ROOT, (LPTSTR)pszAppKey, 0,
&dwType, (LPBYTE)&dwKeyValue, &dwSize);
// If we are able to read a value from the registry and that value
// is 1, there is no need to ask the question again, so return
// a false value.
//
if ( (lResult == ERROR_SUCCESS) && (dwKeyValue >= 1) )
return (FALSE);
return (TRUE);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION:
* mscUpdateRegistryValue
*
* DESCRIPTION:
* See mscAskWizardQuestionAgain. If the user responds "NO" to this
* question, we update a counter in the registry.
*
* PARAMETERS:
* None
*
* RETURNS:
* void
*
*/
void mscUpdateRegistryValue(void)
{
long lResult;
DWORD dwKeyValue = 0;
DWORD dwSize;
DWORD dwType;
TCHAR *pszAppKey = "HYPERTERMINAL";
dwSize = sizeof(DWORD);
lResult = RegQueryValueEx(HKEY_CLASSES_ROOT, (LPTSTR)pszAppKey, 0,
&dwType, (LPBYTE)&dwKeyValue, &dwSize);
dwKeyValue += 1;
lResult = RegSetValueEx(HKEY_CLASSES_ROOT, pszAppKey, 0,
REG_BINARY, (LPBYTE)&dwKeyValue, dwSize);
assert(lResult == ERROR_SUCCESS);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* mscMessageBeep
*
* DESCRIPTION:
* Play a MessageBeep
*
* ARGUMENTS:
* aBeep - the Beep sound to play
*
* RETURNS:
* return value from MessageBeep().
*
*/
INT_PTR mscMessageBeep(UINT aBeep)
{
//
// Play the system exclamation sound. If this session is running
// in a Terminal Service session (Remote Desktop Connection) then
// issue MessageBeep((UINT)-1) so that the sound is transfered to
// the remote machine. REV: 3/25/2002
//
return (MessageBeep((IsTerminalServicesEnabled() == TRUE) ?
(UINT)-1 :
aBeep));
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* IsNT
*
* DESCRIPTION: Determines if we are running under Windows NT
*
* ARGUMENTS:
* None.
*
* RETURNS:
* True if NT
*
* Author: MPT 7-31-97
*/
INT_PTR IsNT(void)
{
static BOOL bChecked = FALSE; // We have not made this check yet.
static BOOL bResult = FALSE; // assume we are not NT/Win2K/XP
if (bChecked == FALSE)
{
#if DEADWOOD
OSVERSIONINFO stOsVersion;
stOsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&stOsVersion))
{
bResult = ( stOsVersion.dwPlatformId == VER_PLATFORM_WIN32_NT );
}
#else // DEADWOOD
DWORD dwVersion = GetVersion();
bResult = ( !( dwVersion & 0x80000000 ) );
#endif // DEADWOOD
bChecked = TRUE;
}
return bResult;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* GetWindowsMajorVersion
*
* DESCRIPTION: Returns the major version of Windows we are running.
*
* ARGUMENTS:
* None.
*
* RETURNS:
* True if NT
*
* Author: MPT 7-31-97
*/
DWORD GetWindowsMajorVersion(void)
{
OSVERSIONINFO stOsVersion;
stOsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&stOsVersion))
{
return stOsVersion.dwMajorVersion;
}
return 0;
}
//
// The following two functions are from code obtained directly
// from MSDN for determining if you are currently running as a
// remote session (Terminal Service). REV: 10/03/2001
//
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* ValidateProductSuite
*
* DESCRIPTION:
* This function compares the passed in "suite name" string
* to the product suite information stored in the registry.
* This only works on the Terminal Server 4.0 platform.
*
* ARGUMENTS:
* SuiteName - Suite name.
*
* RETURNS:
* BOOL
*
*/
BOOL ValidateProductSuite ( LPSTR SuiteName )
{
BOOL rVal = FALSE;
LONG Rslt;
HKEY hKey = NULL;
DWORD Type = 0;
DWORD Size = 0;
LPSTR ProductSuite = NULL;
LPSTR p;
Rslt = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Control\\ProductOptions",
0, KEY_READ,
&hKey );
if ( Rslt != ERROR_SUCCESS )
{
goto exit;
}
Rslt = RegQueryValueEx( hKey, "ProductSuite", NULL, &Type, NULL, &Size );
if ( Rslt != ERROR_SUCCESS || !Size )
{
goto exit;
}
ProductSuite = (LPSTR) LocalAlloc( LPTR, Size );
if ( !ProductSuite )
{
goto exit;
}
Rslt = RegQueryValueEx( hKey, "ProductSuite", NULL, &Type,
(LPBYTE) ProductSuite, &Size );
if ( Rslt != ERROR_SUCCESS || Type != REG_MULTI_SZ )
{
goto exit;
}
p = ProductSuite;
while ( *p )
{
if ( lstrcmp( p, SuiteName ) == 0 )
{
rVal = TRUE;
break;
}
p += ( lstrlen( p ) + 1 );
}
exit:
if ( ProductSuite )
{
LocalFree( ProductSuite );
}
if ( hKey )
{
RegCloseKey( hKey );
}
return rVal;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* IsTerminalServicesEnabled
*
* DESCRIPTION:
* This function performs the basic check to see if
* the platform on which it is running is Terminal
* services enabled. Note, this code is compatible on
* all Win32 platforms. For the Windows 2000 platform
* we perform a "lazy" bind to the new product suite
* APIs that were first introduced on that platform.
*
* ARGUMENTS:
* VOID
*
* RETURNS:
* BOOL
*
*/
INT_PTR IsTerminalServicesEnabled( void )
{
static BOOL checked = FALSE; // We have not made this check yet.
static BOOL bResult = FALSE; // assume Terminal Services is not enabled
if (!checked)
{
DWORD dwVersion = GetVersion();
// are we running NT ?
if ( !( dwVersion & 0x80000000 ) )
{
// Is it Windows 2000 (NT 5.0) or greater ?
if ( LOBYTE( LOWORD( dwVersion ) ) > 4 )
{
#if(WINVER >= 0x0500)
bResult = GetSystemMetrics( SM_REMOTESESSION );
checked = TRUE;
#else // (WINVER >= 0x0500)
// In Windows 2000 we need to use the Product Suite APIs
// Don’t static link because it won’t load on non-Win2000 systems
OSVERSIONINFOEXA osVersionInfo;
DWORDLONG dwlConditionMask = 0;
HMODULE hmodK32 = NULL;
HMODULE hmodNtDll = NULL;
typedef ULONGLONG (*PFnVerSetConditionMask)(ULONGLONG,ULONG,UCHAR);
typedef BOOL (*PFnVerifyVersionInfoA) ( POSVERSIONINFOEXA, DWORD, DWORDLONG );
PFnVerSetConditionMask pfnVerSetConditionMask;
PFnVerifyVersionInfoA pfnVerifyVersionInfoA;
hmodNtDll = GetModuleHandleA( "ntdll.dll" );
if ( hmodNtDll != NULL )
{
pfnVerSetConditionMask =
( PFnVerSetConditionMask )GetProcAddress( hmodNtDll, "VerSetConditionMask");
if ( pfnVerSetConditionMask != NULL )
{
dwlConditionMask =
(*pfnVerSetConditionMask)( dwlConditionMask, VER_SUITENAME, VER_AND );
hmodK32 = GetModuleHandleA( "KERNEL32.DLL" );
if ( hmodK32 != NULL )
{
pfnVerifyVersionInfoA =
(PFnVerifyVersionInfoA)GetProcAddress( hmodK32, "VerifyVersionInfoA" ) ;
if ( pfnVerifyVersionInfoA != NULL )
{
ZeroMemory( &osVersionInfo, sizeof(osVersionInfo) );
osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
osVersionInfo.wSuiteMask = VER_SUITE_TERMINAL;
bResult = (*pfnVerifyVersionInfoA)( &osVersionInfo,
VER_SUITENAME,
dwlConditionMask );
checked = TRUE;
}
}
}
}
#endif(WINVER >= 0x0500)
}
else
{
// This is NT 4.0 or older
bResult = ValidateProductSuite( "Terminal Server" );
checked = TRUE;
}
}
}
return bResult;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* GetDllVersion
*
* DESCRIPTION: Returns the version of a given DLL.
*
* ARGUMENTS:
* lpszDllName - Name of the DLL to check the version number of.
*
* RETURNS:
* The DLL's version number.
*
* Author: REV 4-16-2002
*/
DWORD GetDllVersion(LPCTSTR lpszDllName)
{
HINSTANCE hinstDll;
DWORD dwVersion = 0;
hinstDll = LoadLibrary(lpszDllName);
if(hinstDll)
{
DLLGETVERSIONPROC pDllGetVersion;
pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion");
/*Because some DLLs might not implement this function, you
must test for it explicitly. Depending on the particular
DLL, the lack of a DllGetVersion function can be a useful
indicator of the version.
*/
if(pDllGetVersion)
{
DLLVERSIONINFO dvi;
HRESULT hr;
ZeroMemory(&dvi, sizeof(dvi));
dvi.cbSize = sizeof(dvi);
hr = (*pDllGetVersion)(&dvi);
if(SUCCEEDED(hr))
{
dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion);
}
}
FreeLibrary(hinstDll);
}
return dwVersion;
}