|
|
/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
StrUtils.C
Abstract:
String utility functions
Author:
Bob Watson (a-robw)
Revision History:
24 Jun 94 Written
--*/ //
// Windows Include Files
//
#include <windows.h>
#include <stdio.h>
#include <malloc.h>
#include <tchar.h> // unicode macros
#include <stdlib.h> // string to number conversions
//
// app include files
//
#include "otnboot.h"
#include "otnbtdlg.h"
//
// Local constants
//
#define NUM_BUFS 8
BOOL MatchFirst ( IN LPCTSTR szStringA, IN LPCTSTR szStringB ) /*++
Routine Description:
performs a case in-sensitive comparison of the two strings to the extent of the shortest string. If, up to the length of the shortest string, the strings match then TRUE is returned otherwise FALSE is returned.
Arguments:
IN LPCTSTR szStringA, pointer to first string
IN LPCTSTR szStringB pointer to second string
Return Value:
TRUE if match found FALSE if not
--*/ { LPTSTR szAptr; // pointer to char in szStringA to compare
LPTSTR szBptr; // pointer to char in szStringB to compare
if ((szStringA != NULL) && (szStringB != NULL)) { szAptr = (LPTSTR)szStringA; szBptr = (LPTSTR)szStringB; while ((*szBptr != 0) && (*szAptr != 0)) { if (_totlower(*szBptr) != _totlower(*szAptr)) break; szBptr++; szAptr++; } if (((*szAptr == 0) && ((*szBptr == 0) || (*szBptr == cBackslash))) || ((*szBptr == 0) && ((*szAptr == 0) || (*szAptr == cBackslash)))) { // then a matched directoryto the end of the shortest string
return TRUE; } else { return FALSE; } } else { return FALSE; } }
DWORD GetSizeFromInfString ( IN LPCTSTR szString ) /*++
Routine Description:
Reads the estimated size of the directory tree as stored in the inf file. The format of the INF string is:
key=entry where: key = subdir name entry = NumberOfFiles,TotalBytes
value must be less than 2**32
Arguments:
"entry" string read from INF file
Return Value:
DWORD value of TotalBytes in entry
--*/ { LPTSTR szSize; // size string parsed from input string
LPTSTR szLastChar; // beginning of size value in string
// size is second param in comma separated list
// go to first comma
szSize = (LPTSTR)szString; while ((*szSize != cComma) && (*szSize != 0)) szSize++; szSize++; // go to first char after comma
return _tcstoul (szSize, &szLastChar, 10); }
BOOL SavePathToRegistry ( LPCTSTR szPath, LPCTSTR szServerKey, LPCTSTR szShareKey ) /*++
Routine Description:
splits the path (which must be a UNC path) into server & sharepoint for loading into the system registry. The key used is the \HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Network and the NCAdmin key is created (if it doesn't exist) under which the Server is stored in the szServerKey value and the share point is stored under the szShareKey value
Arguments:
LPCTSTR szPath UNC path to store
LPCTSTR szServerKey name of registry value to store server under
LPCTSTR szShareKey name of registry value to store share under
Return Value:
TRUE values stored OK FALSE values not stored
--*/ { TCHAR szMachine[MAX_COMPUTERNAME_LENGTH+1]; // computer name buffer
LPTSTR szShare; // share name buffer
HKEY hkeyUserInfo; // registry key
HKEY hkeyAppInfo; // registry key
LONG lStatus; // local function status
BOOL bReturn; // return value of this fn
DWORD dwAppKeyDisp; // create/existing value
szShare = GlobalAlloc (GPTR, MAX_PATH_BYTES); if (szShare == NULL) { // unable to alloc memory.
return FALSE; }
if (IsUncPath (szPath)) { // open registry key containing net apps
lStatus = RegOpenKeyEx ( HKEY_CURRENT_USER, cszUserInfoKey, 0L, KEY_READ, &hkeyUserInfo);
if (lStatus != ERROR_SUCCESS) { // unable to open key so return error
bReturn = FALSE; } else { // open registry key containing this app's info
lStatus = RegCreateKeyEx ( hkeyUserInfo, szAppName, 0L, (LPTSTR)cszEmptyString, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyAppInfo, &dwAppKeyDisp);
if (lStatus != ERROR_SUCCESS) { // unable to open key so return false
bReturn = FALSE; } else { if (!GetServerFromUnc (szPath, szMachine)) { // unable to read share so clear value
szMachine[0] = 0; } // get server name from registry
lStatus = RegSetValueEx ( hkeyAppInfo, (LPTSTR)szServerKey, 0L, REG_SZ, (LPBYTE)&szMachine[0], (DWORD)(lstrlen(szMachine)*sizeof(TCHAR)));
if (lStatus == ERROR_SUCCESS) { if (!GetShareFromUnc (szPath, szShare)) { szShare[0] = 0; }
lStatus = RegSetValueEx ( hkeyAppInfo, (LPTSTR)szShareKey, 0L, REG_SZ, (LPBYTE)&szShare[0], (DWORD)(lstrlen(szShare)*sizeof(TCHAR)));
if (lStatus == ERROR_SUCCESS) { bReturn = TRUE; } else { bReturn = FALSE; } } else { bReturn = FALSE; }
RegCloseKey (hkeyAppInfo); } RegCloseKey (hkeyUserInfo); }
bReturn = TRUE; } else { // not a UNC path so return error
bReturn = FALSE; }
FREE_IF_ALLOC (szShare); return bReturn;
}
DWORD QuietGetPrivateProfileString ( IN LPCTSTR lpszSection, /* address of section name */ IN LPCTSTR lpszKey, /* address of key name */ IN LPCTSTR lpszDefault, /* address of default string */ OUT LPTSTR lpszReturnBuffer, /* address of destination buffer */ IN DWORD cchReturnBuffer, /* size of destination buffer */ IN LPCTSTR lpszFile /* address of initialization filename */ ) /*++
Routine Description:
Reads data from profile file without triggering OS error message if unable to access file.
Arguments:
IN LPCTSTR lpszSection address of section name IN LPCTSTR lpszKey address of key name IN LPCTSTR lpszDefault address of default string OUT LPTSTR lpszReturnBuffer address of destination buffer IN DWORD cchReturnBuffer size of destination buffer (in characters) IN LPCTSTR lpszFile address of initialization filename
See HELP on GetPrivateProfileString for details on using these arguments.
Return Value:
number of characters copied into lpszReturnBuffer.
--*/ { DWORD dwReturn; UINT nErrorMode;
// disable windows error message popup
nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
// call function
dwReturn = GetPrivateProfileString ( lpszSection, lpszKey, lpszDefault, lpszReturnBuffer, cchReturnBuffer, lpszFile);
SetErrorMode (nErrorMode); // restore old error mode
return dwReturn; }
LPCTSTR GetKeyFromEntry ( IN LPCTSTR szEntry ) /*++
Routine Description:
copys the "key" from an INF string of the format: Key=Value. All text up to, but not including the "=" is returned.
Arguments:
IN LPCTSTR szEntry line from INF file to process. must be in the format referenced above.
Return Value:
pointer to a read only string that contains the resulting key string.
NOTE: this is stored in a static variable and should be copied to a local variable for further processing OR before calling this routine again.
--*/ { static TCHAR szReturnBuffer[MAX_PATH]; LPTSTR szSource, szDest;
szSource = (LPTSTR)szEntry; szDest = &szReturnBuffer[0];
*szDest = 0;
if (*szSource != 0) { // copy all chars from start to the equal sign
// (or the end of the string)
while ((*szSource != cEqual) && (*szSource != 0)) { *szDest++ = *szSource++; } *szDest = 0; //terminate destination string (key)
} return szReturnBuffer; }
LPCTSTR GetItemFromEntry ( IN LPCTSTR szEntry, IN DWORD dwItem
) /*++
Routine Description:
returns nth item from comma separated list returned from inf file. leaves (double)quoted strings intact.
Arguments:
IN LPCTSTR szEntry entry string returned from INF file
IN DWORD dwItem 1-based index indicating which item to return. (i.e. 1= first item in list, 2= second, etc.)
Return Value:
pointer to buffer containing desired entry in string. Note, this routine may only be called 4 times before the string buffer is re-used. (i.e. don't use this function more than 4 times in another function call!!)
--*/ { static TCHAR szReturnBuffer[4][MAX_PATH]; LPTSTR szSource, szDest; DWORD dwThisItem; static DWORD dwBuff;
dwBuff = ++dwBuff % 4; // wrap buffer index
szSource = (LPTSTR)szEntry; szDest = &szReturnBuffer[dwBuff][0];
*szDest = 0;
// go past ini key
while ((*szSource != cEqual) && (*szSource != 0)) szSource++; if (*szSource == 0){ // no equals found so start at beginning
// presumably this is just the "value"
szSource = (LPTSTR)szEntry; } else { szSource++; } dwThisItem = 1; while (dwThisItem < dwItem) { if (*szSource != 0) { while ((*szSource != cComma) && (*szSource != 0)) { if (*szSource == cDoubleQuote) { // if this is a quote, then go to the close quote
szSource++; while ((*szSource != cDoubleQuote) && (*szSource != 0)) szSource++; } if (*szSource != 0) szSource++; } } dwThisItem++; if (*szSource != 0) szSource++; } // copy this entry to the return buffer
if (*szSource != 0) { while ((*szSource != cComma) && (*szSource != 0)) { if (*szSource == cDoubleQuote) { // if this is a quote, then go to the close quote
// don't copy quotes!
szSource++; while ((*szSource != cDoubleQuote) && (*szSource != 0)) { *szDest++ = *szSource++; } if (*szSource != 0) szSource++; } else { *szDest++ = *szSource++; } } *szDest = 0; }
return &szReturnBuffer[dwBuff][0]; }
LPCTSTR GetFileNameFromEntry ( IN LPCTSTR szEntry ) /*++
Routine Description:
returns pointer into szEntry where file name is found. first character after the ":"
Arguments:
string containing filename in format of: nn:filename.ext
Return Value:
returns pointer into szEntry where file name is found. first character after the ":" returns an empty string if no ":" char was found.
--*/ { LPTSTR szReturn; szReturn = (LPTSTR)szEntry; // go to COLON character
while ((*szReturn != cColon) && (*szReturn != 0)) szReturn++; // scoot to next char
if (*szReturn != 0) szReturn++; return szReturn; }
BOOL TrimSpaces ( IN OUT LPTSTR szString ) /*++
Routine Description:
Trims leading and trailing spaces from szString argument, modifying the buffer passed in
Arguments:
IN OUT LPTSTR szString buffer to process
Return Value:
TRUE if string was modified FALSE if not
--*/ { LPTSTR szSource; LPTSTR szDest; LPTSTR szLast; BOOL bChars;
szLast = szSource = szDest = szString; bChars = FALSE;
while (*szSource != 0) { // skip leading non-space chars
if (*szSource > cSpace) { szLast = szDest; bChars = TRUE; } if (bChars) { // remember last non-space character
// copy source to destination & increment both
*szDest++ = *szSource++; } else { szSource++; } }
if (bChars) { *++szLast = 0; // terminate after last non-space char
} else { // string was all spaces so return an empty (0-len) string
*szString = 0; }
return (szLast != szSource); }
BOOL IsUncPath ( IN LPCTSTR szPath ) /*++
Routine Description:
examines path as a string looking for "tell-tale" double backslash indicating the machine name syntax of a UNC path
Arguments:
IN LPCTSTR szPath path to examine
Return Value:
TRUE if \\ found at start of string FALSE if not
--*/ { LPTSTR szPtChar;
szPtChar = (LPTSTR)szPath; if (*szPtChar == cBackslash) { if (*++szPtChar == cBackslash) { return TRUE; } } return FALSE; }
LPCTSTR GetEntryInMultiSz ( IN LPCTSTR mszList, IN DWORD dwEntry
) /*++
Routine Description:
Searches for the specified element in the mszList and returns the pointer to that element in the list.
Arguments:
IN LPCTSTR mszList Multi-SZ list to search IN DWORD dwEntry 1-based index of entry to return
ReturnValue:
!=cszEmptyString pointer to matching element in list cszEmptyString (pointer to 0-length string) entry is not in list --*/ { LPCTSTR szThisString; DWORD dwIndex=0;
if (mszList == NULL) return (LPCTSTR)cszEmptyString; // no list to process
if (dwEntry == 0) return (LPCTSTR)cszEmptyString; // no string to find
for (szThisString = mszList; *szThisString; szThisString += (lstrlen(szThisString)+ 1)) { dwIndex++; if (dwIndex == dwEntry) { return szThisString; } }
return (LPCTSTR)cszEmptyString; }
DWORD AddStringToMultiSz ( LPTSTR OUT mszDest, LPCTSTR IN szSource ) /*++
Routine Description:
appends the source string to the end of the destination MULTI_SZ string. Assumes that the destination is large enough!
Arguments:
LPTSTR OUT mszDest multi-sz string to be appended LPTSTR IN szSource ASCIZ string to be added to the end of the dest string
ReturnValue:
1
--*/ { LPTSTR szDestElem;
// check function arguments
if ((mszDest == NULL) || (szSource == NULL)) return 0; // invalid buffers
if (*szSource == '\0') return 0; // no string to add
// go to end of dest string
//
for (szDestElem = mszDest; *szDestElem; szDestElem += (lstrlen(szDestElem)+1));
// if here, then add string
// szDestElem is at end of list
lstrcpy (szDestElem, szSource); szDestElem += (lstrlen(szDestElem) + 1); *szDestElem = '\0'; // add second NULL
return 1; }
DWORD StringInMultiSz ( IN LPCTSTR szString, IN LPCTSTR mszList ) /*++
Routine Description:
Searches each element in the mszList and does a case-insensitive comparison with the szString argument.
Arguments:
IN LPCTSTR szString string to find in list IN LPCTSTR mszList list to search
ReturnValue:
>0 szString was found in the list, # returned is the index of the matching entry (1= first) 0 szString was NOT found --*/ { LPTSTR szThisString; DWORD dwIndex=0;
// check input arguments
if ((szString == NULL) || (mszList == NULL)) return 0; // invalid buffer
if (*szString == 0) return 0; // no string to find
for (szThisString = (LPTSTR)mszList; *szThisString; szThisString += (lstrlen(szThisString)+ 1)) { dwIndex++; if (lstrcmpi(szThisString, szString) == 0) { return dwIndex; } }
return 0; }
LPCTSTR GetStringResource ( IN UINT nId ) /*++
Routine Description:
look up string resource and return string
Arguments:
IN UINT nId Resource ID of string to look up
Return Value:
pointer to string referenced by ID in arg list
--*/ { static TCHAR szBufArray[NUM_BUFS][SMALL_BUFFER_SIZE]; static DWORD dwIndex; LPTSTR szBuffer; DWORD dwLength;
dwIndex++; dwIndex %= NUM_BUFS; szBuffer = &szBufArray[dwIndex][0];
dwLength = LoadString ( GetModuleHandle (NULL), nId, szBuffer, SMALL_BUFFER_SIZE);
return (LPCTSTR)szBuffer; }
DWORD GetMultiSzLen ( IN LPCTSTR mszInString ) /*++
Routine Description:
Counts the number of characters in the multi-sz string (including NULL's between strings and terminating NULL char)
Arguments:
IN LPCTSTR mszInString multi-sz string to count
Return Value:
number of characters in string
--*/ { LPCTSTR szEndChar = mszInString; BOOL bEnd = FALSE; DWORD dwCharsInString = 0;
while (!bEnd) { if (*szEndChar == 0) { // this is the end of a line so adjust the count to
// account for the crlf being 2 chars
szEndChar++; dwCharsInString += 2;
if (*szEndChar == 0) { // this is the end of the MSZ
dwCharsInString++; // for the CTRL-Z
bEnd = TRUE; } } else { szEndChar++; dwCharsInString++; } }
return dwCharsInString; }
DWORD TranslateEscapeChars ( IN LPTSTR szNewString, IN LPTSTR szString ) /*++
Translates the following escape sequences if found in the string. The translation is performed on szString and written to szNewString.
The return value is the length of the resulting string in characters;
--*/ { LPTSTR szSource; LPTSTR szDest;
szSource = szString; szDest = szNewString;
while (*szSource != 0) { if (*szSource == '\\') { // this is an escape sequence so go to the next char
// and see which one.
szSource++; switch (*szSource) { case _T('b'): *szDest = _T('\b'); break;
case _T('f'): *szDest = _T('\f'); break;
case _T('n'): *szDest = _T('\n'); break;
case _T('r'): *szDest = _T('\r'); break;
case _T('t'): *szDest = _T('\t'); break;
case _T('v'): *szDest = _T('\v'); break;
case _T('?'): *szDest = _T('\?'); break;
case _T('\''): *szDest = _T('\''); break;
case _T('\"'): *szDest = _T('\"'); break;
case _T('\\'): *szDest = _T('\\'); break;
default: *szDest = *szSource; break; } szDest++; szSource++; } else { // just a plain old character so copy it
*szDest++ = *szSource++; } } return (DWORD)(szDest - szNewString);
}
|