|
|
//+----------------------------------------------------------------------------
//
// File: misc.cpp
//
// Module: CMUTIL.DLL
//
// Synopsis: Misc. utility routines provided by CMUTIL
//
// Copyright (c) 1997-1999 Microsoft Corporation
//
// Author: henryt Created 03/01/98
//
//+----------------------------------------------------------------------------
#include "cmmaster.h"
//+----------------------------------------------------------------------------
// defines
//+----------------------------------------------------------------------------
#define WIN95_OSR2_BUILD_NUMBER 1111
#define LOADSTRING_BUFSIZE 24
#define FAREAST_WIN95_LOADSTRING_BUFSIZE 512
#define MAX_STR_LEN 512 // Maximum length for Format Message string
//+----------------------------------------------------------------------------
// code
//+----------------------------------------------------------------------------
//+----------------------------------------------------------------------------
//
// Function GetOSVersion
//
// Synopsis returns the OS version(platform ID)
//
// Arguments NONE
//
// Returns: DWORD - VER_PLATFORM_WIN32_WINDOWS or
// VER_PLATFORM_WIN32_WINDOWS98 or
// VER_PLATFORM_WIN32_NT
//
// History: Created Header 2/13/98
//
//+----------------------------------------------------------------------------
CMUTILAPI DWORD WINAPI GetOSVersion() { static dwPlatformID = 0;
//
// If this function is called before, reture the saved value
//
if (dwPlatformID != 0) { return dwPlatformID; }
OSVERSIONINFO oviVersion;
ZeroMemory(&oviVersion,sizeof(oviVersion)); oviVersion.dwOSVersionInfoSize = sizeof(oviVersion); GetVersionEx(&oviVersion);
if (oviVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { CMASSERTMSG(oviVersion.dwMajorVersion == 4, "Major Version must be 4 for this version of CM");
//
// If this is Win95 then leave it as VER_PLATFORM_WIN32_WINDOWS, however if this
// is Millennium, Win98 SE, or Win98 Gold we want to modify the returned value
// as follows: VER_PLATFORM_WIN32_MILLENNIUM -> Millennium
// VER_PLATFORM_WIN32_WINDOWS98 -> Win98 SE and Win98 Gold
//
if (oviVersion.dwMajorVersion == 4) { if (LOWORD(oviVersion.dwBuildNumber) > 2222) { //
// Millennium
//
oviVersion.dwPlatformId = VER_PLATFORM_WIN32_MILLENNIUM; } else if (LOWORD(oviVersion.dwBuildNumber) >= 1998) { //
// Win98 Gold and Win98 SE
//
oviVersion.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS98; } } }
dwPlatformID = oviVersion.dwPlatformId; return(dwPlatformID); }
//+----------------------------------------------------------------------------
//
// Function GetOSBuildNumber
//
// Synopsis Get the build number of Operating system
//
// Arguments None
//
// Returns Build Number of OS
//
// History 3/5/97 VetriV Created
//
//-----------------------------------------------------------------------------
CMUTILAPI DWORD WINAPI GetOSBuildNumber() { static dwBuildNumber = 0; OSVERSIONINFO oviVersion;
if (0 != dwBuildNumber) { return dwBuildNumber; }
ZeroMemory(&oviVersion,sizeof(oviVersion)); oviVersion.dwOSVersionInfoSize = sizeof(oviVersion); GetVersionEx(&oviVersion); dwBuildNumber = oviVersion.dwBuildNumber; return dwBuildNumber; }
//+----------------------------------------------------------------------------
//
// Function GetOSMajorVersion
//
// Synopsis Get the Major version number of Operating system
//
// Arguments None
//
// Returns Major version Number of OS
//
// History 2/19/98 VetriV Created
//
//-----------------------------------------------------------------------------
CMUTILAPI DWORD WINAPI GetOSMajorVersion(void) { static dwMajorVersion = 0; OSVERSIONINFO oviVersion;
if (0 != dwMajorVersion) { return dwMajorVersion; }
ZeroMemory(&oviVersion,sizeof(oviVersion)); oviVersion.dwOSVersionInfoSize = sizeof(oviVersion); GetVersionEx(&oviVersion); dwMajorVersion = oviVersion.dwMajorVersion; return dwMajorVersion; }
//+---------------------------------------------------------------------------
//
// Function: IsFarEastNonOSR2Win95()
//
// Synopsis: Checks to see if the OS is a far east version of Win95(golden
// and OPK1, NOT OSR2).
//
// Arguments: NONE
//
// Returns: TRUE/FALSE
//
// History: henryt 07/09/97 Created
// nickball 03/11/98 Moved to cmutil
//----------------------------------------------------------------------------
CMUTILAPI BOOL WINAPI IsFarEastNonOSR2Win95(void) { OSVERSIONINFO oviVersion;
ZeroMemory(&oviVersion, sizeof(oviVersion)); oviVersion.dwOSVersionInfoSize = sizeof(oviVersion);
GetVersionEx(&oviVersion);
//
// Is it (Win95) and (not OSR2) and (DBCS enabled)?
// Far east Win95 are DBCS enabled while other non-English versions
// are SBCS-enabled.
//
MYDBGTST((oviVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && LOWORD(oviVersion.dwBuildNumber) != WIN95_OSR2_BUILD_NUMBER && GetSystemMetrics(SM_DBCSENABLED)), (TEXT("It's a Far East non-OSR2 machine!\n")));
return (oviVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && LOWORD(oviVersion.dwBuildNumber) != WIN95_OSR2_BUILD_NUMBER && GetSystemMetrics(SM_DBCSENABLED));
}
//+---------------------------------------------------------------------------
//
// Function: CmLoadStringA
//
// Synopsis: Loads the ANSI version of the string resource specified by
// the passed in module instance handle and resource ID. The
// function returns the requested string in a CmMalloc-ed buffer
// through the return value. This buffer must be freed by the
// caller. Note that CmLoadString figures out the proper buffer
// size by guessing and then calling loadstring again if the buffer
// is too small.
//
// Arguments: HINSTANCE hInst - module to load the string resource from
// UINT nId - resource ID of the string to load
//
// Returns: LPSTR - On success returns a pointer to the requested string
// resource. On failure the function tries to return
// a pointer to the Empty string ("") but if the memory
// allocation fails it can return NULL.
//
// History: quintinb Created Header 01/14/2000
//
//----------------------------------------------------------------------------
CMUTILAPI LPSTR CmLoadStringA(HINSTANCE hInst, UINT nId) { //
// In some far east versions of non-OSR2 win95, LoadString() ignores the
// nBufferMax paramater when loading DBCS strings. As a result, if the
// DBCS string is bigger than the buffer, the API overwrites the memory.
// We workaround the bug by using a larger buffer size.
//
static fFarEastNonOSR2Win95 = IsFarEastNonOSR2Win95(); size_t nLen = fFarEastNonOSR2Win95? FAREAST_WIN95_LOADSTRING_BUFSIZE : LOADSTRING_BUFSIZE; LPSTR pszString;
if (!nId) { return (CmStrCpyAllocA("")); } while (1) { size_t nNewLen;
pszString = (LPSTR) CmMalloc(nLen*sizeof(CHAR));
MYDBGASSERT(pszString); if (NULL == pszString) { return (CmStrCpyAllocA("")); } nNewLen = LoadStringA(hInst, nId, pszString, nLen-1); //
// we use nNewLen+3 because a DBCS char len can be 2 and a UNICODE
// char len is 2. Ideally, we can use nLen in the above LoadString()
// call and use nNewLen+2 in the line below. But nLen+3 is a safer
// fix now...
//
if ((nNewLen + 3) < nLen) { return (pszString); }
//
// shouldn't reach here for far east non osr2
// this will allow us to catch DBCS string resources that are
// longer than FAREAST_WIN95_LOADSTRING_BUFSIZE.
//
MYDBGASSERT(!fFarEastNonOSR2Win95);
CmFree(pszString); nLen *= 2; } }
//+---------------------------------------------------------------------------
//
// Function: CmLoadStringW
//
// Synopsis: Loads the Unicode version of the string resource specified by
// the passed in module instance handle and resource ID. The
// function returns the requested string in a CmMalloc-ed buffer
// through the return value. This buffer must be freed by the
// caller. Note that CmLoadString figures out the proper buffer
// size by guessing and then calling loadstring again if the buffer
// is too small.
//
// Arguments: HINSTANCE hInst - module to load the string resource from
// UINT nId - resource ID of the string to load
//
// Returns: LPWSTR - On success returns a pointer to the requested string
// resource. On failure the function tries to return
// a pointer to the Empty string ("") but if the memory
// allocation fails it can return NULL.
//
// History: quintinb Created Header 01/14/2000
//
//----------------------------------------------------------------------------
CMUTILAPI LPWSTR CmLoadStringW(HINSTANCE hInst, UINT nId) { size_t nLen = LOADSTRING_BUFSIZE;
LPWSTR pszString;
if (!nId) { return (CmStrCpyAllocW(L"")); }
while (1) { size_t nNewLen;
pszString = (LPWSTR) CmMalloc(nLen*sizeof(WCHAR)); MYDBGASSERT(pszString); if (NULL == pszString) { return (CmStrCpyAllocW(L"")); } nNewLen = LoadStringU(hInst, nId, pszString, nLen-1); //
// we use nNewLen+3 because a DBCS char len can be 2 and a UNICODE
// char len is 2. Ideally, we can use nLen in the above LoadString()
// call and use nNewLen+2 in the line below. But nLen+3 is a safer
// fix now...
//
if ((nNewLen + 3) < nLen) { return (pszString); }
CmFree(pszString); nLen *= 2; } }
//+---------------------------------------------------------------------------
//
// Function: CmFmtMsgW
//
// Synopsis: Simulation of FormatMessage using wvsprintf for cross-platform
// compatibility.
//
// Arguments: hInst - Application instance handle
// dwMsgId - ID of message to use for formatting final output
// ... - Variable arguments to used in message fromatting
//
// Returns: Allocated to formatted string.
//
// History: nickball - Added function header - 5/12/97
// nickball - Moved to cmutil - 03/30/98
// quintinb - Added W and A versions - 03/09/99
//
//----------------------------------------------------------------------------
CMUTILAPI LPWSTR CmFmtMsgW(HINSTANCE hInst, DWORD dwMsgId, ...) { LPWSTR pszTmp = NULL; LPWSTR lpszOutput = NULL; LPWSTR lpszFormat = NULL;
if (!dwMsgId) { return (CmStrCpyAllocW(L"")); } // Allocate a buffer to receive the RC string with specified msg ID
lpszFormat = (LPWSTR) CmMalloc(MAX_STR_LEN*sizeof(WCHAR));
if (!lpszFormat) { CMASSERTMSG(FALSE, "CmFmtMsgW -- CmMalloc returned a NULL pointer for lpszFormat"); return (CmStrCpyAllocW(L"")); } // Initialize argument list
va_list valArgs; va_start(valArgs,dwMsgId);
// Load the format string from the RC
int nRes = LoadStringU(hInst, (UINT) dwMsgId, lpszFormat, MAX_STR_LEN - 1);
#ifdef DEBUG
if (0 == nRes) { CMTRACE3(TEXT("MyFmtMsg() LoadString(dwMsgId=0x%x) return %u, GLE=%u."), dwMsgId, nRes, nRes ? 0: GetLastError()); } #endif
// If nothing loaded, free format buffer and bail
if (nRes == 0 || lpszFormat[0] == '\0') { CMASSERTMSG(FALSE, "CmFmtMsgW -- LoadStringU returned 0 or an empty buffer."); pszTmp = (CmStrCpyAllocW(L"")); goto done; }
// Allocate another buffer and for use by vsprintf
lpszOutput = (LPWSTR) CmMalloc(MAX_STR_LEN*sizeof(WCHAR));
if (!lpszOutput) { CMASSERTMSG(FALSE, "CmFmtMsgW -- CmMalloc returned a NULL pointer for lpszOutput"); pszTmp = (CmStrCpyAllocW(L"")); goto done; }
// Format the final output using vsprintf
nRes = wvsprintfU(lpszOutput, lpszFormat, valArgs); // If wvsprintfU failed, we're done
if (nRes < 0 || lpszOutput[0] == L'\0') { CMASSERTMSG(FALSE, "CmFmtMsgW -- wvsprintfU returned 0 or an empty buffer"); pszTmp = (CmStrCpyAllocW(L"")); goto done; } // Remove trailing spaces
pszTmp = lpszOutput + lstrlenU(lpszOutput) - 1; while (CmIsSpaceW(pszTmp) && (*pszTmp != L'\n')) { *pszTmp = 0; if (pszTmp == lpszOutput) { break; } pszTmp--; }
pszTmp = CmStrCpyAllocW(lpszOutput); // allocates and copies
CMASSERTMSG(pszTmp, "CmFmtMsgW -- CmStrCpyAllocW returned a NULL pointer.");
done: // Cleanup buffers, etc.
if (lpszFormat) { CmFree(lpszFormat); } if (lpszOutput) { CmFree(lpszOutput); } va_end(valArgs); return (pszTmp); }
//+---------------------------------------------------------------------------
//
// Function: CmFmtMsgA
//
// Synopsis: Simulation of FormatMessage using wvsprintf for cross-platform
// compatibility.
//
// Arguments: hInst - Application instance handle
// dwMsgId - ID of message to use for formatting final output
// ... - Variable arguments to used in message fromatting
//
// Returns: Allocated to formatted string.
//
// History: nickball - Added function header - 5/12/97
// nickball - Moved to cmutil - 03/30/98
// quintinb - Added W and A versions - 03/09/99
//
//----------------------------------------------------------------------------
CMUTILAPI LPSTR CmFmtMsgA(HINSTANCE hInst, DWORD dwMsgId, ...) { LPSTR pszTmp = NULL; LPSTR lpszOutput = NULL; LPSTR lpszFormat = NULL;
if (!dwMsgId) { return (CmStrCpyAllocA("")); } // Allocate a buffer to receive the RC string with specified msg ID
lpszFormat = (LPSTR) CmMalloc(MAX_STR_LEN);
if (!lpszFormat) { CMASSERTMSG(FALSE, "CmFmtMsgA -- CmMalloc returned a NULL pointer for lpszFormat"); return (CmStrCpyAllocA("")); } // Initialize argument list
va_list valArgs; va_start(valArgs,dwMsgId);
// Load the format string from the RC
int nRes = LoadStringA(hInst, (UINT) dwMsgId, lpszFormat, MAX_STR_LEN - 1); #ifdef DEBUG
if (0 == nRes) { CMTRACE3(TEXT("MyFmtMsg() LoadString(dwMsgId=0x%x) return %u, GLE=%u."), dwMsgId, nRes, nRes ? 0: GetLastError()); } #endif
// If nothing loaded, free format buffer and bail
if (nRes == 0 || lpszFormat[0] == '\0') { pszTmp = (CmStrCpyAllocA("")); CMASSERTMSG(FALSE, "CmFmtMsgA -- LoadStringA returned 0 or an empty buffer."); goto done; }
// Allocate another buffer and for use by vsprintf
lpszOutput = (LPSTR) CmMalloc(MAX_STR_LEN);
if (!lpszOutput) { pszTmp = (CmStrCpyAllocA("")); CMASSERTMSG(FALSE, "CmFmtMsgA -- CmMalloc returned a NULL pointer for lpszOutput"); goto done; }
// Format the final output using vsprintf
nRes = wvsprintfA(lpszOutput, lpszFormat, valArgs); // If wvsprintfA failed, we're done
if (nRes < 0 || lpszOutput[0] == '\0') { pszTmp = (CmStrCpyAllocA("")); CMASSERTMSG(FALSE, "CmFmtMsgA -- wvsprintfA returned 0 or an empty buffer"); goto done; } // Remove trailing spaces
pszTmp = lpszOutput + lstrlenA(lpszOutput) - 1; while (CmIsSpaceA(pszTmp) && (*pszTmp != '\n')) { *pszTmp = 0; if (pszTmp == lpszOutput) { break; } pszTmp--; }
pszTmp = CmStrCpyAllocA(lpszOutput); // allocates and copies
CMASSERTMSG(pszTmp, "CmFmtMsgA -- CmStrCpyAllocA returned a NULL pointer.");
done: // Cleanup buffers, etc.
if (lpszFormat) { CmFree(lpszFormat); } if (lpszOutput) { CmFree(lpszOutput); } va_end(valArgs); return (pszTmp);
#if 0
/*
// Replaced by the above code because we no longer use the platform specific .MC files
// All strings resources are now managed via standard .RC files
va_list valArgs; DWORD dwRes; LPTSTR pszBuffer = NULL;
if (!dwMsgId) { return (CmStrCpy(TEXT(""))); } va_start(valArgs,dwMsgId);
dwRes = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_HMODULE|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_MAX_WIDTH_MASK, hInst, dwMsgId, LANG_USER_DEFAULT, (LPTSTR) &pszBuffer, 0, &valArgs); MYDBGTST(dwRes==0,("MyFmtMsg() FormatMessage(dwMsgId=0x%x) return %u, GLE=%u.",dwMsgId,dwRes,dwRes?0:GetLastError())); va_end(valArgs); if (dwRes == 0) { if (pszBuffer) { LocalFree(pszBuffer); } return (CmStrCpy(TEXT(""))); } if (!CmStrLen(pszBuffer)) { LocalFree(pszBuffer); return (CmStrCpy(TEXT(""))); } pszTmp = pszBuffer + CmStrLen(pszBuffer) - 1; while (MyIsSpace(*pszTmp) && (*pszTmp != '\n')) { *pszTmp = 0; if (pszTmp == pszBuffer) { break; } pszTmp--; } pszTmp = CmStrCpy(pszBuffer); LocalFree(pszBuffer);
return (pszTmp); */ #endif
}
#if 0 // not used anywhere
/*
//+----------------------------------------------------------------------------
//
// Function: GetMaxStringNumber
//
// Synopsis: Given a buffer containing strings in INI section format, determines
// which is the highest numbered string.
//
// Arguments: LPTSTR pszStr - The string containing an INI section
// LPDWORD pdwMax - Ptr to a DOWRD to be filled with the result
// *pdwMax gets the highest value of atol() of the strings.
//
// Returns: Nothing
//
// History: Anonymous Created 3/30/98
//
//+----------------------------------------------------------------------------
CMUTILAPI void GetMaxStringNumber(LPTSTR pszStr, LPDWORD pdwMax) { LPTSTR pszTmp; DWORD dwMax = 0;
if (pszStr) { pszTmp = pszStr; while (*pszTmp) { DWORD dwMaxTmp;
if (pdwMax) { dwMaxTmp = (DWORD)CmAtol(pszTmp); if (dwMaxTmp > dwMax) { dwMax = dwMaxTmp; } } pszTmp += lstrlen(pszTmp) + 1; } } if (pdwMax) { *pdwMax = dwMax; } } */ #endif
//+---------------------------------------------------------------------------
//
// Function: CmParsePathW
//
// Synopsis: Converts a Cm command line and args path into its component
// parts. If the command portion is a relative path, it is expanded
// to a full path. A ptr to the top level service filename is required
// to make the relative path determination.
//
// Arguments: pszCmdLine - Ptr to the full entry
// pszServiceFile - Ptr to top-level service filename
// ppszCommand - Ptr-ptr to be allocated and filled with command portion
// ppszArguments - Ptr-ptr to be allocated and filled with args portion
//
// Returns: TRUE if ppszCmd and ppszArgs are allocated/filled. FALSE otherwise.
//
// History: 02/19/99 nickball Created
// 02/21/99 nickball Moved to cmutil
// 03/09/99 quintinb Created A and W versions
//
//----------------------------------------------------------------------------
CMUTILAPI BOOL CmParsePathW(LPCWSTR pszCmdLine, LPCWSTR pszServiceFile, LPWSTR *ppszCommand, LPWSTR *ppszArguments) { LPWSTR pszArgs = NULL; LPWSTR pszCmd = NULL; LPWSTR pszTmp = NULL;
BOOL bRet = FALSE;
MYDBGASSERT(pszCmdLine); MYDBGASSERT(pszServiceFile); MYDBGASSERT(ppszCommand); MYDBGASSERT(ppszArguments);
if (NULL == pszCmdLine || NULL == pszServiceFile || NULL == ppszCommand || NULL == ppszArguments) { return FALSE; } CMTRACE1(TEXT("CmParsePathW() pszCmdLine is %s"), pszCmdLine);
//
// Determine where our string begins and what the delimiting char should
// be then make a copy of the entire command line string to muck with.
//
WCHAR tchDelim = L'+';
if (pszCmdLine == CmStrchrW(pszCmdLine, tchDelim)) { pszCmd = CmStrCpyAllocW(CharNextU(pszCmdLine)); } else { pszCmd = CmStrCpyAllocW(pszCmdLine); tchDelim = L' '; } MYDBGASSERT(pszCmd); CmStrTrimW(pszCmd);
//
// Assuming valid inputs, pszCmd is now one of the following:
//
// "C:\\Program Files\\Custom.Exe+"
// "C:\\Program Files\\Custom.Exe+ Args"
// "C:\\Progra~1\\Custom.Exe
// "C:\\Progra~1\\Custom.Exe Args"
// "service\custom.exe"
// "service\custom.exe Args"
//
if (pszCmd && L'\0' != *pszCmd) { //
// Locate the right command delimiter
//
pszArgs = CmStrchrW(pszCmd, tchDelim);
if (pszArgs) { //
// Content of pszTmp is now either "+ Args", "", or "+"
// Get a pointer to the next char and truncate the pszCmd
// that we have thus far.
//
pszTmp = CharNextU(pszArgs); // pszArgs is " Args" or ""
*pszArgs = L'\0'; // The "+" becomes ""
pszArgs = pszTmp; // pszTmp is " Args" or ""
}
//
// Fill argument buffer from pszTmp and command buffer
// from pszCmd with a complete path if necessary.
//
if (NULL == pszArgs) { *ppszArguments = (LPWSTR)CmMalloc(sizeof(WCHAR)); // one Zero-ed WCHAR
} else { MYVERIFY(*ppszArguments = CmStrCpyAllocW(pszArgs)); }
MYVERIFY(*ppszCommand = CmConvertRelativePathW(pszServiceFile, pszCmd)); //
// Trim blanks as needed
//
if (*ppszCommand) { CmStrTrimW(*ppszCommand); } if (*ppszArguments) { CmStrTrimW(*ppszArguments); }
bRet = TRUE; }
//
// Cleanup. Note: pszArgs is never allocated, so we don't have to free it.
//
CmFree(pszCmd);
return bRet; }
//+---------------------------------------------------------------------------
//
// Function: CmParsePathA
//
// Synopsis: Converts a Cm command line and args path into its component
// parts. If the command portion is a relative path, it is expanded
// to a full path. A ptr to the top level service filename is required
// to make the relative path determination.
//
// Arguments: pszCmdLine - Ptr to the full entry
// pszServiceFile - Ptr to top-level service filename
// ppszCommand - Ptr-ptr to be allocated and filled with command portion
// ppszArguments - Ptr-ptr to be allocated and filled with args portion
//
// Returns: TRUE if ppszCmd and ppszArgs are allocated/filled. FALSE otherwise.
//
// History: 02/19/99 nickball Created
// 02/21/99 nickball Moved to cmutil
// 03/09/99 quintinb Created A and W versions
//
//----------------------------------------------------------------------------
CMUTILAPI BOOL CmParsePathA(LPCSTR pszCmdLine, LPCSTR pszServiceFile, LPSTR *ppszCommand, LPSTR *ppszArguments) { LPSTR pszArgs = NULL; LPSTR pszCmd = NULL; LPSTR pszTmp = NULL;
BOOL bRet = FALSE;
MYDBGASSERT(pszCmdLine); MYDBGASSERT(pszServiceFile); MYDBGASSERT(ppszCommand); MYDBGASSERT(ppszArguments);
if (NULL == pszCmdLine || NULL == pszServiceFile || NULL == ppszCommand || NULL == ppszArguments) { return FALSE; } CMTRACE1(TEXT("CmParsePathA() pszCmdLine is %s"), pszCmdLine);
//
// Determine where our string begins and what the delimiting char should
// be then make a copy of the entire command line string to muck with.
//
CHAR tchDelim = '+';
if (pszCmdLine == CmStrchrA(pszCmdLine, tchDelim)) { pszCmd = CmStrCpyAllocA(CharNextA(pszCmdLine)); } else { pszCmd = CmStrCpyAllocA(pszCmdLine); tchDelim = ' '; } MYDBGASSERT(pszCmd); CmStrTrimA(pszCmd);
//
// Assuming valid inputs, pszCmd is now one of the following:
//
// "C:\\Program Files\\Custom.Exe+"
// "C:\\Program Files\\Custom.Exe+ Args"
// "C:\\Progra~1\\Custom.Exe
// "C:\\Progra~1\\Custom.Exe Args"
// "service\custom.exe"
// "service\custom.exe Args"
//
if (pszCmd && '\0' != *pszCmd) { //
// Locate the right command delimiter
//
pszArgs = CmStrchrA(pszCmd, tchDelim);
if (pszArgs) { //
// Content of pszTmp is now either "+ Args", "", or "+"
// Get a pointer to the next char and truncate the pszCmd
// that we have thus far.
//
pszTmp = CharNextA(pszArgs); // pszArgs is " Args" or ""
*pszArgs = '\0'; // The "+" becomes ""
pszArgs = pszTmp; // pszTmp is " Args" or ""
}
//
// Fill argument buffer from pszTmp and command buffer
// from pszCmd with a complete path if necessary.
//
if (NULL == pszArgs) { MYVERIFY(*ppszArguments = (LPSTR)CmMalloc(sizeof(CHAR))); // one Zero-ed char
} else { MYVERIFY(*ppszArguments = CmStrCpyAllocA(pszArgs)); }
MYVERIFY(*ppszCommand = CmConvertRelativePathA(pszServiceFile, pszCmd)); //
// Trim blanks as needed
//
if (*ppszCommand) { CmStrTrimA(*ppszCommand); } if (*ppszArguments) { CmStrTrimA(*ppszArguments); }
bRet = TRUE; }
//
// Cleanup. Note: pszArgs is never allocated, so we don't have to free it.
//
CmFree(pszCmd);
return bRet; }
//+----------------------------------------------------------------------------
//
// Function: CmConvertRelativePathA
//
// Synopsis: Converts the specified relative path to a full path. If the
// specified path is not a relative path specific to this profile,
// it is ignored.
//
// Arguments: LPCSTR pszServiceFile - Full path to the .cms file
// LPCSTR pszRelative - The relative path fragment
//
// Returns: LPSTR - NULL on failure
//
// Note: Do not pass referenced profile service objects to this routine.
// It is designed to derive the short-service name from the top-level
// service filename and path.
//
// History: 03/11/98 nickball Created
// 02/03/99 nickball Added header Note
// 02/21/99 nickball Moved to cmutil
// 03/09/99 quintinb Added W and A versions
//
//+----------------------------------------------------------------------------
CMUTILAPI LPSTR CmConvertRelativePathA(LPCSTR pszServiceFile, LPSTR pszRelative) { MYDBGASSERT(pszServiceFile); MYDBGASSERT(*pszServiceFile); MYDBGASSERT(pszRelative); MYDBGASSERT(*pszRelative);
if (NULL == pszRelative || 0 == pszRelative[0] || NULL == pszServiceFile || 0 == pszServiceFile[0]) { return NULL; } //
// Get the relative dir that we expect to find
//
LPSTR pszConverted = NULL; LPSTR pszRelDir = CmStripPathAndExtA(pszServiceFile);
if (pszRelDir && *pszRelDir) { lstrcatA(pszRelDir, "\\");
//
// Compare against the specifed FRAGMENT. If it matches, convert.
//
CharUpperA(pszRelDir); CharUpperA(pszRelative);
if (pszRelative == CmStrStrA(pszRelative, pszRelDir)) { //
// Combine CMS path and relative for complete
//
LPSTR pszTmp = CmStripFileNameA(pszServiceFile, FALSE); pszConverted = CmBuildFullPathFromRelativeA(pszTmp, pszRelative); CmFree(pszTmp); } else { //
// Its not a relative path for this profile, just make a copy
//
pszConverted = CmStrCpyAllocA(pszRelative); } }
CmFree(pszRelDir);
return pszConverted; }
//+----------------------------------------------------------------------------
//
// Function: CmConvertRelativePathW
//
// Synopsis: Converts the specified relative path to a full path. If the
// specified path is not a relative path specific to this profile,
// it is ignored.
//
// Arguments: LPCWSTR pszServiceFile - Full path to the .cms file
// LPCWSTR pszRelative - The relative path fragment
//
// Returns: LPWSTR - NULL on failure
//
// Note: Do not pass referenced profile service objects to this routine.
// It is designed to derive the short-service name from the top-level
// service filename and path.
//
// History: 03/11/98 nickball Created
// 02/03/99 nickball Added header Note
// 02/21/99 nickball Moved to cmutil
// 03/09/99 quintinb Added W and A versions
//
//+----------------------------------------------------------------------------
CMUTILAPI LPWSTR CmConvertRelativePathW(LPCWSTR pszServiceFile, LPWSTR pszRelative) { MYDBGASSERT(pszServiceFile); MYDBGASSERT(*pszServiceFile); MYDBGASSERT(pszRelative); MYDBGASSERT(*pszRelative);
if (NULL == pszRelative || 0 == pszRelative[0] || NULL == pszServiceFile || 0 == pszServiceFile[0]) { return NULL; } //
// Get the relative dir that we expect to find
//
LPWSTR pszConverted = NULL; LPWSTR pszRelDir = CmStripPathAndExtW(pszServiceFile);
if (pszRelDir && *pszRelDir) { lstrcatU(pszRelDir, L"\\");
//
// Compare against the specifed FRAGMENT. If it matches, convert.
//
CharUpperU(pszRelDir); CharUpperU(pszRelative);
if (pszRelative == CmStrStrW(pszRelative, pszRelDir)) { //
// Combine CMS path and relative for complete
//
LPWSTR pszTmp = CmStripFileNameW(pszServiceFile, FALSE); pszConverted = CmBuildFullPathFromRelativeW(pszTmp, pszRelative); CmFree(pszTmp); } else { //
// Its not a relative path for this profile, just make a copy
//
pszConverted = CmStrCpyAllocW(pszRelative); } }
CmFree(pszRelDir);
return pszConverted; }
//+----------------------------------------------------------------------------
//
// Function: CmStripPathAndExtA
//
// Synopsis: Helper function, strips path and extension from a filename path
//
// Arguments: pszFileName - the filename path to be modified
//
// Returns: LPSTR - The base filename sub-string
//
// History: nickball Created header 8/12/98
// nickball Moved to cmutil 02/21/99
// quintinb Added W and A versions 03/09/99
//
//+----------------------------------------------------------------------------
CMUTILAPI LPSTR CmStripPathAndExtA(LPCSTR pszFileName) { MYDBGASSERT(pszFileName);
if (NULL == pszFileName) { return NULL; }
MYDBGASSERT(*pszFileName); //
// Make a copy of the string and validate format "\\." required.
//
LPSTR pszTmp = CmStrCpyAllocA(pszFileName); if (NULL == pszTmp) { MYDBGASSERT(pszTmp); return NULL; }
LPSTR pszDot = CmStrrchrA(pszTmp, '.'); LPSTR pszSlash = CmStrrchrA(pszTmp, '\\');
if (NULL == pszDot || NULL == pszSlash || pszDot < pszSlash) { CmFree(pszTmp); MYDBGASSERT(FALSE); return NULL; } *pszDot = '\0'; //
// Increment past slash and copy remainder
//
pszSlash = CharNextA(pszSlash); lstrcpyA(pszTmp, pszSlash);
return (pszTmp); } //+----------------------------------------------------------------------------
//
// Function: CmStripPathAndExtW
//
// Synopsis: Helper function, strips path and extension from a filename path
//
// Arguments: pszFileName - the filename path to be modified
//
// Returns: LPWSTR - The base filename sub-string
//
// History: nickball Created header 8/12/98
// nickball Moved to cmutil 02/21/99
// quintinb Added W and A versions 03/09/99
//
//+----------------------------------------------------------------------------
CMUTILAPI LPWSTR CmStripPathAndExtW(LPCWSTR pszFileName) { MYDBGASSERT(pszFileName);
if (NULL == pszFileName) { return NULL; }
MYDBGASSERT(*pszFileName); //
// Make a copy of the string and validate format "\\." required.
//
LPWSTR pszTmp = CmStrCpyAllocW(pszFileName);
if (NULL == pszTmp) { MYDBGASSERT(FALSE); return NULL; }
LPWSTR pszDot = CmStrrchrW(pszTmp, L'.'); LPWSTR pszSlash = CmStrrchrW(pszTmp, L'\\');
if (NULL == pszDot || NULL == pszSlash || pszDot < pszSlash) { CmFree(pszTmp); MYDBGASSERT(FALSE); return NULL; } *pszDot = L'\0'; //
// Increment past slash and copy remainder
//
pszSlash = CharNextU(pszSlash); lstrcpyU(pszTmp, pszSlash);
return (pszTmp); }
//+----------------------------------------------------------------------------
//
// Function: CmStripFileNameA
//
// Synopsis: Helper function to deal with the tedium of extracting the path
// part of a complete filename.
//
// Arguments: LPCSTR pszFullNameAndPath - Ptr to the filename
// BOOL fKeepSlash - Flag indicating that trailing directory '\' should be retained.
//
// Returns: LPSTR - Ptr to an allocated buffer containing the dir, or NULL on failure.
//
// Note: It is up to the caller to provide reasonable input, the only requirement
// is that the input contain '\'.
//
// History: nickball Created 3/10/98
// nickball Moved to cmutil 02/21/99
// quintinb Added W and A versions 03/09/99
//
//+----------------------------------------------------------------------------
CMUTILAPI LPSTR CmStripFileNameA(LPCSTR pszFullNameAndPath, BOOL fKeepSlash) { MYDBGASSERT(pszFullNameAndPath);
if (NULL == pszFullNameAndPath) { return NULL; }
//
// Make a copy of the filename and locate the last '\'
//
LPSTR pszTmp = CmStrCpyAllocA(pszFullNameAndPath); if (NULL == pszTmp) { CMASSERTMSG(NULL, "CmStripFileNameA -- CmStrCpyAllocA returned a NULL pointer for pszTmp"); return NULL; }
LPSTR pszSlash = CmStrrchrA(pszTmp, '\\');
if (NULL == pszSlash) { MYDBGASSERT(FALSE); CmFree(pszTmp); return NULL; }
//
// If slash is desired, move to next char before truncating
//
if (fKeepSlash) { pszSlash = CharNextA(pszSlash); }
*pszSlash = '\0';
return pszTmp; }
//+----------------------------------------------------------------------------
//
// Function: CmStripFileNameW
//
// Synopsis: Helper function to deal with the tedium of extracting the path
// part of a complete filename.
//
// Arguments: LPCWSTR pszFullNameAndPath - Ptr to the filename
// BOOL fKeepSlash - Flag indicating that trailing directory '\' should be retained.
//
// Returns: LPWSTR - Ptr to an allocated buffer containing the dir, or NULL on failure.
//
// Note: It is up to the caller to provide reasonable input, the only requirement
// is that the input contain '\'.
//
// History: nickball Created 3/10/98
// nickball Moved to cmutil 02/21/99
// quintinb Added W and A versions 03/09/99
//
//+----------------------------------------------------------------------------
CMUTILAPI LPWSTR CmStripFileNameW(LPCWSTR pszFullNameAndPath, BOOL fKeepSlash) { MYDBGASSERT(pszFullNameAndPath);
if (NULL == pszFullNameAndPath) { return NULL; }
//
// Make a copy of the filename and locate the last '\'
//
LPWSTR pszTmp = CmStrCpyAllocW(pszFullNameAndPath); if (NULL == pszTmp) { CMASSERTMSG(NULL, "CmStripFileNameW -- CmStrCpyAllocW returned a NULL pointer for pszTmp"); return NULL; }
LPWSTR pszSlash = CmStrrchrW(pszTmp, L'\\');
if (NULL == pszSlash) { MYDBGASSERT(FALSE); CmFree(pszTmp); return NULL; }
//
// If slash is desired, move to next char before truncating
//
if (fKeepSlash) { pszSlash = CharNextU(pszSlash); }
*pszSlash = L'\0';
return pszTmp; }
//+----------------------------------------------------------------------------
//
// Function: CmBuildFullPathFromRelativeA
//
// Synopsis: Builds a full path by stripping the filename from pszFullFileName
// and appending pszRelative.
//
// Arguments: LPCSTR pszFullFileName - A full path and filename
// LPCSTR pszRelative - Relative path fragment.
//
// Typically used to construct a full path to a file in the profile directory
// based upon the path to the .CMP file.
//
// Returns: LPSTR - Ptr to the completed path which must be freed by the caller.
//
// Note: pszRelative must NOT contain a leading "\"
//
// History: nickball Created 03/08/98
// nickball Moved to cmutil 02/21/99
//
//+----------------------------------------------------------------------------
CMUTILAPI LPSTR CmBuildFullPathFromRelativeA(LPCSTR pszFullFileName, LPCSTR pszRelative) { MYDBGASSERT(pszFullFileName); MYDBGASSERT(pszRelative);
//
// Check assumptions
//
if (NULL == pszFullFileName || NULL == pszRelative) { return NULL; }
//
// No empty strings please
//
MYDBGASSERT(*pszFullFileName); MYDBGASSERT(*pszRelative); MYDBGASSERT(pszRelative[0] != '\\');
//
// Get the directory name including trailing '\'
//
LPSTR pszFull = NULL; LPSTR pszProfile = CmStripFileNameA(pszFullFileName, TRUE);
if (pszProfile && *pszProfile) { pszFull = (LPSTR) CmMalloc(lstrlenA(pszProfile) + lstrlenA(pszRelative) + sizeof(CHAR)); MYDBGASSERT(pszFull);
if (pszFull) { //
// Build the complete path with new relative extension
//
lstrcpyA(pszFull, pszProfile); lstrcatA(pszFull, pszRelative); } } CmFree(pszProfile);
return pszFull; }
//+----------------------------------------------------------------------------
//
// Function: CmBuildFullPathFromRelativeW
//
// Synopsis: Builds a full path by stripping the filename from pszFullFileName
// and appending pszRelative.
//
// Arguments: LPWTSTR pszFullFileName - A full path and filename
// LPWTSTR pszRelative - Relative path fragment.
//
// Typically used to construct a full path to a file in the profile directory
// based upon the path to the .CMP file.
//
// Returns: LPWSTR - Ptr to the completed path which must be freed by the caller.
//
// Note: pszRelative must NOT contain a leading "\"
//
// History: nickball Created 3/8/98
// nickball Moved to cmutil 02/21/99
//
//+----------------------------------------------------------------------------
CMUTILAPI LPWSTR CmBuildFullPathFromRelativeW(LPCWSTR pszFullFileName, LPCWSTR pszRelative) { MYDBGASSERT(pszFullFileName); MYDBGASSERT(pszRelative);
//
// Check assumptions
//
if (NULL == pszFullFileName || NULL == pszRelative) { return NULL; }
//
// No empty strings please
//
MYDBGASSERT(*pszFullFileName); MYDBGASSERT(*pszRelative); MYDBGASSERT(pszRelative[0] != L'\\');
//
// Get the directory name including trailing '\'
//
LPWSTR pszFull = NULL; LPWSTR pszProfile = CmStripFileNameW(pszFullFileName, TRUE);
if (pszProfile && *pszProfile) { pszFull = (LPWSTR) CmMalloc((lstrlenU(pszProfile) + lstrlenU(pszRelative) + 1)*sizeof(WCHAR)); MYDBGASSERT(pszFull);
if (pszFull) { //
// Build the complete path with new relative extension
//
lstrcpyU(pszFull, pszProfile); lstrcatU(pszFull, pszRelative); } } CmFree(pszProfile);
return pszFull; }
//+-----------------------------------------------------------------------------------------
// Function: CmWinHelp
//
// Synopsis: Calls Winhelp using the command line parameters
//
// Arguments: See winhelp documentation
// hWndItem - This is a additional parameter we use to designate the window/control for
// which help(context) is needed.
// Returns: TRUE if help was launched successfully otherwise FALSE
//
// Notes:
//
// History: v-vijayb 7/10/99
//
//+-----------------------------------------------------------------------------------------
CMUTILAPI BOOL CmWinHelp(HWND hWndMain, HWND hWndItem, CONST WCHAR *lpszHelp, UINT uCommand, ULONG_PTR dwData) { DWORD cb; TCHAR szName[MAX_PATH]; HDESK hDesk = GetThreadDesktop(GetCurrentThreadId()); BOOL fRun = FALSE; DWORD *prgWinIdHelpId = (DWORD *) dwData;
//
// Get the name of the desktop. Normally returns default or Winlogon or system or WinNT
// On Win95/98 GetUserObjectInformation is not supported and thus the desktop name
// will be empty so we will use the good old help API
//
szName[0] = 0; GetUserObjectInformation(hDesk, UOI_NAME, szName, sizeof(szName), &cb); CMTRACE1(TEXT("Desktop = %s"), szName); if (lstrcmpi(TEXT("Winlogon"), szName) == 0) { return FALSE; /*
STARTUPINFOW StartupInfo; PROCESS_INFORMATION ProcessInfo; WCHAR szCommandLine[MAX_PATH+1];
//
// Launch winhelp
//
ZeroMemory(&ProcessInfo, sizeof(ProcessInfo)); ZeroMemory(&StartupInfo, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); StartupInfo.lpDesktop = L"Winsta0\\Winlogon"; StartupInfo.wShowWindow = SW_SHOW;
ZeroMemory(&szCommandLine, sizeof(szCommandLine));
lstrcpyU(szCommandLine, L"winhlp32.exe "); switch (uCommand) { case HELP_FORCEFILE: break; case HELP_QUIT: lstrcatU(szCommandLine, L"-G "); break; case HELP_WM_HELP: case HELP_CONTEXTMENU: { DWORD dwWinId; WCHAR szTemp[MAX_PATH]; MYDBGASSERT(prgWinIdHelpId); dwWinId = GetWindowLong(hWndItem, GWL_ID); //
// Check if user press right click on a valid window.
// If not abort
//
if (dwWinId == 0) { return (fRun); }
// Find the context help Id
while (*prgWinIdHelpId != 0) { if (*prgWinIdHelpId == dwWinId) { prgWinIdHelpId ++; wsprintfW(szTemp, L"-P -N %d ", *prgWinIdHelpId); lstrcatU(szCommandLine, szTemp); break; } // One for window id & one for help id
prgWinIdHelpId ++; prgWinIdHelpId ++; } } break; default: CMTRACE1(TEXT("CMWinHelp Invalid uCommand = %d"), uCommand); break; }
if (lpszHelp) { lstrcatU(szCommandLine, lpszHelp); } CMTRACE1(TEXT("Help() - Launching %s"), szCommandLine);
if (NULL == CreateProcessU(NULL, szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo)) { LONG lRes;
lRes = GetLastError(); CMTRACE2(TEXT("CMWinHelp CreateProcess() of %s failed, GLE=%u."), szCommandLine, lRes); } else { CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); fRun = TRUE; } */ } else { fRun = WinHelpU(hWndMain, lpszHelp, uCommand, (ULONG_PTR) prgWinIdHelpId); }
return (fRun); }
//+----------------------------------------------------------------------------
//
// Function: IsLogonAsSystem
//
// Synopsis: Whether the current process is running in the system account
//
// Arguments: None
//
// Returns: BOOL - TRUE if running in system account
//
// History: fengsun Created Header 7/13/98
// v-vijayb Modified to use SIDs instead of username
//
//+----------------------------------------------------------------------------
CMUTILAPI BOOL IsLogonAsSystem() { static BOOL fLogonAsSystem = -1;
//
// If this function has been called before, return the saved value.
//
if (fLogonAsSystem != -1) { return fLogonAsSystem; }
//
// Runs only under NT
//
if (OS_NT) { HANDLE hProcess, hAccess; DWORD cbTokenInfo, cbRetInfo; PTOKEN_USER pTokenInfo; SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; PSID pSystemSID = NULL;
//
// On NT, we pick the more stringent value for the default.
//
fLogonAsSystem = TRUE; if (AllocateAndInitializeSid(&SIDAuthNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSystemSID)) { hProcess = GetCurrentProcess(); // Pseudo handle, no need to close
if (OpenProcessToken(hProcess, TOKEN_READ, &hAccess)) { BOOL bRet = GetTokenInformation(hAccess, TokenUser, NULL, 0, &cbRetInfo); MYDBGASSERT((FALSE == bRet) && (0 != cbRetInfo));
if (cbRetInfo) { cbTokenInfo = cbRetInfo; pTokenInfo = (PTOKEN_USER) CmMalloc( cbTokenInfo * sizeof(BYTE) ); if (pTokenInfo) { if (GetTokenInformation(hAccess, TokenUser, (PVOID) pTokenInfo, cbTokenInfo, &cbRetInfo)) { if (EqualSid(pTokenInfo->User.Sid, pSystemSID)) { CMTRACE(TEXT("Running under LOCALSYSTEM account")); fLogonAsSystem = TRUE; } else { fLogonAsSystem = FALSE; } } CmFree(pTokenInfo); } } CloseHandle(hAccess); } FreeSid(pSystemSID); } } else { fLogonAsSystem = FALSE; } return fLogonAsSystem; }
|