/* 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 #pragma hdrstop #include #include "stdtyp.h" #include "misc.h" #include "tdll.h" #include "htchar.h" #include "globals.h" #include "assert.h" #include /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * 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; }