2266 lines
61 KiB
C
2266 lines
61 KiB
C
/*++
|
||
|
||
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;
|
||
}
|