2020-09-30 17:12:29 +02:00

2266 lines
61 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
lodctr.c
Abstract:
Program to read the contents of the file specified in the command line
and update the registry accordingly
Author:
Bob Watson (a-robw) 10 Feb 93
Revision History:
a-robw 25-Feb-93 revised calls to make it compile as a UNICODE or
an ANSI app.
--*/
#define UNICODE 1
#define _UNICODE 1
//
// "C" Include files
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
//
// Windows Include files
//
#include <windows.h>
#include <loadperf.h>
#include <tchar.h>
//
// application include files
//
#include "common.h"
#include "lodctr.h"
#define OLD_VERSION 0x010000
static DWORD dwSystemVersion;
static DWORD dwFileSize;
static TCHAR ComputerName[FILE_NAME_BUFFER_SIZE];
static HKEY hPerfData;
static TCHAR szDataFileRoot[] = {TEXT("%systemroot%\\system32\\perf")};
static TCHAR szDatExt[] = {TEXT(".DAT")};
static TCHAR szBakExt[] = {TEXT(".BAK")};
static BOOL bQuietMode = TRUE; // quiet means no _tprintf's
#define OUTPUT_MESSAGE if (bQuietMode) _tprintf
static
BOOL
MakeBackupCopyOfLanguageFiles (
IN LPCTSTR szLangId
)
{
TCHAR szOldFileName[MAX_PATH];
TCHAR szNewFileName[MAX_PATH];
LPTSTR szOldBaseEnd;
LPTSTR szNewBaseEnd;
BOOL bStatus;
ExpandEnvironmentStrings (szDataFileRoot, szOldFileName, MAX_PATH);
lstrcpy (szNewFileName, szOldFileName);
szOldBaseEnd = szOldFileName + lstrlen(szOldFileName);
szNewBaseEnd = szNewFileName + lstrlen(szNewFileName);
// copy Counter Name Files
*szOldBaseEnd = TEXT('C');
*szNewBaseEnd = TEXT('C');
lstrcpy (szOldBaseEnd+1, szLangId);
lstrcpy (szNewBaseEnd+1, szLangId);
lstrcat (szOldBaseEnd, szDatExt);
lstrcat (szNewBaseEnd, szBakExt);
// copy the old file to the new file name and overwrite any
// previous versions of the file
bStatus = CopyFile (szOldFileName, szNewFileName, FALSE);
if (bStatus) {
// copy Explain Text Files
*szOldBaseEnd = TEXT('H');
*szNewBaseEnd = TEXT('H');
// copy the old file to the new file name and overwrite any
// previous versions of the file
bStatus =CopyFile (szOldFileName, szNewFileName, FALSE);
}
return bStatus;
}
static
BOOL
LanguageInstalled (
IN LPCTSTR szLangId
)
{
BOOL bStatus;
BOOL bReturn = FALSE;
LONG lStatus;
HKEY hKeyMachine;
HKEY hKeyThisLang;
HKEY hPerflib;
// check if we need to connect to remote machine
if (ComputerName[0]) {
bStatus = FALSE;
try {
lStatus = RegConnectRegistry (
(LPTSTR)ComputerName,
HKEY_LOCAL_MACHINE,
&hKeyMachine);
} finally {
if (lStatus != ERROR_SUCCESS) {
SetLastError (lStatus);
hKeyMachine = NULL;
} else {
bStatus = TRUE;
}
}
} else {
hKeyMachine = HKEY_LOCAL_MACHINE;
bStatus = TRUE;
}
if (bStatus) {
// open key to perflib's "root" key
lStatus = RegOpenKeyEx (
hKeyMachine,
NamesKey,
RESERVED,
KEY_READ,
&hPerflib);
if (lStatus == ERROR_SUCCESS) {
// make sure this language is loaded
lStatus = RegOpenKeyEx(
hPerflib,
szLangId,
RESERVED,
KEY_READ,
&hKeyThisLang);
if (lStatus == ERROR_SUCCESS) {
bReturn = TRUE;
// we just need the open status, not the key handle so
// close this handle and set the one we need.
RegCloseKey (hKeyThisLang);
}
RegCloseKey (hPerflib);
}
RegCloseKey (hKeyMachine);
}
return bReturn;
}
static
BOOL
GetFileFromCommandLine (
IN LPTSTR lpCommandLine,
OUT LPTSTR *lpFileName
)
/*++
GetFileFromCommandLine
parses the command line to retrieve the ini filename that should be
the first and only argument.
Arguments
lpCommandLine pointer to command line (returned by GetCommandLine)
lpFileName pointer to buffer that will recieve address of the
validated filename entered on the command line
Return Value
TRUE if a valid filename was returned
FALSE if the filename is not valid or missing
error is returned in GetLastError
--*/
{
INT iNumArgs;
HFILE hIniFile;
OFSTRUCT ofIniFile;
LPTSTR lpExeName = NULL;
LPTSTR lpCmdLineName = NULL;
LPSTR lpIniFileName = NULL;
HANDLE hFileHandle;
TCHAR LocalComputerName[FILE_NAME_BUFFER_SIZE];
DWORD NameBuffer;
// check for valid arguments
if (!lpCommandLine) return (ERROR_INVALID_PARAMETER);
if (!lpFileName) return (ERROR_INVALID_PARAMETER);
// allocate memory for parsing operation
lpExeName = malloc (FILE_NAME_BUFFER_SIZE * sizeof(TCHAR));
lpCmdLineName = malloc (FILE_NAME_BUFFER_SIZE * sizeof(TCHAR));
lpIniFileName = malloc (FILE_NAME_BUFFER_SIZE);
if (!lpExeName || !lpIniFileName || !lpCmdLineName) {
SetLastError (ERROR_OUTOFMEMORY);
if (lpExeName) free (lpExeName);
if (lpIniFileName) free (lpIniFileName);
if (lpCmdLineName) free (lpCmdLineName);
return FALSE;
} else {
// get strings from command line
ComputerName[0] = TEXT('\0');
// Get INI File name
lstrcpy (lpCmdLineName, GetItemFromString (lpCommandLine, 3, TEXT(' ')));
if (lstrlen(lpCmdLineName) == 0) {
// then no computer name was specified so try to get the
// ini file from the 2nd entry
lstrcpy (lpCmdLineName, GetItemFromString (lpCommandLine, 2, TEXT(' ')));
if (lstrlen(lpCmdLineName) == 0) {
// no ini file found
iNumArgs = 1;
} else {
// fill in a blank computer name
iNumArgs = 2;
ComputerName[0] = 0;
}
} else {
// the computer name must be present so fetch it
lstrcpy (LocalComputerName, GetItemFromString (lpCommandLine, 2, TEXT(' ')));
iNumArgs = 3;
}
if (iNumArgs != 2 && iNumArgs != 3) {
// wrong number of arguments
SetLastError (ERROR_INVALID_PARAMETER);
if (lpExeName) free (lpExeName);
if (lpIniFileName) free (lpIniFileName);
return FALSE;
} else {
// check for usage
if (lpCmdLineName[1] == TEXT('?') || LocalComputerName[1] == TEXT('?')) {
// ask for usage
if (lpExeName) free (lpExeName);
if (lpIniFileName) free (lpIniFileName);
return FALSE;
}
// check if there is a computer name in the input line
if (LocalComputerName[0] == TEXT('\\') &&
LocalComputerName[1] == TEXT('\\')) {
// save it form now
lstrcpy (ComputerName, LocalComputerName);
// reuse local buffer to get the this computer's name
NameBuffer = sizeof (LocalComputerName) / sizeof (TCHAR);
GetComputerName(LocalComputerName, &NameBuffer);
if (!lstrcmpi(LocalComputerName, &ComputerName[2])) {
// same name as local computer name
// so clear computer name buffer
ComputerName[0] = TEXT('\0');
}
}
// see if file specified exists
// file name is always an ANSI buffer
CharToOem (lpCmdLineName, lpIniFileName);
hIniFile = OpenFile (lpIniFileName,
&ofIniFile,
OF_PARSE);
if (hIniFile != HFILE_ERROR) {
if (hIniFile)
_lclose (hIniFile);
hFileHandle = CreateFile (
lpCmdLineName,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
free (lpCmdLineName);
if (hFileHandle && hFileHandle != INVALID_HANDLE_VALUE) {
// get file size
dwFileSize = GetFileSize (hFileHandle, NULL);
if (dwFileSize == 0xffffffff) {
dwFileSize = 0L;
} else {
dwFileSize *= sizeof (TCHAR);
}
CloseHandle (hFileHandle);
// file exists, so return name and success
if (lpExeName) free (lpExeName);
if (lpIniFileName) free (lpIniFileName);
// return full pathname if found
OemToChar (ofIniFile.szPathName, *lpFileName);
return TRUE;
} else {
// filename was on command line, but not valid so return
// false, but send name back for error message
if (lpExeName) free (lpExeName);
OemToChar (lpIniFileName, *lpFileName);
return FALSE;
}
} else {
free (lpCmdLineName);
SetLastError (ERROR_FILE_NOT_FOUND);
if (lpExeName) free (lpExeName);
if (lpIniFileName) free (lpIniFileName);
return FALSE;
}
}
}
}
static
BOOL
GetDriverName (
IN LPTSTR lpIniFile,
OUT LPTSTR *lpDevName
)
/*++
GetDriverName
looks up driver name in the .ini file and returns it in lpDevName
Arguments
lpIniFile
Filename of ini file
lpDevName
pointer to pointer to reciev buffer w/dev name in it
Return Value
TRUE if found
FALSE if not found in .ini file
--*/
{
DWORD dwRetSize;
if (lpDevName) {
dwRetSize = GetPrivateProfileString (
TEXT("info"), // info section
TEXT("drivername"), // driver name value
TEXT("drivernameNotFound"), // default value
*lpDevName,
MAX_PATH,
lpIniFile);
if ((lstrcmpi(*lpDevName, TEXT("drivernameNotFound"))) != 0) {
// name found
return TRUE;
} else {
// name not found, default returned so return NULL string
*lpDevName = TEXT("\0");
return FALSE;
}
} else {
SetLastError (ERROR_OUTOFMEMORY);
return FALSE;
}
}
static
BOOL
BuildLanguageTables (
IN LPTSTR lpIniFile,
IN OUT PLANGUAGE_LIST_ELEMENT pFirstElem
)
/*++
BuildLanguageTables
Creates a list of structures that will hold the text for
each supported language
Arguments
lpIniFile
Filename with data
pFirstElem
pointer to first list entry
ReturnValue
TRUE if all OK
FALSE if not
--*/
{
LPTSTR lpEnumeratedLangs;
LPTSTR lpThisLang;
PLANGUAGE_LIST_ELEMENT pThisElem;
DWORD dwSize;
lpEnumeratedLangs = malloc(SMALL_BUFFER_SIZE * sizeof(TCHAR));
if (!lpEnumeratedLangs) {
SetLastError (ERROR_OUTOFMEMORY);
return FALSE;
}
dwSize = GetPrivateProfileString (
TEXT("languages"),
NULL, // return all values in multi-sz string
TEXT("009"), // english as the default
lpEnumeratedLangs,
SMALL_BUFFER_SIZE,
lpIniFile);
// do first language
lpThisLang = lpEnumeratedLangs;
// pThisElem = pFirstElem;
pThisElem = NULL;
while (*lpThisLang) {
//
// see if this language is supporte on this machine
//
if (LanguageInstalled(lpThisLang)) {
if (pThisElem == NULL) {
pThisElem = pFirstElem;
} else {
pThisElem->pNextLang = malloc (sizeof(LANGUAGE_LIST_ELEMENT));
if (!pThisElem) {
SetLastError (ERROR_OUTOFMEMORY);
return FALSE;
}
pThisElem = pThisElem->pNextLang; // point to new one
}
pThisElem->pNextLang = NULL;
pThisElem->LangId = (LPTSTR) malloc ((lstrlen(lpThisLang) + 1) * sizeof(TCHAR));
lstrcpy (pThisElem->LangId, lpThisLang);
pThisElem->pFirstName = NULL;
pThisElem->pThisName = NULL;
pThisElem->dwNumElements=0;
pThisElem->NameBuffer = NULL;
pThisElem->HelpBuffer = NULL;
} else {
// skip this language since it isn't installed on the target
// machine
}
// go to next string
lpThisLang += lstrlen(lpThisLang) + 1;
}
return TRUE;
}
static
BOOL
TryOtherPath (
IN LPTSTR lpIniFile,
IN LPTSTR lpIncludeFileName,
OUT OFSTRUCT * pofIncludeFile
)
/*++
TryOtherPath
Get the include file from other locations since it is not found
in the specified location as stated inint ini file.
Arguments
lpIniFile
Ini file with include file name
lpIncludeFileName
Include file name read from the ini file
pofIncludeFile
address of the ofstruct to return the OEM full path name.
Return Value
TRUE if the Include file is nound.
FALSE if it is not found.
--*/
{
BOOL RetCode = FALSE;
TCHAR LocalFileName [MAX_PATH];
CHAR AnsiFileName [MAX_PATH];
int StringLen;
LPTSTR lpTemp;
HFILE hIncludeFile;
LPSTR lpFileName;
lstrcpy (LocalFileName, lpIniFile) ;
lpTemp = LocalFileName + lstrlen(LocalFileName);
while (lpTemp != LocalFileName) {
// location the end of path name for the ini file
if (*lpTemp == TEXT('\\')) {
lpTemp++;
*lpTemp = TEXT('\0');
break;
} else {
lpTemp--;
}
}
if (lpTemp != LocalFileName) {
// now append the IncludeFileName if we have spaces
StringLen = lstrlen (lpIncludeFileName) + lstrlen (LocalFileName);
if (StringLen < sizeof(LocalFileName) / sizeof(TCHAR)) {
lstrcat (LocalFileName, lpIncludeFileName);
}
wcstombs (AnsiFileName, LocalFileName, sizeof(AnsiFileName));
hIncludeFile = OpenFile (
AnsiFileName,
pofIncludeFile,
OF_EXIST);
if (hIncludeFile != HFILE_ERROR) {
CharToOemA (
pofIncludeFile->szPathName,
pofIncludeFile->szPathName);
RetCode = TRUE;
goto Exit0;
}
// last try, use filename only so OpenFile will serach
// along the path
lpFileName = AnsiFileName + strlen(AnsiFileName);
while (lpFileName != AnsiFileName) {
if (*lpFileName == ':' || *lpFileName == '\\') {
lpFileName++;
break;
}
lpFileName--;
}
if (lpFileName != AnsiFileName) {
hIncludeFile = OpenFile (
lpFileName,
pofIncludeFile,
OF_EXIST);
if (hIncludeFile != HFILE_ERROR) {
CharToOemA (
pofIncludeFile->szPathName,
pofIncludeFile->szPathName);
RetCode = TRUE;
goto Exit0;
}
}
}
Exit0:
return (RetCode);
}
static
BOOL
LoadIncludeFile (
IN LPTSTR lpIniFile,
OUT PSYMBOL_TABLE_ENTRY *pTable
)
/*++
LoadIncludeFile
Reads the include file that contains symbolic name definitions and
loads a table with the values defined
Arguments
lpIniFile
Ini file with include file name
pTable
address of pointer to table structure created
Return Value
TRUE if table read or if no table defined
FALSE if error encountere reading table
--*/
{
INT iNumArgs;
DWORD dwSize;
BOOL bReUse;
PSYMBOL_TABLE_ENTRY pThisSymbol = NULL;
LPTSTR lpIncludeFileName;
LPSTR lpIncludeFile;
LPSTR lpLineBuffer;
LPSTR lpAnsiSymbol;
FILE *fIncludeFile;
HFILE hIncludeFile;
OFSTRUCT ofIncludeFile;
lpIncludeFileName = malloc (MAX_PATH * sizeof (TCHAR));
lpIncludeFile = malloc (MAX_PATH);
lpLineBuffer = malloc (DISP_BUFF_SIZE);
lpAnsiSymbol = malloc (DISP_BUFF_SIZE);
if (!lpIncludeFileName || !lpLineBuffer || !lpAnsiSymbol) {
SetLastError (ERROR_OUTOFMEMORY);
return FALSE;
}
// get name of include file (if present)
dwSize = GetPrivateProfileString (
TEXT("info"),
TEXT("symbolfile"),
TEXT("SymbolFileNotFound"),
lpIncludeFileName,
MAX_PATH,
lpIniFile);
if ((lstrcmpi(lpIncludeFileName, TEXT("SymbolFileNotFound"))) == 0) {
// no symbol file defined
*pTable = NULL;
return TRUE;
}
// if here, then a symbol file was defined and is now stored in
// lpIncludeFileName
CharToOem (lpIncludeFileName, lpIncludeFile);
hIncludeFile = OpenFile (
lpIncludeFile,
&ofIncludeFile,
OF_PARSE);
if (hIncludeFile == HFILE_ERROR) {
// unable to generate include filename
// error is already in GetLastError
OUTPUT_MESSAGE (GetFormatResource(LC_ERR_OPEN_INCLUDE), lpIncludeFileName);
*pTable = NULL;
return FALSE;
} else {
// open a stream
fIncludeFile = fopen (ofIncludeFile.szPathName, "rt");
if (!fIncludeFile) {
// try other locations
if (TryOtherPath (
lpIniFile,
lpIncludeFileName,
&ofIncludeFile)) {
// try it again
fIncludeFile = fopen (ofIncludeFile.szPathName, "rt");
}
}
if (!fIncludeFile) {
OUTPUT_MESSAGE (GetFormatResource(LC_ERR_OPEN_INCLUDE), lpIncludeFileName);
*pTable = NULL;
return FALSE;
}
}
//
// read ANSI Characters from include file
//
bReUse = FALSE;
while (fgets(lpLineBuffer, DISP_BUFF_SIZE, fIncludeFile) != NULL) {
if (strlen(lpLineBuffer) > 8) {
if (!bReUse) {
if (*pTable) {
// then add to list
pThisSymbol->pNext = malloc (sizeof (SYMBOL_TABLE_ENTRY));
pThisSymbol = pThisSymbol->pNext;
} else { // allocate first element
*pTable = malloc (sizeof (SYMBOL_TABLE_ENTRY));
pThisSymbol = *pTable;
}
if (!pThisSymbol) {
SetLastError (ERROR_OUTOFMEMORY);
return FALSE;
}
// allocate room for the symbol name by using the line length
// - the size of "#define "
// pThisSymbol->SymbolName = malloc ((strlen(lpLineBuffer) - 8) * sizeof (TCHAR));
pThisSymbol->SymbolName = malloc (DISP_BUFF_SIZE * sizeof (TCHAR));
if (!pThisSymbol->SymbolName) {
SetLastError (ERROR_OUTOFMEMORY);
return FALSE;
}
}
// all the memory is allocated so load the fields
pThisSymbol->pNext = NULL;
iNumArgs = sscanf (lpLineBuffer, "#define %s %d",
lpAnsiSymbol, &pThisSymbol->Value);
if (iNumArgs != 2) {
*(pThisSymbol->SymbolName) = TEXT('\0');
pThisSymbol->Value = (DWORD)-1L;
bReUse = TRUE;
} else {
OemToChar (lpAnsiSymbol, pThisSymbol->SymbolName);
bReUse = FALSE;
}
}
}
if (lpIncludeFileName) free (lpIncludeFileName);
if (lpIncludeFile) free (lpIncludeFile);
if (lpLineBuffer) free (lpLineBuffer);
fclose (fIncludeFile);
return TRUE;
}
static
BOOL
ParseTextId (
IN LPTSTR lpTextId,
IN PSYMBOL_TABLE_ENTRY pFirstSymbol,
OUT PDWORD pdwOffset,
OUT LPTSTR *lpLangId,
OUT PDWORD pdwType
)
/*++
ParseTextId
decodes Text Id key from .INI file
syntax for this process is:
{<DecimalNumber>} {"NAME"}
{<SymbolInTable>}_<LangIdString>_{"HELP"}
e.g. 0_009_NAME
OBJECT_1_009_HELP
Arguments
lpTextId
string to decode
pFirstSymbol
pointer to first entry in symbol table (NULL if no table)
pdwOffset
address of DWORD to recive offest value
lpLangId
address of pointer to Language Id string
(NOTE: this will point into the string lpTextID which will be
modified by this routine)
pdwType
pointer to dword that will recieve the type of string i.e.
HELP or NAME
Return Value
TRUE text Id decoded successfully
FALSE unable to decode string
NOTE: the string in lpTextID will be modified by this procedure
--*/
{
LPTSTR lpThisChar;
PSYMBOL_TABLE_ENTRY pThisSymbol;
// check for valid return arguments
if (!(pdwOffset) ||
!(lpLangId) ||
!(pdwType)) {
SetLastError (ERROR_INVALID_PARAMETER);
return FALSE;
}
// search string from right to left in order to identify the
// components of the string.
lpThisChar = lpTextId + lstrlen(lpTextId); // point to end of string
while (*lpThisChar != TEXT('_')) {
lpThisChar--;
if (lpThisChar <= lpTextId) {
// underscore not found in string
SetLastError (ERROR_INVALID_DATA);
return FALSE;
}
}
// first underscore found
if ((lstrcmpi(lpThisChar, TEXT("_NAME"))) == 0) {
// name found, so set type
*pdwType = TYPE_NAME;
} else if ((lstrcmpi(lpThisChar, TEXT("_HELP"))) == 0) {
// help text found, so set type
*pdwType = TYPE_HELP;
} else {
// bad format
SetLastError (ERROR_INVALID_DATA);
return FALSE;
}
// set the current underscore to \0 and look for language ID
*lpThisChar-- = TEXT('\0');
while (*lpThisChar != TEXT('_')) {
lpThisChar--;
if (lpThisChar <= lpTextId) {
// underscore not found in string
SetLastError (ERROR_INVALID_DATA);
return FALSE;
}
}
// set lang ID string pointer to current char ('_') + 1
*lpLangId = lpThisChar + 1;
// set this underscore to a NULL and try to decode the remaining text
*lpThisChar = TEXT('\0');
// see if the first part of the string is a decimal digit
if ((_stscanf (lpTextId, TEXT(" %d"), pdwOffset)) != 1) {
// it's not a digit, so try to decode it as a symbol in the
// loaded symbol table
for (pThisSymbol=pFirstSymbol;
pThisSymbol && *(pThisSymbol->SymbolName);
pThisSymbol = pThisSymbol->pNext) {
if ((lstrcmpi(lpTextId, pThisSymbol->SymbolName)) == 0) {
// a matching symbol was found, so insert it's value
// and return (that's all that needs to be done
*pdwOffset = pThisSymbol->Value;
return TRUE;
}
}
// if here, then no matching symbol was found, and it's not
// a number, so return an error
SetLastError (ERROR_BAD_TOKEN_TYPE);
return FALSE;
} else {
// symbol was prefixed with a decimal number
return TRUE;
}
}
static
PLANGUAGE_LIST_ELEMENT
FindLanguage (
IN PLANGUAGE_LIST_ELEMENT pFirstLang,
IN LPTSTR pLangId
)
/*++
FindLanguage
searchs the list of languages and returns a pointer to the language
list entry that matches the pLangId string argument
Arguments
pFirstLang
pointer to first language list element
pLangId
pointer to text string with language ID to look up
Return Value
Pointer to matching language list entry
or NULL if no match
--*/
{
PLANGUAGE_LIST_ELEMENT pThisLang;
for (pThisLang = pFirstLang;
pThisLang;
pThisLang = pThisLang->pNextLang) {
if ((lstrcmpi(pLangId, pThisLang->LangId)) == 0) {
// match found so return pointer
return pThisLang;
}
}
return NULL; // no match found
}
static
BOOL
AddEntryToLanguage (
PLANGUAGE_LIST_ELEMENT pLang,
LPTSTR lpValueKey,
DWORD dwType,
DWORD dwOffset,
LPTSTR lpIniFile
)
/*++
AddEntryToLanguage
Add a text entry to the list of text entries for the specified language
Arguments
pLang
pointer to language structure to update
lpValueKey
value key to look up in .ini file
dwOffset
numeric offset of name in registry
lpIniFile
ini file
Return Value
TRUE if added successfully
FALSE if error
(see GetLastError for status)
--*/
{
LPTSTR lpLocalStringBuff;
DWORD dwSize;
DWORD dwBufferSize;
dwBufferSize = SMALL_BUFFER_SIZE * 4 * sizeof(TCHAR);
if (dwBufferSize < dwFileSize) {
dwBufferSize = dwFileSize;
}
lpLocalStringBuff = malloc (dwBufferSize);
if (!lpLocalStringBuff) {
SetLastError (ERROR_OUTOFMEMORY);
return FALSE;
}
dwSize = GetPrivateProfileString (
TEXT("text"), // section
lpValueKey, // key
TEXT("DefaultValue"), // default value
lpLocalStringBuff,
dwBufferSize / sizeof(TCHAR),
lpIniFile);
if ((lstrcmpi(lpLocalStringBuff, TEXT("DefaultValue")))== 0) {
SetLastError (ERROR_BADKEY);
if (lpLocalStringBuff) free (lpLocalStringBuff);
return FALSE;
}
// key found, so load structure
if (!pLang->pThisName) {
// this is the first
pLang->pThisName =
malloc (sizeof (NAME_ENTRY) +
(lstrlen(lpLocalStringBuff) + 1) * sizeof (TCHAR));
if (!pLang->pThisName) {
SetLastError (ERROR_OUTOFMEMORY);
if (lpLocalStringBuff) free (lpLocalStringBuff);
return FALSE;
} else {
pLang->pFirstName = pLang->pThisName;
}
} else {
pLang->pThisName->pNext =
malloc (sizeof (NAME_ENTRY) +
(lstrlen(lpLocalStringBuff) + 1) * sizeof (TCHAR));
if (!pLang->pThisName->pNext) {
SetLastError (ERROR_OUTOFMEMORY);
if (lpLocalStringBuff) free (lpLocalStringBuff);
return FALSE;
} else {
pLang->pThisName = pLang->pThisName->pNext;
}
}
// pLang->pThisName now points to an uninitialized structre
pLang->pThisName->pNext = NULL;
pLang->pThisName->dwOffset = dwOffset;
pLang->pThisName->dwType = dwType;
pLang->pThisName->lpText = (LPTSTR)&(pLang->pThisName[1]); // string follows
lstrcpy (pLang->pThisName->lpText, lpLocalStringBuff);
if (lpLocalStringBuff) free (lpLocalStringBuff);
SetLastError (ERROR_SUCCESS);
return (TRUE);
}
static
BOOL
LoadLanguageLists (
IN LPTSTR lpIniFile,
IN DWORD dwFirstCounter,
IN DWORD dwFirstHelp,
IN PSYMBOL_TABLE_ENTRY pFirstSymbol,
IN PLANGUAGE_LIST_ELEMENT pFirstLang
)
/*++
LoadLanguageLists
Reads in the name and explain text definitions from the ini file and
builds a list of these items for each of the supported languages and
then combines all the entries into a sorted MULTI_SZ string buffer.
Arguments
lpIniFile
file containing the definitions to add to the registry
dwFirstCounter
starting counter name index number
dwFirstHelp
starting help text index number
pFirstLang
pointer to first element in list of language elements
Return Value
TRUE if all is well
FALSE if not
error is returned in GetLastError
--*/
{
LPTSTR lpTextIdArray;
LPTSTR lpLocalKey;
LPTSTR lpThisKey;
DWORD dwSize;
LPTSTR lpLang;
DWORD dwOffset;
DWORD dwType;
PLANGUAGE_LIST_ELEMENT pThisLang;
DWORD dwBufferSize;
dwBufferSize = SMALL_BUFFER_SIZE * 4 * sizeof(TCHAR);
if (dwBufferSize < dwFileSize) {
dwBufferSize = dwFileSize;
}
if (!(lpTextIdArray = malloc (dwBufferSize))) {
SetLastError (ERROR_OUTOFMEMORY);
return FALSE;
}
if (!(lpLocalKey = malloc (MAX_PATH * sizeof(TCHAR)))) {
SetLastError (ERROR_OUTOFMEMORY);
if (lpTextIdArray) free (lpTextIdArray);
return FALSE;
}
// get list of text keys to look up
dwSize = GetPrivateProfileString (
TEXT("text"), // [text] section of .INI file
NULL, // return all keys
TEXT("DefaultKeyValue"), // default
lpTextIdArray, // return buffer
dwBufferSize / sizeof(TCHAR),
lpIniFile); // .INI file name
if ((lstrcmpi(lpTextIdArray, TEXT("DefaultKeyValue"))) == 0) {
// key not found, default returned
SetLastError (ERROR_NO_SUCH_GROUP);
if (lpTextIdArray) free (lpTextIdArray);
if (lpLocalKey) free (lpLocalKey);
return FALSE;
}
// do each key returned
for (lpThisKey=lpTextIdArray;
*lpThisKey;
lpThisKey += (lstrlen(lpThisKey) + 1)) {
lstrcpy (lpLocalKey, lpThisKey); // make a copy of the key
// parse key to see if it's in the correct format
if (ParseTextId(lpLocalKey, pFirstSymbol, &dwOffset, &lpLang, &dwType)) {
// so get pointer to language entry structure
pThisLang = FindLanguage (pFirstLang, lpLang);
if (pThisLang) {
if (!AddEntryToLanguage(pThisLang,
lpThisKey, dwType,
(dwOffset + ((dwType == TYPE_NAME) ? dwFirstCounter : dwFirstHelp)),
lpIniFile)) {
OUTPUT_MESSAGE (GetFormatResource (LC_ERRADDTOLANG),
lpThisKey,
lpLang,
GetLastError());
}
} else { // language not in list
OUTPUT_MESSAGE (GetFormatResource(LC_LANGNOTFOUND), lpLang, lpThisKey);
}
} else { // unable to parse ID string
OUTPUT_MESSAGE(GetFormatResource(LC_BAD_KEY), lpThisKey);
}
}
if (lpTextIdArray) free (lpTextIdArray);
if (lpLocalKey) free (lpLocalKey);
return TRUE;
}
static
BOOL
SortLanguageTables (
PLANGUAGE_LIST_ELEMENT pFirstLang,
PDWORD pdwLastName,
PDWORD pdwLastHelp
)
/*++
SortLangageTables
walks list of languages loaded, allocates and loads a sorted multi_SZ
buffer containing new entries to be added to current names/help text
Arguments
pFirstLang
pointer to first element in list of languages
ReturnValue
TRUE everything done as expected
FALSE error occurred, status in GetLastError
--*/
{
PLANGUAGE_LIST_ELEMENT pThisLang;
BOOL bSorted;
LPTSTR pNameBufPos, pHelpBufPos;
PNAME_ENTRY pThisName, pPrevName;
DWORD dwHelpSize, dwNameSize, dwSize;
if (!pdwLastName || !pdwLastHelp) {
SetLastError (ERROR_BAD_ARGUMENTS);
return FALSE;
}
for (pThisLang = pFirstLang;
pThisLang;
pThisLang = pThisLang->pNextLang) {
// do each language in list
// sort elements in list by value (offset) so that lowest is first
bSorted = FALSE;
while (!bSorted ) {
// point to start of list
pPrevName = pThisLang->pFirstName;
if (pPrevName) {
pThisName = pPrevName->pNext;
} else {
break; // no elements in this list
}
if (!pThisName) {
break; // only one element in the list
}
bSorted = TRUE; // assume that it's sorted
// go until end of list
while (pThisName->pNext) {
if (pThisName->dwOffset > pThisName->pNext->dwOffset) {
// switch 'em
PNAME_ENTRY pA, pB;
pPrevName->pNext = pThisName->pNext;
pA = pThisName->pNext;
pB = pThisName->pNext->pNext;
pThisName->pNext = pB;
pA->pNext = pThisName;
pThisName = pA;
bSorted = FALSE;
}
//move to next entry
pPrevName = pThisName;
pThisName = pThisName->pNext;
}
// if bSorted = TRUE , then we walked all the way down
// the list without changing anything so that's the end.
}
// with the list sorted, build the MULTI_SZ strings for the
// help and name text strings
// compute buffer size
dwNameSize = dwHelpSize = 0;
*pdwLastName = *pdwLastHelp = 0;
for (pThisName = pThisLang->pFirstName;
pThisName;
pThisName = pThisName->pNext) {
// compute buffer requirements for this entry
dwSize = SIZE_OF_OFFSET_STRING;
dwSize += lstrlen (pThisName->lpText);
dwSize += 1; // null
dwSize *= sizeof (TCHAR); // adjust for character size
// add to appropriate size register
if (pThisName->dwType == TYPE_NAME) {
dwNameSize += dwSize;
if (pThisName->dwOffset > *pdwLastName) {
*pdwLastName = pThisName->dwOffset;
}
} else if (pThisName->dwType == TYPE_HELP) {
dwHelpSize += dwSize;
if (pThisName->dwOffset > *pdwLastHelp) {
*pdwLastHelp = pThisName->dwOffset;
}
}
}
// allocate buffers for the Multi_SZ strings
pThisLang->NameBuffer = malloc (dwNameSize);
pThisLang->HelpBuffer = malloc (dwHelpSize);
if (!pThisLang->NameBuffer || !pThisLang->HelpBuffer) {
SetLastError (ERROR_OUTOFMEMORY);
return FALSE;
}
// fill in buffers with sorted strings
pNameBufPos = (LPTSTR)pThisLang->NameBuffer;
pHelpBufPos = (LPTSTR)pThisLang->HelpBuffer;
for (pThisName = pThisLang->pFirstName;
pThisName;
pThisName = pThisName->pNext) {
if (pThisName->dwType == TYPE_NAME) {
// load number as first 0-term. string
dwSize = _stprintf (pNameBufPos, TEXT("%d"), pThisName->dwOffset);
pNameBufPos += dwSize + 1; // save NULL term.
// load the text to match
lstrcpy (pNameBufPos, pThisName->lpText);
pNameBufPos += lstrlen(pNameBufPos) + 1;
} else if (pThisName->dwType == TYPE_HELP) {
// load number as first 0-term. string
dwSize = _stprintf (pHelpBufPos, TEXT("%d"), pThisName->dwOffset);
pHelpBufPos += dwSize + 1; // save NULL term.
// load the text to match
lstrcpy (pHelpBufPos, pThisName->lpText);
pHelpBufPos += lstrlen(pHelpBufPos) + 1;
}
}
// add additional NULL at end of string to terminate MULTI_SZ
*pHelpBufPos = TEXT('\0');
*pNameBufPos = TEXT('\0');
// compute size of MULTI_SZ strings
pThisLang->dwNameBuffSize = (DWORD)((PBYTE)pNameBufPos -
(PBYTE)pThisLang->NameBuffer) +
sizeof(TCHAR);
pThisLang->dwHelpBuffSize = (DWORD)((PBYTE)pHelpBufPos -
(PBYTE)pThisLang->HelpBuffer) +
sizeof(TCHAR);
}
return TRUE;
}
static
BOOL
UpdateEachLanguage (
HKEY hPerflibRoot,
PLANGUAGE_LIST_ELEMENT pFirstLang
)
/*++
UpdateEachLanguage
Goes through list of languages and adds the sorted MULTI_SZ strings
to the existing counter and explain text in the registry.
Also updates the "Last Counter and Last Help" values
Arguments
hPerflibRoot
handle to Perflib key in the registry
pFirstLanguage
pointer to first language entry
Return Value
TRUE all went as planned
FALSE an error occured, use GetLastError to find out what it was.
--*/
{
PLANGUAGE_LIST_ELEMENT pThisLang;
LPTSTR pHelpBuffer;
LPTSTR pNameBuffer;
LPTSTR pNewName;
LPTSTR pNewHelp;
DWORD dwBufferSize;
DWORD dwValueType;
DWORD dwCounterSize;
DWORD dwHelpSize;
HKEY hKeyThisLang;
LONG lStatus;
TCHAR CounterNameBuffer [20];
TCHAR HelpNameBuffer [20];
TCHAR AddCounterNameBuffer [20];
TCHAR AddHelpNameBuffer [20];
for (pThisLang = pFirstLang;
pThisLang;
pThisLang = pThisLang->pNextLang) {
if (dwSystemVersion == OLD_VERSION) {
// Open key for this language
lStatus = RegOpenKeyEx(
hPerflibRoot,
pThisLang->LangId,
RESERVED,
KEY_READ | KEY_WRITE,
&hKeyThisLang);
} else {
lstrcpy (CounterNameBuffer, CounterNameStr);
lstrcat (CounterNameBuffer, pThisLang->LangId);
lstrcpy (HelpNameBuffer, HelpNameStr);
lstrcat (HelpNameBuffer, pThisLang->LangId);
lstrcpy (AddCounterNameBuffer, AddCounterNameStr);
lstrcat (AddCounterNameBuffer, pThisLang->LangId);
lstrcpy (AddHelpNameBuffer, AddHelpNameStr);
lstrcat (AddHelpNameBuffer, pThisLang->LangId);
// make sure this language is loaded
lStatus = RegOpenKeyEx(
hPerflibRoot,
pThisLang->LangId,
RESERVED,
KEY_READ,
&hKeyThisLang);
// we just need the open status, not the key handle so
// close this handle and set the one we need.
RegCloseKey (hKeyThisLang);
// hKeyThisLang = HKEY_PERFORMANCE_DATA;
hKeyThisLang = hPerfData;
}
if (lStatus == ERROR_SUCCESS) {
// make a backup copy of the data file before updating the
// contents
if (dwSystemVersion != OLD_VERSION) {
// this isn't possible on 3.1
MakeBackupCopyOfLanguageFiles (pThisLang->LangId);
}
// get size of counter names
dwBufferSize = 0;
lStatus = RegQueryValueEx (
hKeyThisLang,
(dwSystemVersion == OLD_VERSION) ? Counters : CounterNameBuffer,
RESERVED,
&dwValueType,
NULL,
&dwBufferSize);
if (lStatus != ERROR_SUCCESS) {
if (dwSystemVersion != OLD_VERSION) {
// this means the language is not installed in the system.
continue;
}
SetLastError (lStatus);
return FALSE;
}
dwCounterSize = dwBufferSize;
// get size of help text
dwBufferSize = 0;
lStatus = RegQueryValueEx (
hKeyThisLang,
(dwSystemVersion == OLD_VERSION) ? Help : HelpNameBuffer,
RESERVED,
&dwValueType,
NULL,
&dwBufferSize);
if (lStatus != ERROR_SUCCESS) {
if (dwSystemVersion != OLD_VERSION) {
// this means the language is not installed in the system.
continue;
}
SetLastError (lStatus);
return FALSE;
}
dwHelpSize = dwBufferSize;
// allocate new buffers
dwCounterSize += pThisLang->dwNameBuffSize;
pNameBuffer = malloc (dwCounterSize);
dwHelpSize += pThisLang->dwHelpBuffSize;
pHelpBuffer = malloc (dwHelpSize);
if (!pNameBuffer || !pHelpBuffer) {
SetLastError (ERROR_OUTOFMEMORY);
return (FALSE);
}
// load current buffers into memory
// read counter names into buffer. Counter names will be stored as
// a MULTI_SZ string in the format of "###" "Name"
dwBufferSize = dwCounterSize;
lStatus = RegQueryValueEx (
hKeyThisLang,
(dwSystemVersion == OLD_VERSION) ? Counters : CounterNameBuffer,
RESERVED,
&dwValueType,
(LPVOID)pNameBuffer,
&dwBufferSize);
if (lStatus != ERROR_SUCCESS) {
SetLastError (lStatus);
return FALSE;
}
// set pointer to location in buffer where new string should be
// appended: end of buffer - 1 (second null at end of MULTI_SZ
pNewName = (LPTSTR)((PBYTE)pNameBuffer + dwBufferSize - sizeof(TCHAR));
// adjust buffer length to take into account 2nd null from 1st
// buffer that has been overwritten
dwCounterSize -= sizeof(TCHAR);
// read explain text into buffer. Counter names will be stored as
// a MULTI_SZ string in the format of "###" "Text..."
dwBufferSize = dwHelpSize;
lStatus = RegQueryValueEx (
hKeyThisLang,
(dwSystemVersion == OLD_VERSION) ? Help : HelpNameBuffer,
RESERVED,
&dwValueType,
(LPVOID)pHelpBuffer,
&dwBufferSize);
if (lStatus != ERROR_SUCCESS) {
SetLastError (lStatus);
return FALSE;
}
// set pointer to location in buffer where new string should be
// appended: end of buffer - 1 (second null at end of MULTI_SZ
pNewHelp = (LPTSTR)((PBYTE)pHelpBuffer + dwBufferSize - sizeof(TCHAR));
// adjust buffer length to take into account 2nd null from 1st
// buffer that has been overwritten
dwHelpSize -= sizeof(TCHAR);
// append new strings to end of current strings
memcpy (pNewHelp, pThisLang->HelpBuffer, pThisLang->dwHelpBuffSize);
memcpy (pNewName, pThisLang->NameBuffer, pThisLang->dwNameBuffSize);
if (dwSystemVersion == OLD_VERSION) {
// load new strings back to the registry
lStatus = RegSetValueEx (
hKeyThisLang,
Counters,
RESERVED,
REG_MULTI_SZ,
(LPBYTE)pNameBuffer,
dwCounterSize);
if (lStatus != ERROR_SUCCESS) {
SetLastError (lStatus);
return FALSE;
}
lStatus = RegSetValueEx (
hKeyThisLang,
Help,
RESERVED,
REG_MULTI_SZ,
(LPBYTE)pHelpBuffer,
dwHelpSize);
if (lStatus != ERROR_SUCCESS) {
SetLastError (lStatus);
return FALSE;
}
} else {
// write to the file thru PerfLib
dwBufferSize = dwCounterSize;
lStatus = RegQueryValueEx (
hKeyThisLang,
AddCounterNameBuffer,
RESERVED,
&dwValueType,
(LPVOID)pNameBuffer,
&dwBufferSize);
if (lStatus != ERROR_SUCCESS) {
SetLastError (lStatus);
return FALSE;
}
dwBufferSize = dwHelpSize;
lStatus = RegQueryValueEx (
hKeyThisLang,
AddHelpNameBuffer,
RESERVED,
&dwValueType,
(LPVOID)pHelpBuffer,
&dwBufferSize);
if (lStatus != ERROR_SUCCESS) {
SetLastError (lStatus);
return FALSE;
}
}
free (pNameBuffer);
free (pHelpBuffer);
if (dwSystemVersion == OLD_VERSION)
RegCloseKey (hKeyThisLang);
} else {
OUTPUT_MESSAGE (GetFormatResource (LC_UNABLEOPENLANG), pThisLang->LangId);
}
}
return TRUE;
}
static
BOOL
UpdateRegistry (
LPTSTR lpIniFile,
HKEY hKeyMachine,
LPTSTR lpDriverName,
PLANGUAGE_LIST_ELEMENT pFirstLang,
PSYMBOL_TABLE_ENTRY pFirstSymbol
)
/*++
UpdateRegistry
- checks, and if not busy, sets the "busy" key in the registry
- Reads in the text and help definitions from the .ini file
- Reads in the current contents of the HELP and COUNTER names
- Builds a sorted MULTI_SZ struct containing the new definitions
- Appends the new MULTI_SZ to the current as read from the registry
- loads the new MULTI_SZ string into the registry
- updates the keys in the driver's entry and Perflib's entry in the
registry (e.g. first, last, etc)
- clears the "busy" key
Arguments
lpIniFile
pathname to .ini file conatining definitions
hKeyMachine
handle to HKEY_LOCAL_MACHINE in registry on system to
update counters for.
lpDriverName
Name of device driver to load counters for
pFirstLang
pointer to first element in language structure list
pFirstSymbol
pointer to first element in symbol definition list
Return Value
TRUE if registry updated successfully
FALSE if registry not updated
(This routine will print an error message to stdout if an error
is encountered).
--*/
{
HKEY hDriverPerf = NULL;
HKEY hPerflib = NULL;
LPTSTR lpDriverKeyPath;
DWORD dwType;
DWORD dwSize;
DWORD dwFirstDriverCounter;
DWORD dwFirstDriverHelp;
DWORD dwLastDriverCounter;
DWORD dwLastPerflibCounter;
DWORD dwLastPerflibHelp;
BOOL bStatus;
LONG lStatus;
HANDLE hFileMapping = NULL;
DWORD MapFileSize;
SECURITY_ATTRIBUTES SecAttr;
TCHAR MapFileName[] = TEXT("Perflib Busy");
DWORD *lpData;
bStatus = FALSE;
SetLastError (ERROR_SUCCESS);
// allocate temporary buffers
lpDriverKeyPath = malloc (MAX_PATH * sizeof(TCHAR));
if (!lpDriverKeyPath) {
SetLastError (ERROR_OUTOFMEMORY);
goto UpdateRegExit;
}
// build driver key path string
lstrcpy (lpDriverKeyPath, DriverPathRoot);
lstrcat (lpDriverKeyPath, Slash);
lstrcat (lpDriverKeyPath, lpDriverName);
lstrcat (lpDriverKeyPath, Slash);
lstrcat (lpDriverKeyPath, Performance);
// check if we need to connect to remote machine
if (ComputerName[0]) {
lStatus = !ERROR_SUCCESS;
try {
lStatus = RegConnectRegistry (
(LPTSTR)ComputerName,
HKEY_LOCAL_MACHINE,
&hKeyMachine);
} finally {
if (lStatus != ERROR_SUCCESS) {
SetLastError (lStatus);
hKeyMachine = NULL;
OUTPUT_MESSAGE (GetFormatResource(LC_CONNECT_PROBLEM),
ComputerName, lStatus);
bStatus = FALSE;
goto UpdateRegExit;
}
}
} else {
hKeyMachine = HKEY_LOCAL_MACHINE;
}
// open keys to registry
// open key to driver's performance key
lStatus = RegOpenKeyEx (
hKeyMachine,
lpDriverKeyPath,
RESERVED,
KEY_WRITE | KEY_READ,
&hDriverPerf);
if (lStatus != ERROR_SUCCESS) {
OUTPUT_MESSAGE (GetFormatResource(LC_ERR_OPEN_DRIVERPERF1), lpDriverKeyPath);
OUTPUT_MESSAGE (GetFormatResource(LC_ERR_OPEN_DRIVERPERF2), lStatus);
SetLastError (lStatus);
goto UpdateRegExit;
}
// open key to perflib's "root" key
lStatus = RegOpenKeyEx (
hKeyMachine,
NamesKey,
RESERVED,
KEY_WRITE | KEY_READ,
&hPerflib);
if (lStatus != ERROR_SUCCESS) {
OUTPUT_MESSAGE (GetFormatResource(LC_ERR_OPEN_PERFLIB), lStatus);
SetLastError (lStatus);
goto UpdateRegExit;
}
// get "last" values from PERFLIB
dwType = 0;
dwLastPerflibCounter = 0;
dwSize = sizeof (dwLastPerflibCounter);
lStatus = RegQueryValueEx (
hPerflib,
LastCounter,
RESERVED,
&dwType,
(LPBYTE)&dwLastPerflibCounter,
&dwSize);
if (lStatus != ERROR_SUCCESS) {
// this request should always succeed, if not then worse things
// will happen later on, so quit now and avoid the trouble.
OUTPUT_MESSAGE (GetFormatResource (LC_ERR_READLASTPERFLIB), lStatus);
SetLastError (lStatus);
goto UpdateRegExit;
}
// get last help value now
dwType = 0;
dwLastPerflibHelp = 0;
dwSize = sizeof (dwLastPerflibHelp);
lStatus = RegQueryValueEx (
hPerflib,
LastHelp,
RESERVED,
&dwType,
(LPBYTE)&dwLastPerflibHelp,
&dwSize);
if (lStatus != ERROR_SUCCESS) {
// this request should always succeed, if not then worse things
// will happen later on, so quit now and avoid the trouble.
OUTPUT_MESSAGE (GetFormatResource (LC_ERR_READLASTPERFLIB), lStatus);
SetLastError (lStatus);
goto UpdateRegExit;
}
// get last help value now
dwType = 0;
dwSize = sizeof (dwSystemVersion);
lStatus = RegQueryValueEx (
hPerflib,
VersionStr,
RESERVED,
&dwType,
(LPBYTE)&dwSystemVersion,
&dwSize);
if (lStatus != ERROR_SUCCESS) {
dwSystemVersion = OLD_VERSION;
}
// set the hPerfData to HKEY_PERFORMANCE_DATA for new version
// if remote machine, then need to connect to it.
if (dwSystemVersion != OLD_VERSION) {
hPerfData = HKEY_PERFORMANCE_DATA;
lStatus = !ERROR_SUCCESS;
if (ComputerName[0]) {
#if 0
// the following is not working for remote machine since we
// are using RegQueryValue to add the counter.
// Need to fix up Perflib before it will work
try {
lStatus = RegConnectRegistry (
(LPTSTR)ComputerName,
HKEY_PERFORMANCE_DATA,
&hPerfData);
} finally {
if (lStatus != ERROR_SUCCESS) {
SetLastError (lStatus);
hPerfData = NULL;
OUTPUT_MESSAGE (GetFormatResource(LC_CONNECT_PROBLEM),
ComputerName, lStatus);
bStatus = FALSE;
goto UpdateRegExit;
}
}
#else
// have to do it the old faction way
dwSystemVersion = OLD_VERSION;
lStatus = ERROR_SUCCESS;
#endif
}
} // NEW_VERSION
// see if this driver's counter names have already been installed
// by checking to see if LastCounter's value is less than Perflib's
// Last Counter
dwType = 0;
dwLastDriverCounter = 0;
dwSize = sizeof (dwLastDriverCounter);
lStatus = RegQueryValueEx (
hDriverPerf,
LastCounter,
RESERVED,
&dwType,
(LPBYTE)&dwLastDriverCounter,
&dwSize);
if (lStatus == ERROR_SUCCESS) {
// if key found, then compare with perflib value and exit this
// procedure if the driver's last counter is <= to perflib's last
//
// if key not found, then continue with installation
// on the assumption that the counters have not been installed
if (dwLastDriverCounter <= dwLastPerflibCounter) {
OUTPUT_MESSAGE (GetFormatResource(LC_ERR_ALREADY_IN), lpDriverName);
SetLastError (ERROR_ALREADY_EXISTS);
goto UpdateRegExit;
}
}
// This checking is causing more problems than necessary. Removed
// for now. SHould use named semaphore instead.
#if 0
// everything looks like it's ready to go so first check the
// busy indicator
lStatus = RegQueryValueEx (
hPerflib,
Busy,
RESERVED,
&dwType,
NULL,
&dwSize);
if (lStatus == ERROR_SUCCESS) { // perflib is in use at the moment
OUTPUT_MESSAGE (GetFormatResource (LC_PERFLIBISBUSY));
return ERROR_BUSY;
}
#endif
// create the file mapping
SecAttr.nLength = sizeof (SecAttr);
SecAttr.bInheritHandle = TRUE;
SecAttr.lpSecurityDescriptor = NULL;
MapFileSize = sizeof(DWORD);
hFileMapping = CreateFileMapping ((HANDLE)0xFFFFFFFF, &SecAttr,
PAGE_READWRITE, (DWORD)0, MapFileSize, (LPCTSTR)MapFileName);
if (hFileMapping) {
lpData = MapViewOfFile (hFileMapping,
FILE_MAP_ALL_ACCESS, 0L, 0L, 0L);
if (lpData) {
*lpData = 1L;
UnmapViewOfFile (lpData);
}
}
// set the "busy" indicator under the PERFLIB key
dwSize = lstrlen(lpDriverName) * sizeof (TCHAR);
lStatus = RegSetValueEx (
hPerflib,
Busy,
RESERVED,
REG_SZ,
(LPBYTE)lpDriverName,
dwSize);
if (lStatus != ERROR_SUCCESS) {
OUTPUT_MESSAGE (GetFormatResource (LC_ERR_UNABLESETBUSY), lStatus);
SetLastError (lStatus);
goto UpdateRegExit;
}
// increment (by 2) the last counters so they point to the first
// unused index after the existing names and then
// set the first driver counters
dwFirstDriverCounter = dwLastPerflibCounter += 2;
dwFirstDriverHelp = dwLastPerflibHelp += 2;
// load .INI file definitions into language tables
if (!LoadLanguageLists (lpIniFile, dwLastPerflibCounter, dwLastPerflibHelp,
pFirstSymbol, pFirstLang)) {
// error message is displayed by LoadLanguageLists so just abort
// error is in GetLastError already
goto UpdateRegExit;
}
// all the symbols and definitions have been loaded into internal
// tables. so now they need to be sorted and merged into a multiSZ string
// this routine also updates the "last" counters
if (!SortLanguageTables (pFirstLang, &dwLastPerflibCounter, &dwLastPerflibHelp)) {
OUTPUT_MESSAGE (GetFormatResource(LC_UNABLESORTTABLES), GetLastError());
goto UpdateRegExit;
}
if (!UpdateEachLanguage (hPerflib, pFirstLang)) {
OUTPUT_MESSAGE (GetFormatResource(LC_ERR_UPDATELANG), GetLastError());
goto UpdateRegExit;
}
// update last counters for driver and perflib
// perflib...
lStatus = RegSetValueEx(
hPerflib,
LastCounter,
RESERVED,
REG_DWORD,
(LPBYTE)&dwLastPerflibCounter,
sizeof(DWORD));
if (lStatus != ERROR_SUCCESS) {
OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE),
LastCounter, TEXT("Perflib"));
}
lStatus = RegSetValueEx(
hPerflib,
LastHelp,
RESERVED,
REG_DWORD,
(LPBYTE)&dwLastPerflibHelp,
sizeof(DWORD));
if (lStatus != ERROR_SUCCESS) {
OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE),
LastHelp, TEXT("Perflib"));
}
// and the driver
lStatus = RegSetValueEx(
hDriverPerf,
LastCounter,
RESERVED,
REG_DWORD,
(LPBYTE)&dwLastPerflibCounter,
sizeof(DWORD));
if (lStatus != ERROR_SUCCESS) {
OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE),
LastCounter, lpDriverName);
}
lStatus = RegSetValueEx(
hDriverPerf,
LastHelp,
RESERVED,
REG_DWORD,
(LPBYTE)&dwLastPerflibHelp,
sizeof(DWORD));
if (lStatus != ERROR_SUCCESS) {
OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE),
LastHelp, lpDriverName);
}
lStatus = RegSetValueEx(
hDriverPerf,
FirstCounter,
RESERVED,
REG_DWORD,
(LPBYTE)&dwFirstDriverCounter,
sizeof(DWORD));
if (lStatus != ERROR_SUCCESS) {
OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE),
FirstCounter, lpDriverName);
}
lStatus = RegSetValueEx(
hDriverPerf,
FirstHelp,
RESERVED,
REG_DWORD,
(LPBYTE)&dwFirstDriverHelp,
sizeof(DWORD));
if (lStatus != ERROR_SUCCESS) {
OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE),
FirstHelp, lpDriverName);
}
bStatus = TRUE;
// free temporary buffers
UpdateRegExit:
// clear busy flag
lStatus = RegDeleteValue (
hPerflib,
Busy);
// free temporary buffers
if (lpDriverKeyPath) free (lpDriverKeyPath);
if (hDriverPerf) RegCloseKey (hDriverPerf);
if (hPerflib) RegCloseKey (hPerflib);
// if (dwSystemVersion != OLD_VERSION) {
// RegCloseKey (HKEY_PERFORMANCE_DATA) ;
// }
if (hFileMapping) {
CloseHandle (hFileMapping);
}
if (hPerfData && hPerfData != HKEY_PERFORMANCE_DATA) {
RegCloseKey (hPerfData);
}
if (hKeyMachine && hKeyMachine != HKEY_LOCAL_MACHINE) {
RegCloseKey (hKeyMachine) ;
}
return bStatus;
}
LOADPERF_FUNCTION
LoadPerfCounterTextStringsW (
IN LPWSTR lpCommandLine,
IN BOOL bQuietModeArg
)
/*++
LoadPerfCounterTexStringsW
loads the perf counter strings into the registry and updates
the perf counter text registry values
Arguments
command line string in the following format:
"/?" displays the usage text
"file.ini" loads the perf strings found in file.ini
"\\machine file.ini" loads the perf strings found onto machine
ReturnValue
0 (ERROR_SUCCESS) if command was processed
Non-Zero if command error was detected.
--*/
{
LPTSTR lpIniFile;
LPTSTR lpDriverName;
LANGUAGE_LIST_ELEMENT LangList;
PSYMBOL_TABLE_ENTRY SymbolTable = NULL;
PSYMBOL_TABLE_ENTRY pThisSymbol = NULL;
int ErrorCode = ERROR_SUCCESS;
lpIniFile = malloc (MAX_PATH * sizeof (TCHAR));
lpDriverName = malloc (MAX_PATH * sizeof (TCHAR));
if (!lpIniFile || !lpDriverName) {
return (ERROR_OUTOFMEMORY);
}
*lpIniFile = TEXT('\0');
*lpDriverName = TEXT('\0');
// save quiet mode flag value
bQuietMode = bQuietModeArg;
// read command line to determine what to do
if (GetFileFromCommandLine (lpCommandLine, &lpIniFile)) {
// valid filename (i.e. file exists)
// get device driver name
if (!GetDriverName (lpIniFile, &lpDriverName)) {
OUTPUT_MESSAGE (GetFormatResource(LC_DEVNAME_ERR_1), lpIniFile);
OUTPUT_MESSAGE (GetFormatResource(LC_DEVNAME_ERR_2));
ErrorCode = ERROR_INVALID_PARAMETER;
goto EndOfMain;
}
if (!BuildLanguageTables(lpIniFile, &LangList)) {
OUTPUT_MESSAGE (GetFormatResource(LC_LANGLIST_ERR), lpIniFile);
ErrorCode = LC_LANGLIST_ERR;
goto EndOfMain;
}
if (!LoadIncludeFile(lpIniFile, &SymbolTable)) {
// open errors displayed in routine
ErrorCode = LC_LANGLIST_ERR;
goto EndOfMain;
}
if (!UpdateRegistry(lpIniFile,
HKEY_LOCAL_MACHINE,
lpDriverName,
&LangList,
SymbolTable)) {
OUTPUT_MESSAGE (GetFormatResource(LC_ERR_UPDATE_REG));
ErrorCode = LC_ERR_UPDATE_REG;
}
} else {
if (*lpIniFile) {
OUTPUT_MESSAGE (GetFormatResource(LC_NO_INIFILE), lpIniFile);
} else {
//Incorrect Command Format
// display command line usage
if (!bQuietMode) {
DisplayCommandHelp(LC_FIRST_CMD_HELP, LC_LAST_CMD_HELP);
}
ErrorCode = ERROR_INVALID_PARAMETER;
}
}
EndOfMain:
if (lpIniFile) free (lpIniFile);
if (lpDriverName) free (lpDriverName);
return (ErrorCode);
}
LOADPERF_FUNCTION
LoadPerfCounterTextStringsA (
IN LPSTR lpAnsiCommandLine,
IN BOOL bQuietModeArg
)
{
LPWSTR lpWideCommandLine;
DWORD dwStrLen;
LONG lReturn;
if (lpAnsiCommandLine != NULL) {
//length of string including terminator
dwStrLen = lstrlenA(lpAnsiCommandLine) + 1;
lpWideCommandLine = GlobalAlloc (GPTR, (dwStrLen * sizeof(WCHAR)));
if (lpWideCommandLine != NULL) {
mbstowcs (lpWideCommandLine, lpAnsiCommandLine, dwStrLen);
lReturn = LoadPerfCounterTextStringsW (lpWideCommandLine,
bQuietModeArg );
GlobalFree (lpWideCommandLine);
} else {
lReturn = GetLastError();
}
} else {
lReturn = ERROR_INVALID_PARAMETER;
}
return lReturn;
}