/*++ Copyright (c) 1991-1999 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. Bob Watson (bobw) 10 Mar 99 added event log messages --*/ #ifndef UNICODE #define UNICODE 1 #endif #ifndef _UNICODE #define _UNICODE 1 #endif #ifdef _LODCTR_DBG_OUTPUT #undef _LODCTR_DBG_OUTPUT #endif //#define _LODCTR_DBG_OUTPUT // // "C" Include files // #include #include #include #include #include #include #include #include // // Windows Include files // #include #define __LOADPERF__ #include #include #include #include "wmistr.h" #include "evntrace.h" // // application include files // #include "winperfp.h" #include "common.h" #include "lodctr.h" #include "wbemutil.h" #include "mofcomp.h" #include "ldprfmsg.h" typedef struct _DllValidationData { FILETIME CreationDate; LONGLONG FileSize; } DllValidationData, *pDllValidationData; #define OLD_VERSION 0x010000 #define MAX_PROFILE_BUFFER 65536 static DWORD dwSystemVersion; static DWORD dwFileSize; static TCHAR ComputerName[FILE_NAME_BUFFER_SIZE]; static TCHAR szServiceName[MAX_PATH]; static TCHAR szServiceDisplayName[MAX_PATH]; static HKEY hPerfData; static BOOL bQuietMode = TRUE; // quiet means no _tprintf's // string constants static const TCHAR szDataFileRoot[] = {TEXT("%systemroot%\\system32\\Perf")}; static const TCHAR szDatExt[] = {TEXT(".DAT")}; static const TCHAR szBakExt[] = {TEXT(".BAK")}; static const TCHAR szInfo[] = {TEXT("info")}; static const TCHAR szDriverName[] = {TEXT("drivername")}; static const TCHAR szMofFileName[] = {TEXT("MofFile")}; static const TCHAR szNotFound[] = {TEXT("NotFound")}; static const TCHAR szLanguages[] = {TEXT("languages")}; static const TCHAR sz009[] = {TEXT("009")}; static const TCHAR szSymbolFile[] = {TEXT("symbolfile")}; static const TCHAR szName[] = {TEXT("_NAME")}; static const TCHAR szHelp[] = {TEXT("_HELP")}; static const TCHAR sz_DFormat[] = {TEXT(" %d")}; static const TCHAR szDFormat[] = {TEXT("%d")}; static const TCHAR szText[] = {TEXT("text")}; static const TCHAR szObjects[] = {TEXT("objects")}; static const TCHAR szSpace[] = {TEXT(" ")}; static const TCHAR MapFileName[] = {TEXT("Perflib Busy")}; static const TCHAR szPerflib[] = {TEXT("Perflib")}; static const TCHAR cszLibrary[] = {TEXT("Library")}; static const CHAR caszOpen[] = {"Open"}; static const CHAR caszCollect[] = {"Collect"}; static const CHAR caszClose[] = {"Close"}; static const TCHAR szBaseIndex[] = {TEXT("Base Index")}; static const TCHAR szTrusted[] = {TEXT("Trusted")}; static const TCHAR szDisablePerformanceCounters[] = {TEXT("Disable Performance Counters")}; #define OLD_VERSION 0x010000 LPCWSTR VersionName = (LPCWSTR)L"Version"; LPCWSTR CounterName = (LPCWSTR)L"Counter "; LPCWSTR HelpName = (LPCWSTR)L"Explain "; int __cdecl My_vfwprintf( FILE *str, const wchar_t *format, va_list argptr ); __inline void __cdecl OUTPUT_MESSAGE ( const TCHAR* format, ... ) { va_list args; va_start( args, format ); if (!bQuietMode) { My_vfwprintf(stdout, format, args); } va_end(args); } __inline static PPERF_OBJECT_TYPE NextObject ( PPERF_OBJECT_TYPE pObject ) { // NextObject return ((PPERF_OBJECT_TYPE) ((PBYTE) pObject + pObject->TotalByteLength)); } // NextObject __inline static PERF_COUNTER_DEFINITION * FirstCounter( PERF_OBJECT_TYPE *pObjectDef ) { return (PERF_COUNTER_DEFINITION *) ((PCHAR) pObjectDef + pObjectDef->HeaderLength); } __inline static PERF_COUNTER_DEFINITION * NextCounter( PERF_COUNTER_DEFINITION *pCounterDef ) { return (PERF_COUNTER_DEFINITION *) ((PCHAR) pCounterDef + pCounterDef->ByteLength); } DWORD MakeTempFileName ( LPCWSTR wszRoot, LPWSTR wszTempFilename ) { FILETIME ft; DWORD dwReturn; WCHAR wszLocalFilename[MAX_PATH]; GetSystemTimeAsFileTime (&ft); dwReturn = (DWORD) swprintf(wszLocalFilename, (LPCWSTR)L"%%windir%%\\system32\\wbem\\%s_%8.8x%8.8x.mof", (wszRoot != NULL ? wszRoot : (LPCWSTR)L"LodCtr"), ft.dwHighDateTime, ft.dwLowDateTime); if (dwReturn > 0) { // expand env. vars dwReturn = ExpandEnvironmentStringsW ( wszLocalFilename, wszTempFilename, MAX_PATH-1); } return dwReturn; } DWORD WriteWideStringToAnsiFile ( HANDLE hFile, LPCWSTR szWideString, LPDWORD pdwLength ) { BOOL bStatus; DWORD dwStatus; LPSTR szAnsiString; DWORD dwBytesWritten = 0; szAnsiString = MemoryAllocate(* pdwLength); if (szAnsiString != NULL) { wcstombs (szAnsiString, szWideString, *pdwLength); bStatus = WriteFile ( hFile, (LPCVOID) szAnsiString, *pdwLength, &dwBytesWritten, NULL); if (bStatus) { *pdwLength = dwBytesWritten; dwStatus = ERROR_SUCCESS; } else { dwStatus = GetLastError(); } MemoryFree (szAnsiString); } else { dwStatus = GetLastError(); } return dwStatus; } LPWSTR *BuildNameTable( HKEY hKeyRegistry, // handle to registry db with counter names LPWSTR lpszLangId, // unicode value of Language subkey PDWORD pdwLastItem // size of array in elements ) /*++ BuildNameTable Arguments: hKeyRegistry Handle to an open registry (this can be local or remote.) and is the value returned by RegConnectRegistry or a default key. lpszLangId The unicode id of the language to look up. (default is 409) Return Value: pointer to an allocated table. (the caller must MemoryFree it when finished!) the table is an array of pointers to zero terminated strings. NULL is returned if an error occured. --*/ { LPWSTR *lpReturnValue; LPWSTR *lpCounterId; LPWSTR lpCounterNames; LPWSTR lpHelpText; LPWSTR lpThisName; LONG lWin32Status; DWORD dwLastError; DWORD dwValueType; DWORD dwArraySize; DWORD dwBufferSize; DWORD dwCounterSize; DWORD dwHelpSize; DWORD dwThisCounter; DWORD dwSystemVersion; DWORD dwLastId; DWORD dwLastHelpId; DWORD dwLastCounterId; DWORD dwLastCounterIdUsed; DWORD dwLastHelpIdUsed; HKEY hKeyValue; HKEY hKeyNames; LPWSTR lpValueNameString; WCHAR CounterNameBuffer [50]; WCHAR HelpNameBuffer [50]; lpValueNameString = NULL; //initialize to NULL lpReturnValue = NULL; hKeyValue = NULL; hKeyNames = NULL; // check for null arguments and insert defaults if necessary if (!lpszLangId) { lpszLangId = (LPWSTR)DefaultLangId; } // open registry to get number of items for computing array size __try { lWin32Status = RegOpenKeyEx ( hKeyRegistry, NamesKey, RESERVED, KEY_READ, & hKeyValue); } __except (EXCEPTION_EXECUTE_HANDLER) { lWin32Status = GetExceptionCode(); } if (lWin32Status != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_OPEN_KEY, // event, 2, lWin32Status, __LINE__, 0, 0, 1, (LPWSTR) NamesKey, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LODCTR_BUILDNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), lWin32Status, TRACE_WSTR(NamesKey), NULL)); goto BNT_BAILOUT; } // get number of items dwBufferSize = sizeof (dwLastHelpId); __try { lWin32Status = RegQueryValueEx ( hKeyValue, LastHelp, RESERVED, & dwValueType, (LPBYTE) & dwLastHelpId, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lWin32Status = GetExceptionCode(); } if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_READ_VALUE, // event, 2, lWin32Status, __LINE__, 0, 0, 1, (LPWSTR) LastHelp, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LODCTR_BUILDNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), lWin32Status, TRACE_WSTR(LastHelp), NULL)); goto BNT_BAILOUT; } // get number of items dwBufferSize = sizeof (dwLastId); __try { lWin32Status = RegQueryValueEx ( hKeyValue, LastCounter, RESERVED, & dwValueType, (LPBYTE) & dwLastCounterId, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lWin32Status = GetExceptionCode(); } if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_READ_VALUE, // event, 2, lWin32Status, __LINE__, 0, 0, 1, (LPWSTR) LastCounter, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LODCTR_BUILDNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), lWin32Status, TRACE_WSTR(LastCounter), NULL)); goto BNT_BAILOUT; } dwLastId = (dwLastCounterId < dwLastHelpId) ? (dwLastHelpId) : (dwLastCounterId); // compute size of pointer array dwArraySize = (dwLastId + 1) * sizeof(LPWSTR); // get Perflib system version dwBufferSize = sizeof (dwSystemVersion); __try { lWin32Status = RegQueryValueEx ( hKeyValue, VersionName, RESERVED, & dwValueType, (LPBYTE) & dwSystemVersion, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lWin32Status = GetExceptionCode(); } if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) { dwSystemVersion = OLD_VERSION; // reset the error status lWin32Status = ERROR_SUCCESS; } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LODCTR_BUILDNAMETABLE, 0, lWin32Status, TRACE_DWORD(dwLastCounterId), TRACE_DWORD(dwLastHelpId), NULL)); if (dwSystemVersion == OLD_VERSION) { // get names from registry lpValueNameString = MemoryAllocate ( lstrlen(NamesKey) * sizeof (WCHAR) + lstrlen(Slash) * sizeof (WCHAR) + lstrlen(lpszLangId) * sizeof (WCHAR) + sizeof (UNICODE_NULL)); if (!lpValueNameString) goto BNT_BAILOUT; lstrcpy (lpValueNameString, NamesKey); lstrcat (lpValueNameString, Slash); lstrcat (lpValueNameString, lpszLangId); lWin32Status = RegOpenKeyEx ( hKeyRegistry, lpValueNameString, RESERVED, KEY_READ, & hKeyNames); } else { if (ComputerName[0] == 0) { hKeyNames = HKEY_PERFORMANCE_DATA; } else { __try { lWin32Status = RegConnectRegistry(ComputerName, HKEY_PERFORMANCE_DATA, & hKeyNames); } __except (EXCEPTION_EXECUTE_HANDLER) { lWin32Status = GetExceptionCode(); } } lstrcpy (CounterNameBuffer, CounterName); lstrcat (CounterNameBuffer, lpszLangId); lstrcpy (HelpNameBuffer, HelpName); lstrcat (HelpNameBuffer, lpszLangId); } // get size of counter names and add that to the arrays if (lWin32Status != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_ACCESS_STRINGS, // event, 2, lWin32Status, __LINE__, 0, 0, 1, (LPWSTR) lpszLangId, NULL, NULL); goto BNT_BAILOUT; } dwBufferSize = 0; __try { lWin32Status = RegQueryValueEx ( hKeyNames, dwSystemVersion == OLD_VERSION ? Counters : CounterNameBuffer, RESERVED, & dwValueType, NULL, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lWin32Status = GetExceptionCode(); } if (lWin32Status != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_READ_COUNTER_STRINGS, // event, 2, lWin32Status, __LINE__, 0, 0, 1, (LPWSTR) lpszLangId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LODCTR_BUILDNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), lWin32Status, TRACE_WSTR(Counters), NULL)); goto BNT_BAILOUT; } dwCounterSize = dwBufferSize; // get size of counter names and add that to the arrays if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT; dwBufferSize = 0; __try { lWin32Status = RegQueryValueEx ( hKeyNames, dwSystemVersion == OLD_VERSION ? Help : HelpNameBuffer, RESERVED, & dwValueType, NULL, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lWin32Status = GetExceptionCode(); } if (lWin32Status != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_READ_HELP_STRINGS, // event, 2, lWin32Status, __LINE__, 0, 0, 1, (LPWSTR) lpszLangId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LODCTR_BUILDNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), lWin32Status, TRACE_WSTR(Help), NULL)); goto BNT_BAILOUT; } dwHelpSize = dwBufferSize; lpReturnValue = MemoryAllocate (dwArraySize + dwCounterSize + dwHelpSize); if (!lpReturnValue) { lWin32Status = ERROR_OUTOFMEMORY; SetLastError(lWin32Status); ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_MEMORY_ALLOCATION_FAILURE, // event, 1, __LINE__, 0, 0, 0, 0, NULL, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LODCTR_BUILDNAMETABLE, 0, ERROR_OUTOFMEMORY, NULL)); goto BNT_BAILOUT; } // initialize pointers into buffer lpCounterId = lpReturnValue; lpCounterNames = (LPWSTR)((LPBYTE)lpCounterId + dwArraySize); lpHelpText = (LPWSTR)((LPBYTE)lpCounterNames + dwCounterSize); // read counters into memory dwBufferSize = dwCounterSize; __try { lWin32Status = RegQueryValueEx ( hKeyNames, dwSystemVersion == OLD_VERSION ? Counters : CounterNameBuffer, RESERVED, & dwValueType, (LPVOID) lpCounterNames, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lWin32Status = GetExceptionCode(); } if (lWin32Status != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_READ_COUNTER_STRINGS, // event, 2, lWin32Status, __LINE__, 0, 0, 1, (LPWSTR) lpszLangId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LODCTR_BUILDNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), lWin32Status, TRACE_WSTR(Counters), NULL)); goto BNT_BAILOUT; } dwBufferSize = dwHelpSize; __try { lWin32Status = RegQueryValueEx ( hKeyNames, dwSystemVersion == OLD_VERSION ? Help : HelpNameBuffer, RESERVED, & dwValueType, (LPVOID) lpHelpText, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lWin32Status = GetExceptionCode(); } if (lWin32Status != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_READ_HELP_STRINGS, // event, 2, lWin32Status, __LINE__, 0, 0, 1, (LPWSTR) lpszLangId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LODCTR_BUILDNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), lWin32Status, TRACE_WSTR(Help), NULL)); goto BNT_BAILOUT; } dwLastCounterIdUsed = 0; dwLastHelpIdUsed = 0; // load counter array items for (lpThisName = lpCounterNames; *lpThisName; lpThisName += (lstrlen(lpThisName)+1) ) { // first string should be an integer (in decimal unicode digits) dwThisCounter = wcstoul (lpThisName, NULL, 10); if ((dwThisCounter == 0) || (dwThisCounter > dwLastId)) { lWin32Status = ERROR_INVALID_DATA; SetLastError(lWin32Status); ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_REGISTRY_COUNTER_STRINGS_CORRUPT, // event, 4, dwThisCounter, dwLastCounterId, dwLastId, __LINE__, 1, lpThisName, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LODCTR_BUILDNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), lWin32Status, TRACE_WSTR(lpThisName), TRACE_DWORD(dwThisCounter), TRACE_DWORD(dwLastId), NULL)); goto BNT_BAILOUT; // bad entry } // point to corresponding counter name lpThisName += (lstrlen(lpThisName)+1); // and load array element; lpCounterId[dwThisCounter] = lpThisName; if (dwThisCounter > dwLastCounterIdUsed) dwLastCounterIdUsed = dwThisCounter; } for (lpThisName = lpHelpText; *lpThisName; lpThisName += (lstrlen(lpThisName)+1) ) { // first string should be an integer (in decimal unicode digits) dwThisCounter = wcstoul (lpThisName, NULL, 10); if ((dwThisCounter == 0) || (dwThisCounter > dwLastId)) { lWin32Status = ERROR_INVALID_DATA; SetLastError(lWin32Status); ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_REGISTRY_HELP_STRINGS_CORRUPT, // event, 4, dwThisCounter, dwLastHelpId, dwLastId, __LINE__, 1, lpThisName, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LODCTR_BUILDNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), lWin32Status, TRACE_WSTR(lpThisName), TRACE_DWORD(dwThisCounter), TRACE_DWORD(dwLastId), NULL)); goto BNT_BAILOUT; // bad entry } // point to corresponding counter name lpThisName += (lstrlen(lpThisName)+1); // and load array element; lpCounterId[dwThisCounter] = lpThisName; if (dwThisCounter > dwLastHelpIdUsed) dwLastHelpIdUsed= dwThisCounter; } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LODCTR_BUILDNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), lWin32Status, TRACE_WSTR(lpszLangId), TRACE_DWORD(dwLastCounterIdUsed), TRACE_DWORD(dwLastHelpIdUsed), TRACE_DWORD(dwLastId), NULL)); // check the registry for consistency // the last help string index should be the last ID used if (dwLastCounterIdUsed > dwLastId) { lWin32Status = ERROR_INVALID_DATA; SetLastError(lWin32Status); ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_REGISTRY_INDEX_CORRUPT, // event, 3, dwLastId, dwLastCounterIdUsed, __LINE__, 0, 0, NULL, NULL, NULL); goto BNT_BAILOUT; // bad registry } if (dwLastHelpIdUsed > dwLastId) { lWin32Status = ERROR_INVALID_DATA; SetLastError(lWin32Status); ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_REGISTRY_INDEX_CORRUPT, // event, 3, dwLastId, dwLastHelpIdUsed, __LINE__, 0, 0, NULL, NULL, NULL); goto BNT_BAILOUT; // bad registry } if (pdwLastItem) *pdwLastItem = dwLastId; MemoryFree ((LPVOID)lpValueNameString); if (hKeyValue) { RegCloseKey (hKeyValue); } if (hKeyNames && hKeyNames != HKEY_PERFORMANCE_DATA) { RegCloseKey (hKeyNames); } return lpReturnValue; BNT_BAILOUT: if (lWin32Status != ERROR_SUCCESS) { dwLastError = GetLastError(); } if (lpValueNameString) { MemoryFree ((LPVOID)lpValueNameString); } if (lpReturnValue) { MemoryFree ((LPVOID)lpReturnValue); } if (hKeyValue) { RegCloseKey (hKeyValue); } if (hKeyNames && hKeyNames != HKEY_PERFORMANCE_DATA) { RegCloseKey (hKeyNames); } return NULL; } BOOL MakeBackupCopyOfLanguageFiles ( IN LPCTSTR szLangId ) { TCHAR szOldFileName[MAX_PATH]; TCHAR szTmpFileName[MAX_PATH]; TCHAR szNewFileName[MAX_PATH]; BOOL bStatus; DWORD dwStatus; HANDLE hOutFile; UNREFERENCED_PARAMETER (szLangId); ExpandEnvironmentStrings (szDataFileRoot, szOldFileName, MAX_PATH); _stprintf (szNewFileName, (LPCTSTR)(TEXT("%sStringBackup.INI")), szOldFileName); _stprintf(szTmpFileName, (LPCTSTR)(TEXT("%sStringBackup.TMP")), szOldFileName); // see if the file already exists hOutFile = CreateFile( szTmpFileName, GENERIC_READ, 0, // no sharing NULL, // default security OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hOutFile != INVALID_HANDLE_VALUE) { CloseHandle(hOutFile); bStatus = DeleteFile(szTmpFileName); } // create backup of file // dwStatus = BackupPerfRegistryToFileW (szTmpFileName, NULL); if (dwStatus == ERROR_SUCCESS) { bStatus = CopyFile(szTmpFileName, szNewFileName, FALSE); if (bStatus) { DeleteFile(szTmpFileName); } } else { // unable to create a backup file SetLastError (dwStatus); bStatus = FALSE; } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_MAKEBACKUPCOPYOFLANGUAGEFILES, ARG_DEF(ARG_TYPE_WSTR, 1), GetLastError(), TRACE_WSTR(szNewFileName), NULL)); return bStatus; } BOOL GetFileFromCommandLine ( IN LPTSTR lpCommandLine, OUT LPTSTR *lpFileName, IN DWORD_PTR *pdwFlags ) /*++ 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 pdwFlags pointer to dword containing flag bits 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; LPTSTR lpExeName = NULL; LPTSTR lpCmdLineName = NULL; LPWSTR lpIniFileName = NULL; LPWSTR lpMofFlag = NULL; HANDLE hFileHandle; TCHAR LocalComputerName[FILE_NAME_BUFFER_SIZE]; DWORD NameBuffer; DWORD dwCpuArg, dwIniArg; // check for valid arguments if (!lpCommandLine) return (ERROR_INVALID_PARAMETER); if (!lpFileName) return (ERROR_INVALID_PARAMETER); if (!pdwFlags) return (ERROR_INVALID_PARAMETER); // allocate memory for parsing operation lpExeName = MemoryAllocate (FILE_NAME_BUFFER_SIZE * sizeof(TCHAR)); lpCmdLineName = MemoryAllocate (FILE_NAME_BUFFER_SIZE * sizeof(TCHAR)); lpIniFileName = MemoryAllocate (FILE_NAME_BUFFER_SIZE * sizeof(WCHAR)); lpMofFlag = MemoryAllocate (FILE_NAME_BUFFER_SIZE * sizeof(WCHAR)); if (!lpExeName || !lpIniFileName || !lpCmdLineName || !lpMofFlag) { SetLastError (ERROR_OUTOFMEMORY); if (lpExeName) MemoryFree (lpExeName); if (lpIniFileName) MemoryFree (lpIniFileName); if (lpCmdLineName) MemoryFree (lpCmdLineName); if (lpMofFlag) MemoryFree (lpMofFlag); return FALSE; } else { // get strings from command line RtlZeroMemory(ComputerName, sizeof(TCHAR) * FILE_NAME_BUFFER_SIZE); RtlZeroMemory(LocalComputerName, sizeof(TCHAR) * FILE_NAME_BUFFER_SIZE); // check for mof Flag lstrcpyW (lpMofFlag, GetItemFromString (lpCommandLine, 2, cSpace)); *pdwFlags |= LOADPERF_FLAGS_LOAD_REGISTRY_ONLY; // default unless a switch is found if ((lpMofFlag[0] == cHyphen) || (lpMofFlag[0] == cSlash)) { if ((lpMofFlag[1] == cM) || (lpMofFlag[1] == cm)) { *pdwFlags &= ~LOADPERF_FLAGS_LOAD_REGISTRY_ONLY; // clear that bit } else if ((lpMofFlag[1] == cQuestion)) { // ask for usage if (lpExeName) MemoryFree (lpExeName); if (lpIniFileName) MemoryFree (lpIniFileName); if (lpMofFlag) MemoryFree (lpMofFlag); return FALSE; } dwCpuArg = 3; dwIniArg = 4; } else { dwCpuArg = 2; dwIniArg = 3; } // Get INI File name lstrcpy (lpCmdLineName, GetItemFromString (lpCommandLine, dwIniArg, cSpace)); 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, dwCpuArg, cSpace)); 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, dwCpuArg, cSpace)); iNumArgs = 3; } if (iNumArgs != 2 && iNumArgs != 3) { // wrong number of arguments SetLastError (ERROR_INVALID_PARAMETER); if (lpExeName) MemoryFree (lpExeName); if (lpIniFileName) MemoryFree (lpIniFileName); if (lpMofFlag) MemoryFree (lpMofFlag); return FALSE; } else { // check if there is a computer name in the input line if (LocalComputerName[0] == cBackslash && LocalComputerName[1] == cBackslash) { // 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] = 0; } } if (SearchPath (NULL, lpCmdLineName, NULL, FILE_NAME_BUFFER_SIZE, lpIniFileName, NULL) > 0) { hFileHandle = CreateFile ( lpIniFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); MemoryFree (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) MemoryFree (lpExeName); lstrcpyW (*lpFileName, lpIniFileName); if (lpIniFileName) MemoryFree (lpIniFileName); return TRUE; } else { // filename was on command line, but not valid so return // false, but send name back for error message if (lpExeName) MemoryFree (lpExeName); lstrcpyW (*lpFileName, lpIniFileName); if (lpIniFileName) MemoryFree (lpIniFileName); return FALSE; } } else { MemoryFree (lpCmdLineName); SetLastError (ERROR_OPEN_FAILED); if (lpExeName) MemoryFree (lpExeName); if (lpIniFileName) MemoryFree (lpIniFileName); return FALSE; } } } } BOOL LodctrSetSericeAsTrusted( IN LPCTSTR lpIniFile, IN LPCTSTR szMachineName, IN LPCTSTR szServiceName ) /*++ 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; DWORD dwStatus; BOOL bReturn; static WCHAR szParam[MAX_PATH]; dwRetSize = GetPrivateProfileString ( szInfo, // info section szTrusted, // Trusted name value szNotFound, // default value szParam, MAX_PATH, lpIniFile); if ((lstrcmpi(szParam, szNotFound)) != 0) { // Trusted string found so set dwStatus = SetServiceAsTrustedW ( szMachineName, szServiceName); if (dwStatus != ERROR_SUCCESS) { SetLastError (dwStatus); bReturn = FALSE; } bReturn = TRUE; } else { // Service is not trusted to have a good Perf DLL SetLastError (ERROR_SUCCESS); bReturn = FALSE; } return bReturn; } 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; BOOL bReturn = FALSE; if (lpDevName) { dwRetSize = GetPrivateProfileString ( szInfo, // info section szDriverName, // driver name value szNotFound, // default value * lpDevName, MAX_PATH, lpIniFile); if ((lstrcmpi(*lpDevName, szNotFound)) != 0) { // name found bReturn = TRUE; } else { // name not found, default returned so return NULL string SetLastError (ERROR_BAD_DRIVER); *lpDevName = 0; } } else { SetLastError (ERROR_INVALID_PARAMETER); } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_GETDRIVERNAME, ARG_DEF(ARG_TYPE_WSTR, 1), GetLastError(), TRACE_WSTR(lpIniFile), NULL)); return bReturn; } 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 = NULL; LPTSTR lpThisLang = NULL; PLANGUAGE_LIST_ELEMENT pThisElem; PLANGUAGE_LIST_ELEMENT pPrevElem; DWORD dwSize; BOOL bReturn = FALSE; if (lpIniFile == NULL || pFirstElem == NULL) { SetLastError (ERROR_INVALID_PARAMETER); goto Cleanup; } lpEnumeratedLangs = MemoryAllocate(SMALL_BUFFER_SIZE * sizeof(TCHAR)); if (!lpEnumeratedLangs) { SetLastError (ERROR_OUTOFMEMORY); goto Cleanup; } dwSize = GetPrivateProfileString ( szLanguages, NULL, // return all values in multi-sz string sz009, // english as the default lpEnumeratedLangs, SMALL_BUFFER_SIZE, lpIniFile); // do first language lpThisLang = lpEnumeratedLangs; pThisElem = NULL; pPrevElem = NULL; while (*lpThisLang) { // // see if this language is supporte on this machine // if (pThisElem == NULL) { pThisElem = pPrevElem = pFirstElem; } else { pThisElem->pNextLang = MemoryAllocate (sizeof(LANGUAGE_LIST_ELEMENT)); if (!pThisElem->pNextLang) { SetLastError (ERROR_OUTOFMEMORY); goto Cleanup; } pPrevElem = pThisElem; pThisElem = pThisElem->pNextLang; // point to new one } pThisElem->pNextLang = NULL; pThisElem->LangId = (LPTSTR) MemoryAllocate ((lstrlen(lpThisLang) + 1) * sizeof(TCHAR)); if (pThisElem->LangId == NULL) { if (pThisElem == pFirstElem) { pThisElem = pPrevElem = NULL; } else { MemoryFree(pThisElem); pThisElem = pPrevElem; pThisElem->pNextLang = NULL; } SetLastError(ERROR_OUTOFMEMORY); goto Cleanup; } lstrcpy (pThisElem->LangId, lpThisLang); pThisElem->pFirstName = NULL; pThisElem->pThisName = NULL; pThisElem->dwNumElements=0; pThisElem->NameBuffer = NULL; pThisElem->HelpBuffer = NULL; pThisElem->dwNameBuffSize = 0; pThisElem->dwHelpBuffSize = 0; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_BUILDLANGUAGETABLES, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_SUCCESS, TRACE_WSTR(lpIniFile), TRACE_WSTR(pThisElem->LangId), NULL)); // go to next string lpThisLang += lstrlen(lpThisLang) + 1; } if (pThisElem == NULL) { // then no languages were found SetLastError (ERROR_RESOURCE_LANG_NOT_FOUND); } else { bReturn = TRUE; } Cleanup: if (! bReturn) { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_BUILDLANGUAGETABLES, ARG_DEF(ARG_TYPE_WSTR, 1), GetLastError(), TRACE_WSTR(lpThisLang), NULL)); } if (lpEnumeratedLangs != NULL) { MemoryFree(lpEnumeratedLangs); } return bReturn; } 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 = NULL; LPTSTR lpIncludeFile = NULL; LPTSTR lpIniPath = NULL; LPSTR lpLineBuffer = NULL; LPSTR lpAnsiSymbol = NULL; TCHAR szIniDrive[_MAX_DRIVE]; TCHAR szIniDir[_MAX_DIR]; FILE * fIncludeFile = NULL; DWORD dwLen; BOOL bReturn = TRUE; lpIncludeFileName = MemoryAllocate (MAX_PATH * sizeof (TCHAR)); lpIncludeFile = MemoryAllocate (MAX_PATH * sizeof(TCHAR)); lpLineBuffer = MemoryAllocate (DISP_BUFF_SIZE); lpAnsiSymbol = MemoryAllocate (DISP_BUFF_SIZE); lpIniPath = MemoryAllocate (MAX_PATH * sizeof (TCHAR)); if (!lpIncludeFileName || !lpLineBuffer || !lpAnsiSymbol || !lpIniPath) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_MEMORY_ALLOCATION_FAILURE, // event, 1, __LINE__, 0, 0, 0, 0, NULL, NULL, NULL); SetLastError (ERROR_OUTOFMEMORY); bReturn = FALSE; goto Cleanup; } // get name of include file (if present) dwSize = GetPrivateProfileString ( szInfo, szSymbolFile, szNotFound, lpIncludeFileName, MAX_PATH, lpIniFile); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LOADINCLUDEFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_SUCCESS, TRACE_WSTR(lpIniFile), TRACE_WSTR(lpIncludeFileName), NULL)); if (lstrcmpi(lpIncludeFileName, szNotFound) == 0) { // no symbol file defined * pTable = NULL; bReturn = TRUE; goto Cleanup; } // if here, then a symbol file was defined and is now stored in // lpIncludeFileName // get path for the ini file and search that first _tsplitpath (lpIniFile, szIniDrive, szIniDir, NULL, NULL); lpIniPath = lstrcpy (lpIniPath, szIniDrive); lpIniPath = lstrcat (lpIniPath, szIniDir); dwLen = SearchPath(lpIniPath, lpIncludeFileName, NULL, MAX_PATH, lpIncludeFile, NULL); if (dwLen == 0) { // include file not found with the ini file so search the std. path dwLen = SearchPath(NULL, lpIncludeFileName, NULL, MAX_PATH, lpIncludeFile, NULL); } if (dwLen > 0) { // file name expanded and found so open fIncludeFile = _tfopen (lpIncludeFile, (LPCTSTR)TEXT("rt")); if (fIncludeFile == NULL) { OUTPUT_MESSAGE (GetFormatResource(LC_ERR_OPEN_INCLUDE), lpIncludeFileName); *pTable = NULL; SetLastError (ERROR_OPEN_FAILED); bReturn = FALSE; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LOADINCLUDEFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_OPEN_FAILED, TRACE_WSTR(lpIniFile), TRACE_WSTR(lpIncludeFile), NULL)); goto Cleanup; } } else { // unable to find the include filename // error is already in GetLastError OUTPUT_MESSAGE (GetFormatResource(LC_ERR_OPEN_INCLUDE), lpIncludeFileName); *pTable = NULL; SetLastError (ERROR_BAD_PATHNAME); bReturn = FALSE; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LOADINCLUDEFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_BAD_PATHNAME, TRACE_WSTR(lpIniFile), TRACE_WSTR(lpIncludeFileName), NULL)); goto Cleanup; } // // 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 = MemoryAllocate (sizeof (SYMBOL_TABLE_ENTRY)); pThisSymbol = pThisSymbol->pNext; } else { // allocate first element *pTable = MemoryAllocate (sizeof (SYMBOL_TABLE_ENTRY)); pThisSymbol = *pTable; } if (!pThisSymbol) { SetLastError (ERROR_OUTOFMEMORY); bReturn = FALSE; goto Cleanup; } // allocate room for the symbol name by using the line length // - the size of "#define " // pThisSymbol->SymbolName = MemoryAllocate ((strlen(lpLineBuffer) - 8) * sizeof (TCHAR)); pThisSymbol->SymbolName = MemoryAllocate (DISP_BUFF_SIZE * sizeof (TCHAR)); if (!pThisSymbol->SymbolName) { SetLastError (ERROR_OUTOFMEMORY); bReturn = FALSE; goto Cleanup; } } // 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) = 0; pThisSymbol->Value = (DWORD)-1L; bReUse = TRUE; } else { // OemToChar (lpAnsiSymbol, pThisSymbol->SymbolName); mbstowcs (pThisSymbol->SymbolName, lpAnsiSymbol, lstrlenA(lpAnsiSymbol)+1); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LOADINCLUDEFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_SUCCESS, TRACE_WSTR(lpIncludeFileName), TRACE_WSTR(pThisSymbol->SymbolName), TRACE_DWORD(pThisSymbol->Value), NULL)); bReUse = FALSE; } } } Cleanup: if (! bReturn) { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LOADINCLUDEFILE, ARG_DEF(ARG_TYPE_WSTR, 1), GetLastError(), TRACE_WSTR(lpIniFile), NULL)); } if (lpIncludeFileName) MemoryFree(lpIncludeFileName); if (lpIncludeFile) MemoryFree(lpIncludeFile); if (lpLineBuffer) MemoryFree(lpLineBuffer); if (lpIniPath) MemoryFree(lpIniPath); if (fIncludeFile != NULL) fclose(fIncludeFile); return bReturn; } 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: {} {"NAME"} {}__{"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 != cUnderscore) { lpThisChar--; if (lpThisChar <= lpTextId) { // underscore not found in string SetLastError (ERROR_INVALID_DATA); return FALSE; } } // first underscore found if ((lstrcmpi(lpThisChar, szName)) == 0) { // name found, so set type *pdwType = TYPE_NAME; } else if ((lstrcmpi(lpThisChar, szHelp)) == 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-- = 0; while (*lpThisChar != cUnderscore) { 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 = 0; // see if the first part of the string is a decimal digit if ((_stscanf (lpTextId, sz_DFormat, 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; } } PLANGUAGE_LIST_ELEMENT FindLanguage ( IN PLANGUAGE_LIST_ELEMENT pFirstLang, IN LPCTSTR 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 } BOOL GetValue( LPTSTR lpLocalSectionBuff, LPTSTR lpLocalStringBuff ) { LPTSTR lpPosition; BOOL bReturn = FALSE; lpPosition = _tcschr(lpLocalSectionBuff,cEquals); if (lpPosition) { lpPosition++; // make sure the "=" isn't the last char if (*lpPosition != 0) { //Found the "equals" sign lstrcpy (lpLocalStringBuff,lpPosition); } else { // empty string, return a pseudo blank string lstrcpy(lpLocalStringBuff, L" "); } bReturn = TRUE; } else { //ErrorFinfing the "=" // bad format SetLastError (ERROR_INVALID_DATA); } return bReturn; } BOOL GetValueFromIniKey (LPTSTR lpValueKey, LPTSTR lpTextSection, DWORD* pdwLastReadOffset, DWORD dwTryCount, LPTSTR lpLocalStringBuff ) { LPTSTR lpLocalSectionBuff; DWORD dwIndex; DWORD dwLastReadOffset; BOOL bRetVal = FALSE; if ((lpTextSection) && (lpValueKey)) { dwLastReadOffset = *pdwLastReadOffset; lpLocalSectionBuff = lpTextSection ; lpLocalSectionBuff += dwLastReadOffset; while(!(*lpLocalSectionBuff)){ dwLastReadOffset += (lstrlen(lpTextSection + dwLastReadOffset) + 1); lpLocalSectionBuff = lpTextSection + dwLastReadOffset; *pdwLastReadOffset = dwLastReadOffset; } // search next N entries in buffer for entry // this should usually work since the file // is scanned sequentially so it's tried first for (dwIndex = 0; dwIndex < dwTryCount ; dwIndex++) { // see if this is the correct entry // and return it if it is if (_tcsstr(lpLocalSectionBuff,lpValueKey)) { bRetVal = GetValue(lpLocalSectionBuff, lpLocalStringBuff); //Set the lastReadOffset First dwLastReadOffset += (lstrlen(lpTextSection + dwLastReadOffset) + 1); *pdwLastReadOffset = dwLastReadOffset; break; // out of the for loop } else { // this isn't the correct one so go to the next // entry in the file dwLastReadOffset += (lstrlen(lpTextSection + dwLastReadOffset) + 1); lpLocalSectionBuff = lpTextSection + dwLastReadOffset; *pdwLastReadOffset = dwLastReadOffset; } } if (!bRetVal) { //Cannont Find the key using lastReadOffset //try again from the beggining of the Array dwLastReadOffset = 0; lpLocalSectionBuff = lpTextSection; *pdwLastReadOffset = dwLastReadOffset; while (*lpLocalSectionBuff != 0) { if (_tcsstr(lpLocalSectionBuff,lpValueKey)) { bRetVal = GetValue(lpLocalSectionBuff, lpLocalStringBuff); break; } else { // go to the next entry dwLastReadOffset += (lstrlen(lpTextSection + dwLastReadOffset) + 1); lpLocalSectionBuff = lpTextSection + dwLastReadOffset; *pdwLastReadOffset = dwLastReadOffset; } } } } else { // one or two null pointers so give up now } return bRetVal; } BOOL AddEntryToLanguage ( PLANGUAGE_LIST_ELEMENT pLang, LPTSTR lpValueKey, LPTSTR lpTextSection, DWORD *pdwLastReadOffset, DWORD dwTryCount, 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 = NULL; DWORD dwBufferSize; DWORD dwStatus = ERROR_SUCCESS; BOOL bRetVal; BOOL bReturn = FALSE; UNREFERENCED_PARAMETER (lpIniFile); if ( (dwType == TYPE_NAME && dwOffset < FIRST_EXT_COUNTER_INDEX) || (dwType == TYPE_HELP && dwOffset < FIRST_EXT_HELP_INDEX)) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, (DWORD) LDPRFMSG_CORRUPT_INDEX, 3, dwOffset, dwType, __LINE__, 0, 1, lpValueKey, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_ADDENTRYTOLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_BADKEY, TRACE_WSTR(lpTextSection), TRACE_WSTR(lpValueKey), TRACE_DWORD(dwType), TRACE_DWORD(dwOffset), NULL)); dwStatus = ERROR_BADKEY; goto Cleanup; } dwBufferSize = SMALL_BUFFER_SIZE * 4 * sizeof(TCHAR); if (dwBufferSize < dwFileSize) { dwBufferSize = dwFileSize; } lpLocalStringBuff = MemoryAllocate (dwBufferSize); if (!lpLocalStringBuff) { dwStatus = ERROR_OUTOFMEMORY; goto Cleanup; } bRetVal = GetValueFromIniKey(lpValueKey, lpTextSection, pdwLastReadOffset, dwTryCount, lpLocalStringBuff); if (!bRetVal) { DWORD dwLastReadOffset = * pdwLastReadOffset; TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_ADDENTRYTOLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_BADKEY, TRACE_WSTR(lpTextSection), TRACE_WSTR(lpValueKey), TRACE_DWORD(dwLastReadOffset), NULL)); dwStatus = ERROR_BADKEY; goto Cleanup; } if ((lstrcmpi(lpLocalStringBuff, szNotFound))== 0) { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_ADDENTRYTOLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_BADKEY, TRACE_WSTR(lpTextSection), TRACE_WSTR(lpValueKey), NULL)); dwStatus = ERROR_BADKEY; goto Cleanup; } // key found, so load structure if (!pLang->pThisName) { // this is the first pLang->pThisName = MemoryAllocate (sizeof (NAME_ENTRY) + (lstrlen(lpLocalStringBuff) + 1) * sizeof (TCHAR)); if (!pLang->pThisName) { dwStatus = ERROR_OUTOFMEMORY; goto Cleanup; } else { pLang->pFirstName = pLang->pThisName; } } else { pLang->pThisName->pNext = MemoryAllocate (sizeof (NAME_ENTRY) + (lstrlen(lpLocalStringBuff) + 1) * sizeof (TCHAR)); if (!pLang->pThisName->pNext) { dwStatus = ERROR_OUTOFMEMORY; goto Cleanup; } 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]); lstrcpy (pLang->pThisName->lpText, lpLocalStringBuff); bReturn = TRUE; Cleanup: if (lpLocalStringBuff != NULL) MemoryFree (lpLocalStringBuff); SetLastError(dwStatus); return (bReturn); } BOOL CreateObjectList ( IN LPTSTR lpIniFile, IN DWORD dwFirstDriverCounter, IN PSYMBOL_TABLE_ENTRY pFirstSymbol, IN LPTSTR lpszObjectList, IN PPERFOBJECT_LOOKUP pObjectGuidTable, IN LPDWORD pdwObjectGuidTableEntries ) { TCHAR szDigits[32]; LPTSTR szLangId; TCHAR szTempString[256]; LPWSTR szGuidStringBuffer; LPTSTR szThisKey; DWORD dwSize; DWORD dwObjectCount = 0; DWORD dwId; DWORD dwType; DWORD dwObjectGuidIndex = 0; DWORD dwBufferSize = dwFileSize; LPTSTR szObjectSectionEntries = NULL; BOOL bResult = TRUE; if (dwBufferSize < MAX_PROFILE_BUFFER * sizeof(TCHAR)) { dwBufferSize = MAX_PROFILE_BUFFER * sizeof(TCHAR); } szObjectSectionEntries = MemoryAllocate(dwBufferSize); if (szObjectSectionEntries == NULL) { SetLastError(ERROR_OUTOFMEMORY); bResult = FALSE; goto Cleanup; } ZeroMemory(szObjectSectionEntries, dwBufferSize); szThisKey = & szObjectSectionEntries[0]; dwSize = GetPrivateProfileString ( szObjects, NULL, szNotFound, szObjectSectionEntries, dwBufferSize / sizeof(TCHAR), lpIniFile); * lpszObjectList = 0; if (lstrcmp(szObjectSectionEntries, szNotFound) != 0) { // then some entries were found so read each one, compute the // index value and save in the string buffer passed by the caller for (szThisKey = szObjectSectionEntries; *szThisKey != 0; szThisKey += lstrlen(szThisKey) + 1) { // ParstTextId modifies the string so we need to make a work copy lstrcpy (szTempString, szThisKey); if (ParseTextId(szTempString, pFirstSymbol, &dwId, &szLangId, &dwType)) { // then dwID is the id of an object supported by this DLL if (dwObjectCount != 0) { lstrcat (lpszObjectList, szSpace); } _ultot ((dwId + dwFirstDriverCounter), szDigits, 10); lstrcat (lpszObjectList, szDigits); // // now see if this object has a GUID string // szGuidStringBuffer = MemoryAllocate(1024); if (szGuidStringBuffer == NULL) { // cannot allocate memory for szGuidStringBuffer, ignore // and continue the next one. // dwObjectCount ++; continue; } dwSize = GetPrivateProfileStringW ( szObjects, szThisKey, szNotFound, szGuidStringBuffer, 1024, lpIniFile); if (dwSize > 0) { if (lstrcmpW (szGuidStringBuffer, szNotFound) != 0) { // then some string is present, so see if // it looks like a GUID if ((szGuidStringBuffer[0] == L'{') && (szGuidStringBuffer[9] == L'-') && (szGuidStringBuffer[14] == L'-') && (szGuidStringBuffer[19] == L'-') && (szGuidStringBuffer[24] == L'-') && (szGuidStringBuffer[37] == L'}')) { // then it's probably a GUID so store it szGuidStringBuffer = MemoryResize (szGuidStringBuffer, (dwSize + 1) * sizeof(WCHAR)); if (szGuidStringBuffer == NULL) { // cannot reallocate memory for // szGuidStringBuffer, ignore and continue // the next one. // continue; } if (dwObjectGuidIndex < *pdwObjectGuidTableEntries) { pObjectGuidTable[dwObjectGuidIndex].PerfObjectId = dwId + dwFirstDriverCounter; pObjectGuidTable[dwObjectGuidIndex].GuidString = szGuidStringBuffer; dwObjectGuidIndex++; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_CREATEOBJECTLIST, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_SUCCESS, TRACE_WSTR(lpIniFile), TRACE_WSTR(szGuidStringBuffer), TRACE_DWORD(dwObjectGuidIndex), NULL)); } else { // table is full } } else { // not a GUID so ignore } } else { // no string after object reference } } dwObjectCount++; } else { // invalid key format } } // save size of Guid Table *pdwObjectGuidTableEntries = dwObjectGuidIndex; } else { // log message that object list is not used TRACE((WINPERF_DBG_TRACE_WARNING), (& LoadPerfGuid, __LINE__, LOADPERF_CREATEOBJECTLIST, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_SUCCESS, TRACE_WSTR(lpIniFile), TRACE_DWORD(dwFirstDriverCounter), NULL)); } Cleanup: if (szObjectSectionEntries != NULL) { MemoryFree(szObjectSectionEntries); } return bResult; } 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; LPTSTR lpTextSectionArray; DWORD dwSize; LPTSTR lpLang; DWORD dwOffset; DWORD dwType; PLANGUAGE_LIST_ELEMENT pThisLang, pLangPointer=NULL; DWORD dwBufferSize; DWORD dwSuccessCount = 0; DWORD dwErrorCount = 0; DWORD dwLastReadOffset = 0; DWORD dwTryCount = 4; //Init this value with 4 (at least 4 times to try maching Key and Value) pLangPointer = pFirstLang; while (pFirstLang) { pFirstLang = pFirstLang->pNextLang; //if you have more languages then increase this try limit to 4 + No. of langs dwTryCount++; } pFirstLang = pLangPointer; dwBufferSize = SMALL_BUFFER_SIZE * 4 * sizeof(TCHAR); if (dwBufferSize < dwFileSize) { dwBufferSize = dwFileSize; } lpTextIdArray = MemoryAllocate (dwBufferSize); if (lpTextIdArray == NULL) { SetLastError (ERROR_OUTOFMEMORY); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LOADLANGUAGELISTS, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_OUTOFMEMORY, TRACE_WSTR(lpIniFile), TRACE_DWORD(dwFirstCounter), TRACE_DWORD(dwFirstHelp), NULL)); return FALSE; } lpLocalKey = MemoryAllocate (MAX_PATH * sizeof(TCHAR)); if (lpLocalKey == NULL) { SetLastError (ERROR_OUTOFMEMORY); if (lpTextIdArray) MemoryFree (lpTextIdArray); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LOADLANGUAGELISTS, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_OUTOFMEMORY, TRACE_WSTR(lpIniFile), TRACE_DWORD(dwFirstCounter), TRACE_DWORD(dwFirstHelp), NULL)); return FALSE; } lpTextSectionArray = MemoryAllocate (dwBufferSize); if (lpTextSectionArray == NULL) { SetLastError (ERROR_OUTOFMEMORY); if (lpTextIdArray) MemoryFree(lpTextIdArray); if (lpLocalKey) MemoryFree(lpLocalKey); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LOADLANGUAGELISTS, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_OUTOFMEMORY, TRACE_WSTR(lpIniFile), TRACE_DWORD(dwFirstCounter), TRACE_DWORD(dwFirstHelp), NULL)); return FALSE; } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LOADLANGUAGELISTS, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_SUCCESS, TRACE_WSTR(lpIniFile), TRACE_DWORD(dwFirstCounter), TRACE_DWORD(dwFirstHelp), NULL)); // get list of text keys to look up dwSize = GetPrivateProfileString ( szText, // [text] section of .INI file NULL, // return all keys szNotFound, lpTextIdArray, // return buffer dwBufferSize / sizeof(TCHAR), lpIniFile); // .INI file name if ((lstrcmpi(lpTextIdArray, szNotFound)) == 0) { // key not found, default returned SetLastError (ERROR_NO_SUCH_GROUP); if (lpTextIdArray) MemoryFree(lpTextIdArray); if (lpLocalKey) MemoryFree(lpLocalKey); if (lpTextSectionArray) MemoryFree(lpTextSectionArray); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LOADLANGUAGELISTS, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_NO_SUCH_GROUP, TRACE_WSTR(lpIniFile), TRACE_DWORD(dwFirstCounter), TRACE_DWORD(dwFirstHelp), NULL)); return FALSE; } // get the the [text] section from the ini file dwSize = GetPrivateProfileSection ( szText, // [text] section of .INI file lpTextSectionArray, // return buffer dwBufferSize / sizeof(TCHAR), lpIniFile); // .INI file name // 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, lpTextSectionArray, & dwLastReadOffset, dwTryCount, dwType, (dwOffset + ( (dwType == TYPE_NAME) ? dwFirstCounter : dwFirstHelp)), lpIniFile)) { OUTPUT_MESSAGE (GetFormatResource (LC_ERRADDTOLANG), lpThisKey, lpLang, GetLastError()); dwErrorCount ++; } else { dwSuccessCount ++; } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LOADLANGUAGELISTS, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_SUCCESS, TRACE_WSTR(lpThisKey), TRACE_WSTR(lpLang), TRACE_DWORD(dwOffset), TRACE_DWORD(dwType), NULL)); } else { // language not in list OUTPUT_MESSAGE (GetFormatResource(LC_LANGNOTFOUND), lpLang, lpThisKey); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LOADLANGUAGELISTS, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_SUCCESS, TRACE_WSTR(lpThisKey), TRACE_WSTR(lpLang), NULL)); } } else { // unable to parse ID string OUTPUT_MESSAGE(GetFormatResource(LC_BAD_KEY), lpThisKey); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LOADLANGUAGELISTS, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_BADKEY, TRACE_WSTR(lpThisKey), TRACE_WSTR(lpLang), NULL)); } } if (lpTextIdArray) MemoryFree(lpTextIdArray); if (lpLocalKey) MemoryFree(lpLocalKey); if (lpTextSectionArray) MemoryFree(lpTextSectionArray); return (BOOL) (dwErrorCount == 0); } 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; DWORD dwCurrentLastName; DWORD dwCurrentLastHelp; if (!pdwLastName || !pdwLastHelp) { SetLastError (ERROR_BAD_ARGUMENTS); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_SORTLANGUAGETABLES, 0, ERROR_BAD_ARGUMENTS, NULL)); 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 if (pThisLang->pFirstName == NULL) { // no elements in this list, continue the next one continue; } 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; dwCurrentLastName = 0; dwCurrentLastHelp = 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 > dwCurrentLastName) { dwCurrentLastName = pThisName->dwOffset; } } else if (pThisName->dwType == TYPE_HELP) { dwHelpSize += dwSize; if (pThisName->dwOffset > dwCurrentLastHelp) { dwCurrentLastHelp = pThisName->dwOffset; } } } // allocate buffers for the Multi_SZ strings pThisLang->NameBuffer = MemoryAllocate (dwNameSize); pThisLang->HelpBuffer = MemoryAllocate (dwHelpSize); if (!pThisLang->NameBuffer || !pThisLang->HelpBuffer) { SetLastError (ERROR_OUTOFMEMORY); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_SORTLANGUAGETABLES, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_OUTOFMEMORY, TRACE_WSTR(pThisLang->LangId), TRACE_DWORD(pThisLang->dwNumElements), TRACE_DWORD(dwCurrentLastName), TRACE_DWORD(dwCurrentLastHelp), NULL)); 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, szDFormat, 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, szDFormat, 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 = 0; * pNameBufPos = 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); if (* pdwLastName < dwCurrentLastName) { * pdwLastName = dwCurrentLastName; } if (* pdwLastHelp < dwCurrentLastHelp) { * pdwLastHelp = dwCurrentLastHelp; } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_SORTLANGUAGETABLES, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_SUCCESS, TRACE_WSTR(pThisLang->LangId), TRACE_DWORD(pThisLang->dwNumElements), TRACE_DWORD(dwCurrentLastName), TRACE_DWORD(dwCurrentLastHelp), NULL)); } dwCurrentLastName = * pdwLastName; dwCurrentLastHelp = * pdwLastHelp; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_SORTLANGUAGETABLES, 0, ERROR_SUCCESS, TRACE_DWORD(dwCurrentLastName), TRACE_DWORD(dwCurrentLastHelp), NULL)); return TRUE; } BOOL GetInstalledLanguageList ( HKEY hPerflibRoot, LPTSTR *mszLangList ) /*++ returns a list of language sub keys found under the perflib key --*/ { BOOL bReturn = TRUE; LONG lStatus; DWORD dwIndex = 0; LPTSTR szBuffer; DWORD dwBufSize; LPTSTR szRetBuffer = NULL; DWORD dwRetBufSize = 0; DWORD dwLastBufSize = 0; LPTSTR szNextString; dwBufSize = MAX_PATH; szBuffer = MemoryAllocate(MAX_PATH * sizeof(TCHAR)); if (szBuffer == NULL) { SetLastError (ERROR_OUTOFMEMORY); bReturn = FALSE; } if (bReturn) { while ((lStatus = RegEnumKeyEx (hPerflibRoot, dwIndex, szBuffer, &dwBufSize, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS) { TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_GETINSTALLEDLANGUAGELIST, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_SUCCESS, TRACE_WSTR(szBuffer), TRACE_DWORD(dwIndex), NULL)); dwRetBufSize += (lstrlen(szBuffer) + 1) * sizeof(TCHAR); if (szRetBuffer != NULL) { LPTSTR szTmpBuffer = szRetBuffer; szRetBuffer = MemoryResize(szRetBuffer, dwRetBufSize); if (szRetBuffer == NULL) { MemoryFree(szTmpBuffer); } } else { szRetBuffer = MemoryAllocate(dwRetBufSize); } if (szRetBuffer == NULL) { SetLastError (ERROR_OUTOFMEMORY); bReturn = FALSE; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_GETINSTALLEDLANGUAGELIST, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_OUTOFMEMORY, TRACE_WSTR(szBuffer), TRACE_DWORD(dwIndex), NULL)); break; } szNextString = (LPTSTR) ((LPBYTE) szRetBuffer + dwLastBufSize); lstrcpy(szNextString, szBuffer); dwLastBufSize = dwRetBufSize; dwIndex ++; dwBufSize = MAX_PATH; RtlZeroMemory(szBuffer, MAX_PATH * sizeof(TCHAR)); } } if (bReturn) { LPTSTR szTmpBuffer = szRetBuffer; // add terminating null char dwRetBufSize += sizeof (TCHAR); if (szRetBuffer != NULL) { szRetBuffer = MemoryResize(szRetBuffer, dwRetBufSize); } else { szRetBuffer = MemoryAllocate(dwRetBufSize); } if (szRetBuffer == NULL) { if (szTmpBuffer != NULL) MemoryFree(szTmpBuffer); SetLastError (ERROR_OUTOFMEMORY); bReturn = FALSE; } else { szNextString = (LPTSTR) ((LPBYTE) szRetBuffer + dwLastBufSize); * szNextString = _T('\0'); } } if (bReturn) { * mszLangList = szRetBuffer; } else { * mszLangList = NULL; MemoryFree(szRetBuffer); } return bReturn; } BOOL CheckNameTable( LPTSTR lpNameStr, LPTSTR lpHelpStr, LPDWORD pdwLastCounter, LPDWORD pdwLastHelp, BOOL bUpdate ) { BOOL bResult = TRUE; BOOL bChanged = FALSE; LPTSTR lpThisId; DWORD dwThisId; DWORD dwLastCounter = * pdwLastCounter; DWORD dwLastHelp = * pdwLastHelp; DWORD dwLastId = (dwLastCounter > dwLastHelp) ? (dwLastCounter) : (dwLastHelp); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_CHECKNAMETABLE, 0, ERROR_SUCCESS, TRACE_DWORD(dwLastCounter), TRACE_DWORD(dwLastHelp), NULL)); for (lpThisId = lpNameStr; * lpThisId; lpThisId += (lstrlen(lpThisId) + 1)) { dwThisId = _tcstoul(lpThisId, NULL, 10); if ((dwThisId == 0) || (dwThisId != 1 && dwThisId % 2 != 0)) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_REGISTRY_COUNTER_STRINGS_CORRUPT, 4, dwThisId, dwLastCounter, dwLastId, __LINE__, 1, lpThisId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_CHECKNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_BADKEY, TRACE_WSTR(lpThisId), TRACE_DWORD(dwThisId), TRACE_DWORD(dwLastCounter), TRACE_DWORD(dwLastHelp), NULL)); SetLastError(ERROR_BADKEY); bResult = FALSE; break; } else if (dwThisId > dwLastId || dwThisId > dwLastCounter) { if (bUpdate) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_REGISTRY_COUNTER_STRINGS_CORRUPT, 4, dwThisId, dwLastCounter, dwLastId, __LINE__, 1, lpThisId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_CHECKNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_BADKEY, TRACE_WSTR(lpThisId), TRACE_DWORD(dwThisId), TRACE_DWORD(dwLastCounter), TRACE_DWORD(dwLastHelp), NULL)); SetLastError(ERROR_BADKEY); bResult = FALSE; break; } else { bChanged = TRUE; if (dwThisId > dwLastCounter) dwLastCounter = dwThisId; if (dwLastCounter > dwLastId) dwLastId = dwLastCounter; } } lpThisId += (lstrlen(lpThisId) + 1); } if (! bResult) goto Cleanup; for (lpThisId = lpHelpStr; * lpThisId; lpThisId += (lstrlen(lpThisId) + 1)) { dwThisId = _tcstoul(lpThisId, NULL, 10); if ((dwThisId == 0) || (dwThisId != 1 && dwThisId % 2 == 0)) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_REGISTRY_HELP_STRINGS_CORRUPT, 4, dwThisId, dwLastHelp, dwLastId, __LINE__, 1, lpThisId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_CHECKNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_BADKEY, TRACE_WSTR(lpThisId), TRACE_DWORD(dwThisId), TRACE_DWORD(dwLastCounter), TRACE_DWORD(dwLastHelp), NULL)); SetLastError(ERROR_BADKEY); bResult = FALSE; break; } else if (dwThisId > dwLastId || dwThisId > dwLastHelp) { if (bUpdate) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_REGISTRY_HELP_STRINGS_CORRUPT, 4, dwThisId, dwLastHelp, dwLastId, __LINE__, 1, lpThisId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_CHECKNAMETABLE, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_BADKEY, TRACE_WSTR(lpThisId), TRACE_DWORD(dwThisId), TRACE_DWORD(dwLastCounter), TRACE_DWORD(dwLastHelp), NULL)); SetLastError(ERROR_BADKEY); bResult = FALSE; break; } else { bChanged = TRUE; if (dwThisId > dwLastHelp) dwLastHelp = dwThisId; if (dwLastHelp > dwLastId) dwLastId = dwLastHelp; } } lpThisId += (lstrlen(lpThisId) + 1); } Cleanup: if (bResult) { if (bChanged) { ReportLoadPerfEvent( EVENTLOG_WARNING_TYPE, (DWORD) LDPRFMSG_CORRUPT_PERFLIB_INDEX, 4, * pdwLastCounter, * pdwLastHelp, dwLastCounter, dwLastHelp, 0, NULL, NULL, NULL); * pdwLastCounter = dwLastCounter; * pdwLastHelp = dwLastHelp; } } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_CHECKNAMETABLE, 0, GetLastError(), TRACE_DWORD(dwLastCounter), TRACE_DWORD(dwLastHelp), NULL)); return bResult; } BOOL UpdateEachLanguage ( HKEY hPerflibRoot, LPWSTR mszInstalledLangList, LPDWORD pdwLastCounter, LPDWORD pdwLastHelp, PLANGUAGE_LIST_ELEMENT pFirstLang, BOOL bUpdate ) /*++ 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 mszInstalledLangList MSZ string of installed language keys 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 = NULL; LPTSTR pNameBuffer = NULL; LPTSTR pNewName = NULL; LPTSTR pNewHelp = NULL; DWORD dwLastCounter = * pdwLastCounter; DWORD dwLastHelp = * pdwLastHelp; DWORD dwBufferSize; DWORD dwValueType; DWORD dwCounterSize; DWORD dwHelpSize; HKEY hKeyThisLang; LONG lStatus; TCHAR CounterNameBuffer [20]; TCHAR HelpNameBuffer [20]; TCHAR AddCounterNameBuffer [20]; TCHAR AddHelpNameBuffer [20]; LPTSTR szThisLang; BOOL bResult = TRUE; if (bUpdate && dwSystemVersion != OLD_VERSION) { // this isn't possible on 3.1 MakeBackupCopyOfLanguageFiles(NULL); } for (szThisLang = mszInstalledLangList; *szThisLang != 0; szThisLang += (lstrlen(szThisLang) + 1)) { TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_SUCCESS, TRACE_WSTR(szThisLang), NULL)); if (dwSystemVersion == OLD_VERSION) { // Open key for this language lStatus = RegOpenKeyEx( hPerflibRoot, szThisLang, RESERVED, KEY_READ | KEY_WRITE, & hKeyThisLang); } else { lstrcpy(CounterNameBuffer, CounterNameStr); lstrcat(CounterNameBuffer, szThisLang); lstrcpy(HelpNameBuffer, HelpNameStr); lstrcat(HelpNameBuffer, szThisLang); lstrcpy(AddCounterNameBuffer, AddCounterNameStr); lstrcat(AddCounterNameBuffer, szThisLang); lstrcpy(AddHelpNameBuffer, AddHelpNameStr); lstrcat(AddHelpNameBuffer, szThisLang); // make sure this language is loaded __try { lStatus = RegOpenKeyEx( hPerflibRoot, szThisLang, RESERVED, KEY_READ, & hKeyThisLang); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(szThisLang), NULL)); } // we just need the open status, not the key handle so // close this handle and set the one we need. if (lStatus == ERROR_SUCCESS) { RegCloseKey (hKeyThisLang); } hKeyThisLang = hPerfData; } if (bUpdate) { // look up the new strings to add pThisLang = FindLanguage(pFirstLang, szThisLang); if (pThisLang == NULL) { // try default language if available pThisLang = FindLanguage(pFirstLang, DefaultLangTag); } if (pThisLang == NULL) { // try english language if available pThisLang = FindLanguage(pFirstLang, DefaultLangId); } if (pThisLang == NULL) { // unable to add this language so continue lStatus = ERROR_NO_MATCH; TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, 0, lStatus, TRACE_DWORD(dwLastCounter), TRACE_DWORD(dwLastHelp), NULL)); } else { if ( pThisLang->NameBuffer == NULL || pThisLang->HelpBuffer == NULL) { ReportLoadPerfEvent( EVENTLOG_WARNING_TYPE, // error type (DWORD) LDPRFMSG_CORRUPT_INCLUDE_FILE, // event, 1, __LINE__, 0, 0, 0, 1, pThisLang->LangId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_WARNING), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1), LDPRFMSG_CORRUPT_INCLUDE_FILE, TRACE_WSTR(pThisLang->LangId), NULL)); lStatus = LDPRFMSG_CORRUPT_INCLUDE_FILE; } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(pThisLang->LangId), TRACE_DWORD(dwLastCounter), TRACE_DWORD(dwLastHelp), NULL)); } } if (lStatus == ERROR_SUCCESS) { // get size of counter names dwBufferSize = 0; __try { lStatus = RegQueryValueEx ( hKeyThisLang, (dwSystemVersion == OLD_VERSION) ? Counters : CounterNameBuffer, RESERVED, & dwValueType, NULL, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { if (dwSystemVersion != OLD_VERSION) { // this means the language is not installed in the system. continue; } ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_READ_COUNTER_STRINGS, // event, 2, lStatus, __LINE__, 0, 0, 1, szThisLang, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szThisLang), TRACE_WSTR(Counters), NULL)); bResult = FALSE; goto Cleanup; } dwCounterSize = dwBufferSize; // get size of help text dwBufferSize = 0; __try { lStatus = RegQueryValueEx ( hKeyThisLang, (dwSystemVersion == OLD_VERSION) ? Help : HelpNameBuffer, RESERVED, & dwValueType, NULL, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { if (dwSystemVersion != OLD_VERSION) { // this means the language is not installed in the system. continue; } ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_READ_HELP_STRINGS, // event, 2, lStatus, __LINE__, 0, 0, 1, szThisLang, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szThisLang), TRACE_WSTR(Help), NULL)); bResult = FALSE; goto Cleanup; } dwHelpSize = dwBufferSize; // allocate new buffers if (bUpdate) { dwCounterSize += pThisLang->dwNameBuffSize; dwHelpSize += pThisLang->dwHelpBuffSize; } pNameBuffer = MemoryAllocate(dwCounterSize); pHelpBuffer = MemoryAllocate(dwHelpSize); if (!pNameBuffer || !pHelpBuffer) { lStatus = ERROR_OUTOFMEMORY; TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, 0, ERROR_OUTOFMEMORY, NULL)); bResult = FALSE; goto Cleanup; } ZeroMemory(pNameBuffer, dwCounterSize); ZeroMemory(pHelpBuffer, dwHelpSize); // 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; __try { lStatus = RegQueryValueEx ( hKeyThisLang, (dwSystemVersion == OLD_VERSION) ? Counters : CounterNameBuffer, RESERVED, & dwValueType, (LPVOID)pNameBuffer, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_READ_COUNTER_STRINGS, // event, 2, lStatus, __LINE__, 0, 0, 1, szThisLang, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szThisLang), TRACE_WSTR(Counters), NULL)); bResult = FALSE; goto Cleanup; } if (bUpdate) { // 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; __try { lStatus = RegQueryValueEx ( hKeyThisLang, (dwSystemVersion == OLD_VERSION) ? Help : HelpNameBuffer, RESERVED, & dwValueType, (LPVOID)pHelpBuffer, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_READ_HELP_STRINGS, // event, 2, lStatus, __LINE__, 0, 0, 1, szThisLang, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szThisLang), TRACE_WSTR(Help), NULL)); bResult = FALSE; goto Cleanup; } if (bUpdate) { // 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); } if (bUpdate) { // append new strings to end of current strings memcpy(pNewHelp, pThisLang->HelpBuffer, pThisLang->dwHelpBuffSize); memcpy(pNewName, pThisLang->NameBuffer, pThisLang->dwNameBuffSize); } if (! CheckNameTable(pNameBuffer, pHelpBuffer, & dwLastCounter, & dwLastHelp, bUpdate)) { bResult = FALSE; goto Cleanup; } if (bUpdate) { 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) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_UPDATE_COUNTER_STRINGS, // event, 2, lStatus, __LINE__, 0, 0, 1, pThisLang->LangId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(pThisLang->LangId), TRACE_WSTR(Counters), NULL)); bResult = FALSE; goto Cleanup; } lStatus = RegSetValueEx ( hKeyThisLang, Help, RESERVED, REG_MULTI_SZ, (LPBYTE) pHelpBuffer, dwHelpSize); if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_UPDATE_HELP_STRINGS, // event, 2, lStatus, __LINE__, 0, 0, 1, pThisLang->LangId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(pThisLang->LangId), TRACE_WSTR(Help), NULL)); bResult = FALSE; goto Cleanup; } } else { // write to the file thru PerfLib dwBufferSize = dwCounterSize; __try { lStatus = RegQueryValueEx ( hKeyThisLang, AddCounterNameBuffer, RESERVED, & dwValueType, (LPVOID) pNameBuffer, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_UPDATE_COUNTER_STRINGS, // event, 2, lStatus, __LINE__, 0, 0, 1, pThisLang->LangId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(pThisLang->LangId), TRACE_WSTR(AddCounterNameBuffer), NULL)); bResult = FALSE; goto Cleanup; } dwBufferSize = dwHelpSize; __try { lStatus = RegQueryValueEx ( hKeyThisLang, AddHelpNameBuffer, RESERVED, & dwValueType, (LPVOID) pHelpBuffer, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_UPDATE_HELP_STRINGS, // event, 2, lStatus, __LINE__, 0, 0, 1, pThisLang->LangId, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEEACHLANGUAGE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(pThisLang->LangId), TRACE_WSTR(AddHelpNameBuffer), NULL)); bResult = FALSE; goto Cleanup; } } } MemoryFree(pNameBuffer); MemoryFree(pHelpBuffer); pNameBuffer = NULL; pHelpBuffer = NULL; if (dwSystemVersion == OLD_VERSION) { RegCloseKey (hKeyThisLang); } } else { OUTPUT_MESSAGE (GetFormatResource (LC_UNABLEOPENLANG), szThisLang); } } Cleanup: if (! bResult) { SetLastError(lStatus); } else if (! bUpdate) { * pdwLastCounter = dwLastCounter; * pdwLastHelp = dwLastHelp; } if (pNameBuffer != NULL) MemoryFree(pNameBuffer); if (pHelpBuffer != NULL) MemoryFree(pHelpBuffer); return bResult; } BOOL UpdateRegistry ( LPTSTR lpIniFile, LPTSTR lpDriverName, PLANGUAGE_LIST_ELEMENT pFirstLang, PSYMBOL_TABLE_ENTRY pFirstSymbol, PPERFOBJECT_LOOKUP plObjectGuidTable, LPDWORD pdwObjectGuidTableSize, LPDWORD pdwIndexValues ) /*++ 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) - deletes the DisablePerformanceCounters value if it's present in order to re-enable the perf counter DLL - 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; HKEY hKeyMachine = NULL; DWORD dwType; DWORD dwSize; DWORD dwFirstDriverCounter; DWORD dwFirstDriverHelp; DWORD dwLastDriverCounter; DWORD dwLastPerflibCounter; DWORD dwLastPerflibHelp; DWORD dwPerflibBaseIndex; DWORD dwLastCounter; DWORD dwLastHelp; BOOL bStatus; LONG lStatus; LPTSTR lpszObjectList = NULL; DWORD dwObjectList = dwFileSize; LPTSTR mszLangList = NULL; DWORD dwWaitStatus; HANDLE hLocalMutex = NULL; if (LoadPerfGrabMutex() == FALSE) { return FALSE; } bStatus = FALSE; SetLastError (ERROR_SUCCESS); // allocate temporary buffers lpDriverKeyPath = MemoryAllocate (MAX_PATH * sizeof(TCHAR)); if (dwObjectList < MAX_PROFILE_BUFFER * sizeof(TCHAR)) { dwObjectList = MAX_PROFILE_BUFFER * sizeof(TCHAR); } lpszObjectList = MemoryAllocate(dwObjectList); if (lpDriverKeyPath == NULL || lpszObjectList == NULL) { SetLastError (ERROR_OUTOFMEMORY); goto UpdateRegExit; } ZeroMemory(lpDriverKeyPath, MAX_PATH * sizeof(TCHAR)); ZeroMemory(lpszObjectList, dwObjectList); // 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; } } if (lStatus != ERROR_SUCCESS) goto UpdateRegExit; } else { hKeyMachine = HKEY_LOCAL_MACHINE; } // open keys to registry // open key to driver's performance key __try { lStatus = RegOpenKeyEx( hKeyMachine, lpDriverKeyPath, RESERVED, KEY_WRITE | KEY_READ, & hDriverPerf); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_OPEN_KEY, // event, 2, lStatus, __LINE__, 0, 0, 1, (LPWSTR) lpDriverKeyPath, NULL, NULL); OUTPUT_MESSAGE (GetFormatResource(LC_ERR_OPEN_DRIVERPERF1), lpDriverKeyPath); OUTPUT_MESSAGE (GetFormatResource(LC_ERR_OPEN_DRIVERPERF2), lStatus); SetLastError (lStatus); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(lpIniFile), TRACE_WSTR(lpDriverName), NULL)); goto UpdateRegExit; } // open key to perflib's "root" key __try { lStatus = RegOpenKeyEx( hKeyMachine, NamesKey, RESERVED, KEY_WRITE | KEY_READ, & hPerflib); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_OPEN_KEY, // event, 2, lStatus, __LINE__, 0, 0, 1, (LPWSTR) NamesKey, NULL, NULL); OUTPUT_MESSAGE (GetFormatResource(LC_ERR_OPEN_PERFLIB), lStatus); SetLastError (lStatus); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_WSTR(NamesKey), NULL)); goto UpdateRegExit; } // get "LastCounter" values from PERFLIB dwType = 0; dwLastPerflibCounter = 0; dwSize = sizeof (dwLastPerflibCounter); __try { lStatus = RegQueryValueEx ( hPerflib, LastCounter, RESERVED, & dwType, (LPBYTE) & dwLastPerflibCounter, & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } 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. ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_QUERY_VALUE, // event, 2, lStatus, __LINE__, 0, 0, 2, (LPWSTR) LastCounter, (LPWSTR) NamesKey, NULL); OUTPUT_MESSAGE (GetFormatResource (LC_ERR_READLASTPERFLIB), lStatus); SetLastError (lStatus); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(NamesKey), TRACE_WSTR(LastCounter), NULL)); goto UpdateRegExit; } // get "LastHelp" value now dwType = 0; dwLastPerflibHelp = 0; dwSize = sizeof (dwLastPerflibHelp); __try { lStatus = RegQueryValueEx ( hPerflib, LastHelp, RESERVED, & dwType, (LPBYTE) & dwLastPerflibHelp, & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } 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. ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_QUERY_VALUE, // event, 2, lStatus, __LINE__, 0, 0, 2, (LPWSTR) LastHelp, (LPWSTR) NamesKey, NULL); OUTPUT_MESSAGE (GetFormatResource (LC_ERR_READLASTPERFLIB), lStatus); SetLastError (lStatus); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(NamesKey), TRACE_WSTR(LastHelp), NULL)); goto UpdateRegExit; } // get "Base Index" value now dwType = 0; dwPerflibBaseIndex = 0; dwSize = sizeof (dwPerflibBaseIndex); __try { lStatus = RegQueryValueEx ( hPerflib, szBaseIndex, RESERVED, & dwType, (LPBYTE) & dwPerflibBaseIndex, & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } 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. ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_QUERY_VALUE, // event, 2, lStatus, __LINE__, 0, 0, 2, (LPWSTR) szBaseIndex, (LPWSTR) NamesKey, NULL); OUTPUT_MESSAGE (GetFormatResource (LC_ERR_READLASTPERFLIB), lStatus); SetLastError (lStatus); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(NamesKey), TRACE_WSTR(szBaseIndex), NULL)); goto UpdateRegExit; } // get "Version" value now dwType = 0; dwSize = sizeof (dwSystemVersion); __try { lStatus = RegQueryValueEx ( hPerflib, VersionStr, RESERVED, & dwType, (LPBYTE) & dwSystemVersion, & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } 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]) { // have to do it the old faction way dwSystemVersion = OLD_VERSION; lStatus = ERROR_SUCCESS; } } // 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); __try { lStatus = RegQueryValueEx ( hDriverPerf, LastCounter, RESERVED, & dwType, (LPBYTE) & dwLastDriverCounter, & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } 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; } } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(lpIniFile), TRACE_WSTR(lpDriverName), TRACE_DWORD(dwLastPerflibCounter), TRACE_DWORD(dwLastPerflibHelp), TRACE_DWORD(dwPerflibBaseIndex), TRACE_DWORD(dwSystemVersion), NULL)); // set the "busy" indicator under the PERFLIB key dwSize = lstrlen(lpDriverName) * sizeof (TCHAR); __try { lStatus = RegSetValueEx( hPerflib, Busy, RESERVED, REG_SZ, (LPBYTE) lpDriverName, dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { OUTPUT_MESSAGE (GetFormatResource (LC_ERR_UNABLESETBUSY), lStatus); SetLastError (lStatus); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(NamesKey), TRACE_WSTR(Busy), NULL)); goto UpdateRegExit; } dwLastCounter = dwLastPerflibCounter; dwLastHelp = dwLastPerflibHelp; // get the list of installed languages on this machine if (!GetInstalledLanguageList (hPerflib, &mszLangList)) { OUTPUT_MESSAGE (GetFormatResource(LC_ERR_UPDATELANG), GetLastError()); goto UpdateRegExit; } if (!UpdateEachLanguage(hPerflib, mszLangList, & dwLastCounter, & dwLastHelp, pFirstLang, FALSE)) { OUTPUT_MESSAGE (GetFormatResource(LC_ERR_UPDATELANG), GetLastError()); 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 = dwLastCounter + 2; dwFirstDriverHelp = dwLastHelp + 2; if ( (dwPerflibBaseIndex < PERFLIB_BASE_INDEX) || (dwFirstDriverCounter < dwPerflibBaseIndex) || (dwFirstDriverHelp < dwPerflibBaseIndex)) { // potential CounterIndex/HelpIndex overlap with Base counters, // ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_REGISTRY_BASEINDEX_CORRUPT, // event, 4, dwPerflibBaseIndex, dwFirstDriverCounter, dwFirstDriverHelp, __LINE__, 1, lpDriverName, NULL, NULL); lStatus = ERROR_BADKEY; SetLastError(lStatus); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(lpDriverName), TRACE_DWORD(dwPerflibBaseIndex), TRACE_DWORD(dwFirstDriverCounter), TRACE_DWORD(dwFirstDriverHelp), NULL)); goto UpdateRegExit; } // load .INI file definitions into language tables if (!LoadLanguageLists (lpIniFile, dwFirstDriverCounter , dwFirstDriverHelp, pFirstSymbol, pFirstLang)) { // error message is displayed by LoadLanguageLists so just abort // error is in GetLastError already goto UpdateRegExit; } if (!CreateObjectList (lpIniFile, dwFirstDriverCounter, pFirstSymbol, lpszObjectList, plObjectGuidTable, pdwObjectGuidTableSize)) { // error message is displayed by CreateObjectList 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, &dwLastCounter, &dwLastHelp)) { OUTPUT_MESSAGE (GetFormatResource(LC_UNABLESORTTABLES), GetLastError()); goto UpdateRegExit; } if ( (dwLastCounter < dwLastPerflibCounter) || (dwLastHelp < dwLastPerflibHelp)) { // potential CounterIndex/HelpIndex overlap with Base counters, // ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_REGISTRY_BASEINDEX_CORRUPT, // event, 4, dwLastPerflibCounter, dwLastCounter, dwLastHelp, __LINE__, 1 , lpDriverName, NULL, NULL); lStatus = ERROR_BADKEY; SetLastError(lStatus); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(lpDriverName), TRACE_DWORD(dwLastPerflibCounter), TRACE_DWORD(dwLastPerflibHelp), TRACE_DWORD(dwLastCounter), TRACE_DWORD(dwLastHelp), NULL)); goto UpdateRegExit; } if (!UpdateEachLanguage(hPerflib, mszLangList, & dwLastCounter, & dwLastHelp, pFirstLang, TRUE)) { OUTPUT_MESSAGE (GetFormatResource(LC_ERR_UPDATELANG), GetLastError()); goto UpdateRegExit; } dwLastPerflibCounter = dwLastCounter; dwLastPerflibHelp = dwLastHelp; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(lpDriverName), TRACE_DWORD(dwFirstDriverCounter), TRACE_DWORD(dwFirstDriverHelp), TRACE_DWORD(dwLastPerflibCounter), TRACE_DWORD(dwLastPerflibHelp), NULL)); if (dwLastCounter < dwFirstDriverCounter) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_CORRUPT_INDEX_RANGE, // event, 3, dwFirstDriverCounter, dwLastCounter, __LINE__, 0, 2, (LPWSTR) Counters, (LPWSTR) lpDriverKeyPath, NULL); goto UpdateRegExit; } if (dwLastHelp < dwFirstDriverHelp) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_CORRUPT_INDEX_RANGE, // event, 3, dwFirstDriverHelp, dwLastHelp, __LINE__, 0, 2, (LPWSTR) Help, (LPWSTR) lpDriverKeyPath, NULL); goto UpdateRegExit; } // update last counters for driver and perflib // perflib... __try { lStatus = RegSetValueEx( hPerflib, LastCounter, RESERVED, REG_DWORD, (LPBYTE) & dwLastPerflibCounter, sizeof(DWORD)); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event, 3, lStatus, dwLastPerflibCounter, __LINE__, 0, 2, (LPWSTR) LastCounter, (LPWSTR) NamesKey, NULL); OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE), LastCounter, szPerflib); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(NamesKey), TRACE_WSTR(LastCounter), TRACE_DWORD(dwLastPerflibCounter), NULL)); } __try { lStatus = RegSetValueEx( hPerflib, LastHelp, RESERVED, REG_DWORD, (LPBYTE) & dwLastPerflibHelp, sizeof(DWORD)); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event, 3, lStatus, dwLastPerflibHelp, __LINE__, 0, 2, (LPWSTR) LastHelp, (LPWSTR) NamesKey, NULL); OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE), LastHelp, szPerflib); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(NamesKey), TRACE_WSTR(LastHelp), TRACE_DWORD(dwLastPerflibHelp), NULL)); } // and the driver __try { lStatus = RegSetValueEx( hDriverPerf, LastCounter, RESERVED, REG_DWORD, (LPBYTE) & dwLastPerflibCounter, sizeof(DWORD)); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event, 3, lStatus, dwLastPerflibCounter, __LINE__, 0, 2, (LPWSTR) LastCounter, (LPWSTR) lpDriverKeyPath, NULL); OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE), LastCounter, lpDriverName); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_WSTR(LastCounter), TRACE_DWORD(dwLastPerflibCounter), NULL)); } __try { lStatus = RegSetValueEx( hDriverPerf, LastHelp, RESERVED, REG_DWORD, (LPBYTE) & dwLastPerflibHelp, sizeof(DWORD)); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event, 3, lStatus, dwLastPerflibHelp, __LINE__, 0, 2, (LPWSTR) LastHelp, (LPWSTR) lpDriverKeyPath, NULL); OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE), LastHelp, lpDriverName); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_WSTR(LastHelp), TRACE_DWORD(dwLastPerflibHelp), NULL)); } __try { lStatus = RegSetValueEx( hDriverPerf, cszFirstCounter, RESERVED, REG_DWORD, (LPBYTE) & dwFirstDriverCounter, sizeof(DWORD)); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event, 3, lStatus, dwFirstDriverCounter, __LINE__, 0, 2, (LPWSTR) cszFirstCounter, (LPWSTR) lpDriverKeyPath, NULL); OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE), cszFirstCounter, lpDriverName); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_WSTR(cszFirstCounter), TRACE_DWORD(dwFirstDriverCounter), NULL)); } __try { lStatus = RegSetValueEx( hDriverPerf, FirstHelp, RESERVED, REG_DWORD, (LPBYTE) & dwFirstDriverHelp, sizeof(DWORD)); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event, 3, lStatus, dwFirstDriverHelp, __LINE__, 0, 2, (LPWSTR) FirstHelp, (LPWSTR) lpDriverKeyPath, NULL); OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE), FirstHelp, lpDriverName); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_WSTR(FirstHelp), TRACE_DWORD(dwFirstDriverHelp), NULL)); } if (*lpszObjectList != 0) { __try { lStatus = RegSetValueEx( hDriverPerf, szObjectList, RESERVED, REG_SZ, (LPBYTE) lpszObjectList, (lstrlen(lpszObjectList) + 1) * sizeof (TCHAR)); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event, 2, lStatus, __LINE__, 0, 0, 2, (LPWSTR) szObjectList, (LPWSTR) lpDriverKeyPath, NULL); OUTPUT_MESSAGE (GetFormatResource (LC_UNABLESETVALUE), szObjectList, lpDriverName); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEREGISTRY, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_WSTR(szObjectList), NULL)); } } bStatus = TRUE; pdwIndexValues[0] = dwFirstDriverCounter; // first Counter pdwIndexValues[1] = dwLastPerflibCounter; // last Counter pdwIndexValues[2] = dwFirstDriverHelp; // first Help pdwIndexValues[3] = dwLastPerflibHelp; // last Help // remove "DisablePerformanceCounter" value so perf counters are re-enabled. lStatus = RegDeleteValue (hDriverPerf, szDisablePerformanceCounters); // MemoryFree temporary buffers UpdateRegExit: // clear busy flag if (hPerflib) { lStatus = RegDeleteValue ( hPerflib, Busy); } ReleaseMutex(hLoadPerfMutex); // MemoryFree temporary buffers // free any guid string buffers here // TODO: add this code if (lpDriverKeyPath) MemoryFree (lpDriverKeyPath); if (lpszObjectList) MemoryFree (lpszObjectList); if (hDriverPerf) RegCloseKey (hDriverPerf); if (hPerflib) RegCloseKey (hPerflib); if (mszLangList != NULL) MemoryFree(mszLangList); if (hPerfData && hPerfData != HKEY_PERFORMANCE_DATA) { RegCloseKey (hPerfData); } if (hKeyMachine && hKeyMachine != HKEY_LOCAL_MACHINE) { RegCloseKey (hKeyMachine) ; } return bStatus; } DWORD GetMofFileFromIni ( LPCWSTR lpIniFile, LPWSTR MofFilename ) { DWORD dwRetSize; DWORD dwReturn = ERROR_SUCCESS; if (MofFilename) { dwRetSize = GetPrivateProfileString ( szInfo, // info section szMofFileName, // Mof Filename value szNotFound, // default value MofFilename, // output buffer MAX_PATH, // buffer size lpIniFile); // ini file to read if ((lstrcmpi(MofFilename, szNotFound)) != 0) { // name found TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_GETMOFFILEFROMINI, ARG_DEF(ARG_TYPE_WSTR, 1), dwReturn, TRACE_WSTR(MofFilename), NULL)); } else { // name not found, default returned so return NULL string MofFilename[0] = 0; dwReturn = ERROR_FILE_NOT_FOUND; } } else { dwReturn = ERROR_INVALID_PARAMETER; } if (dwReturn != ERROR_SUCCESS) { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_GETMOFFILEFROMINI, 0, dwReturn, NULL)); } return dwReturn; } DWORD OpenCounterAndBuildMofFile ( LPCWSTR lpDriverName, LPCWSTR MofFilename, PPERFOBJECT_LOOKUP plObjectGuidTable, DWORD dwObjectGuidTableSize ) { DWORD dwType; DWORD dwSize; HKEY hKeyMachine = NULL; HKEY hDriverPerf = NULL; LONG lStatus = ERROR_SUCCESS; LPWSTR *lpCounterText; LPWSTR *lpDisplayText = NULL; // Localized name strings array DWORD dwLastElement; WCHAR lpDriverKeyPath[MAX_PATH]; WCHAR wszPerfLibraryName[MAX_PATH]; WCHAR wszLibraryExpPath[MAX_PATH]; WCHAR szProviderName[MAX_PATH]; DWORD dwProviderNameSize; HANDLE hPerfLibrary = NULL; CHAR szOpenProcName[MAX_PATH]; PM_OPEN_PROC *pOpenProc = NULL; CHAR szCollectProcName[MAX_PATH]; PM_COLLECT_PROC *pCollectProc = NULL; CHAR szCloseProcName[MAX_PATH]; PM_CLOSE_PROC *pCloseProc = NULL; LPBYTE pPerfBuffer = NULL; LPBYTE pPerfBufferArg; DWORD dwPerfBufferSize; DWORD dwThisObject; DWORD dwThisCounterDef; WCHAR szMofBuffer[8192*2]; DWORD dwMofBufferSize; HANDLE hMofFile; PERF_COUNTER_DLL_INFO PcDllInfo; DWORD dwGuidIdx; WCHAR wszLocalLang[8]; PPERF_OBJECT_TYPE pThisObject; PPERF_COUNTER_DEFINITION pThisCounterDef; // get registry key for this object // 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) { hKeyMachine = NULL; } } } else { hKeyMachine = HKEY_LOCAL_MACHINE; } // bail out here if unable to open the registry if (hKeyMachine == NULL) return lStatus; // get ENGLISH string list lpCounterText = BuildNameTable ( hKeyMachine, (LPWSTR)L"009", // Use english as the language entry for WBEM &dwLastElement); if (lpCounterText == NULL) { goto MakeMofErrorExit; } // get LOCAL strings // get locale and convert to string first memset (wszLocalLang, 0, sizeof(wszLocalLang)); swprintf (wszLocalLang, (LPCWSTR)L"0%2.2x", (GetSystemDefaultLCID() & 0x000000FF)); lpDisplayText = BuildNameTable ( hKeyMachine, (LPWSTR)wszLocalLang, // Use local language for strings &dwLastElement); if (lpDisplayText == NULL) { lpDisplayText = BuildNameTable ( hKeyMachine, (LPWSTR)L"009", // then Use english &dwLastElement); if (lpDisplayText == NULL) { goto MakeMofErrorExit; } } // open key to driver's performance key __try { lStatus = RegOpenKeyEx ( hKeyMachine, lpDriverKeyPath, RESERVED, KEY_WRITE | KEY_READ, & hDriverPerf); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_UNABLE_OPEN_KEY, // event, 2, lStatus, __LINE__, 0, 0, 1, (LPWSTR) lpDriverKeyPath, NULL, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_OPENCOUNTERANDBUILDMOFFILE, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(lpDriverName), NULL)); goto MakeMofErrorExit; } // get library name dwType = 0; dwSize = sizeof(wszPerfLibraryName); __try { lStatus = RegQueryValueExW (hDriverPerf, cszLibrary, NULL, & dwType, (LPBYTE) & wszPerfLibraryName[0], & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus == ERROR_SUCCESS) { if (dwType == REG_EXPAND_SZ) { // expand any environment vars dwSize = ExpandEnvironmentStringsW( wszPerfLibraryName, wszLibraryExpPath, MAX_PATH); if ((dwSize > MAX_PATH) || (dwSize == 0)) { lStatus = ERROR_INVALID_DLL; } } else if (dwType == REG_SZ) { // look for dll and save full file Path dwSize = SearchPathW ( NULL, // use standard system search path wszPerfLibraryName, NULL, MAX_PATH, wszLibraryExpPath, NULL); if ((dwSize > MAX_PATH) || (dwSize == 0)) { lStatus = ERROR_INVALID_DLL; } } else { lStatus = ERROR_INVALID_DLL; } if (lStatus != ERROR_SUCCESS) { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_OPENCOUNTERANDBUILDMOFFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_WSTR(wszPerfLibraryName), NULL)); } } else { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_OPENCOUNTERANDBUILDMOFFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_WSTR(cszLibrary), NULL)); } // unable to continue if error if (lStatus != ERROR_SUCCESS) { goto MakeMofErrorExit; } // get open procedure name dwType = 0; dwSize = sizeof(szOpenProcName); __try { lStatus = RegQueryValueExA (hDriverPerf, caszOpen, NULL, & dwType, (LPBYTE) & szOpenProcName[0], & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } // unable to continue if error if (lStatus != ERROR_SUCCESS) { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_OPENCOUNTERANDBUILDMOFFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_STR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_STR(caszOpen), NULL)); goto MakeMofErrorExit; } // get collect procedure name dwType = 0; dwSize = sizeof(szCollectProcName); __try { lStatus = RegQueryValueExA (hDriverPerf, caszCollect, NULL, & dwType, (LPBYTE) & szCollectProcName[0], & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } // unable to continue if error if (lStatus != ERROR_SUCCESS) { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_OPENCOUNTERANDBUILDMOFFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_STR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_STR(caszCollect), NULL)); goto MakeMofErrorExit; } // get close procedure name dwType = 0; dwSize = sizeof(szCloseProcName); __try { lStatus = RegQueryValueExA (hDriverPerf, caszClose, NULL, & dwType, (LPBYTE) & szCloseProcName[0], & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } // unable to continue if error if (lStatus != ERROR_SUCCESS) { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_OPENCOUNTERANDBUILDMOFFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_STR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_STR(caszClose), NULL)); goto MakeMofErrorExit; } // load perf counter library hPerfLibrary = LoadLibraryW (wszPerfLibraryName); if (hPerfLibrary == NULL) { lStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_OPENCOUNTERANDBUILDMOFFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_WSTR(wszPerfLibraryName), NULL)); goto MakeMofErrorExit; } // get open procedure pointer pOpenProc = (PM_OPEN_PROC *) GetProcAddress ( hPerfLibrary, szOpenProcName); if (pOpenProc == NULL) { lStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_OPENCOUNTERANDBUILDMOFFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_STR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_STR(szOpenProcName), NULL)); goto MakeMofErrorExit; } // get collect procedure pointer pCollectProc = (PM_COLLECT_PROC *) GetProcAddress ( hPerfLibrary, szCollectProcName); if (pCollectProc == NULL) { lStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_OPENCOUNTERANDBUILDMOFFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_STR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_STR(szCollectProcName), NULL)); goto MakeMofErrorExit; } // get close procedure pointer pCloseProc = (PM_CLOSE_PROC *) GetProcAddress ( hPerfLibrary, szCloseProcName); if (pCloseProc == NULL) { lStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_OPENCOUNTERANDBUILDMOFFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_STR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_STR(szCloseProcName), NULL)); goto MakeMofErrorExit; } // call open procedure to initialize the counter __try { lStatus = (*pOpenProc)((LPWSTR)L""); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } // unable to continue if error if (lStatus != ERROR_SUCCESS) { goto MakeMofErrorExit; } dwPerfBufferSize = 0; // call the collect function to get a buffer do { // allocate a query buffer to pass to the collect function dwPerfBufferSize += 0x8000; if (pPerfBuffer == NULL) { pPerfBuffer = (LPBYTE) MemoryAllocate (dwPerfBufferSize); } else { // if buffer is too small, resize and try again pPerfBuffer = (LPBYTE) MemoryResize (pPerfBuffer, dwPerfBufferSize); } if (pPerfBuffer == NULL) { goto MakeMofErrorExit; } dwSize = dwPerfBufferSize; dwType = 0; // count of object types pPerfBufferArg = pPerfBuffer; lStatus = (* pCollectProc) ( (LPWSTR)L"Global", &pPerfBufferArg, &dwSize, &dwType); } while (lStatus == ERROR_MORE_DATA); if (lStatus != ERROR_SUCCESS) { goto MakeMofErrorExit; } // create temporary file for writing the MOF to hMofFile = CreateFileW ( MofFilename, GENERIC_WRITE, 0, // no sharing NULL, // default security CREATE_ALWAYS, // always start fresh FILE_ATTRIBUTE_NORMAL, // nothing special NULL); // no template if (hMofFile == INVALID_HANDLE_VALUE) { // unable to create MOF file lStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_OPENCOUNTERANDBUILDMOFFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(lpDriverName), TRACE_WSTR(MofFilename), NULL)); goto MakeMofErrorExit; } lstrcpyW (szProviderName, wszPerfLibraryName); dwProviderNameSize = (sizeof(szProviderName) / sizeof(szProviderName[0])); dwMofBufferSize = (sizeof(szMofBuffer) / sizeof(szMofBuffer[0])); lStatus = GenerateMofHeader (szMofBuffer, (LPTSTR)ComputerName, &dwMofBufferSize); if (lStatus == ERROR_SUCCESS) { lStatus = WriteWideStringToAnsiFile (hMofFile, szMofBuffer, &dwMofBufferSize); } PcDllInfo.szWbemProviderName = szProviderName; PcDllInfo.szRegistryKey = (LPWSTR)lpDriverName; // for each object returned pThisObject = (PPERF_OBJECT_TYPE)pPerfBuffer; for (dwThisObject = 0; dwThisObject < dwType; dwThisObject++) { PcDllInfo.szClassGuid = (LPWSTR)L""; // look up class guid string in table passed in if (plObjectGuidTable != NULL) { dwGuidIdx = 0; while (dwGuidIdx < dwObjectGuidTableSize) { if (pThisObject->ObjectNameTitleIndex == (DWORD)plObjectGuidTable[dwGuidIdx].PerfObjectId) { PcDllInfo.szClassGuid = plObjectGuidTable[dwGuidIdx].GuidString; break; } dwGuidIdx++; } } if (PcDllInfo.szClassGuid[0] == 0) { // try the standard list PcDllInfo.szClassGuid = (LPWSTR)GetPerfObjectGuid (pThisObject->ObjectNameTitleIndex); } else { // just leave it blank } // create WBEM Class object for this perf object dwMofBufferSize = (sizeof(szMofBuffer) / sizeof(szMofBuffer[0])); lStatus = GenerateMofObject (szMofBuffer, &dwMofBufferSize, &PcDllInfo, pThisObject, lpCounterText, lpDisplayText, WM_GMO_RAW_DEFINITION); if (lStatus == ERROR_SUCCESS) { if (lStatus == ERROR_SUCCESS) { lStatus = WriteWideStringToAnsiFile ( hMofFile, szMofBuffer, &dwMofBufferSize); } // for each counter defined in this object pThisCounterDef = FirstCounter (pThisObject); for (dwThisCounterDef = 0; dwThisCounterDef < pThisObject->NumCounters; dwThisCounterDef++) { // define a WBEM property dwMofBufferSize = (sizeof(szMofBuffer) / sizeof(szMofBuffer[0])); lStatus = GenerateMofCounter (szMofBuffer, &dwMofBufferSize, pThisCounterDef, lpCounterText,lpDisplayText, WM_GMO_RAW_DEFINITION); if (lStatus == ERROR_SUCCESS) { lStatus = WriteWideStringToAnsiFile ( hMofFile, szMofBuffer, &dwMofBufferSize); } pThisCounterDef = NextCounter (pThisCounterDef); } dwMofBufferSize = (sizeof(szMofBuffer) / sizeof(szMofBuffer[0])); lStatus = GenerateMofObjectTail (szMofBuffer, &dwMofBufferSize); if (lStatus == ERROR_SUCCESS) { lStatus = WriteWideStringToAnsiFile ( hMofFile, szMofBuffer, &dwMofBufferSize); } } // end for each object pThisObject = NextObject (pThisObject); } // write end of file SetEndOfFile(hMofFile); CloseHandle(hMofFile); // call close proc lStatus = (* pCloseProc)(); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_OPENCOUNTERANDBUILDMOFFILE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2) | ARG_DEF(ARG_TYPE_WSTR, 3) | ARG_DEF(ARG_TYPE_STR, 4) | ARG_DEF(ARG_TYPE_STR, 5) | ARG_DEF(ARG_TYPE_STR, 6), lStatus, TRACE_WSTR(lpDriverName), TRACE_WSTR(MofFilename), TRACE_WSTR(wszPerfLibraryName), TRACE_STR(szOpenProcName), TRACE_STR(szCollectProcName), TRACE_STR(szCloseProcName), NULL)); MakeMofErrorExit: // close the registry key if necessary if ((hKeyMachine != HKEY_LOCAL_MACHINE) && (hKeyMachine != NULL)) { RegCloseKey (hKeyMachine); } if (hDriverPerf != NULL) RegCloseKey (hDriverPerf); if (lpCounterText == NULL) MemoryFree (lpCounterText); if (lpDisplayText == NULL) MemoryFree (lpDisplayText); // MemoryFree perf counter library if (hPerfLibrary != NULL) FreeLibrary (hPerfLibrary); // MemoryFree the collection buffer if (pPerfBuffer != NULL) MemoryFree (pPerfBuffer); // return return (DWORD)lStatus; } LOADPERF_FUNCTION InstallPerfDllW ( IN LPCWSTR szComputerName, IN LPCWSTR lpIniFile, IN ULONG_PTR dwFlags ) { LPWSTR lpDriverName = NULL; WCHAR MofFilename[MAX_PATH]; PERFOBJECT_LOOKUP plObjectGuidTable[16]; DWORD dwObjectGuidTableSize; DWORD dwObjectIndex; LANGUAGE_LIST_ELEMENT LangList; PSYMBOL_TABLE_ENTRY SymbolTable = NULL; DWORD ErrorCode = ERROR_SUCCESS; DWORD dwIndexValues[4] = {0,0,0,0}; HKEY hKeyMachine = HKEY_LOCAL_MACHINE; HKEY hKeyDriver = NULL; WinPerfStartTrace(NULL); bQuietMode = (BOOL)((dwFlags & LOADPERF_FLAGS_DISPLAY_USER_MSGS) == 0); // initialize the object GUID table memset (plObjectGuidTable, 0, sizeof (plObjectGuidTable)); dwObjectGuidTableSize = sizeof (plObjectGuidTable) / sizeof (plObjectGuidTable[0]) ; if (szComputerName == NULL) { ComputerName[0] = 0; // use the local computer } else { if (lstrlenW(szComputerName) < FILE_NAME_BUFFER_SIZE) { lstrcpyW (ComputerName, szComputerName); } else { ErrorCode = ERROR_INVALID_PARAMETER; } } if ((lpIniFile != NULL) && (ErrorCode == ERROR_SUCCESS)) { lpDriverName = MemoryAllocate (MAX_PATH * sizeof (WCHAR)); if (lpDriverName == NULL) { ErrorCode = ERROR_OUTOFMEMORY; goto EndOfMain; } // valid filename (i.e. file exists) // get device driver name if (!GetDriverName ((LPWSTR)lpIniFile, &lpDriverName)) { OUTPUT_MESSAGE (GetFormatResource(LC_DEVNAME_ERR_1), lpIniFile); OUTPUT_MESSAGE (GetFormatResource(LC_DEVNAME_ERR_2)); ErrorCode = GetLastError(); MemoryFree(lpDriverName); lpDriverName = NULL; goto EndOfMain; } hKeyMachine = HKEY_LOCAL_MACHINE; if (ComputerName[0]) { ErrorCode = RegConnectRegistry ( (LPTSTR) ComputerName, HKEY_LOCAL_MACHINE, & hKeyMachine); if (ErrorCode != ERROR_SUCCESS) { hKeyMachine = HKEY_LOCAL_MACHINE; } } RtlZeroMemory(szServiceDisplayName, MAX_PATH * sizeof(TCHAR)); RtlZeroMemory(szServiceName, MAX_PATH * sizeof(TCHAR)); lstrcpy(szServiceName, DriverPathRoot); lstrcat(szServiceName, Slash); lstrcat(szServiceName, lpDriverName); ErrorCode = RegOpenKeyEx(hKeyMachine, szServiceName, RESERVED, KEY_READ | KEY_WRITE, & hKeyDriver); if (ErrorCode == ERROR_SUCCESS) { DWORD dwType = 0; DWORD dwBufferSize = MAX_PATH * sizeof(TCHAR); __try { ErrorCode = RegQueryValueEx(hKeyDriver, szDisplayName, RESERVED, & dwType, (LPBYTE) szServiceDisplayName, & dwBufferSize); } __except (EXCEPTION_EXECUTE_HANDLER) { ErrorCode = GetExceptionCode(); } } if (ErrorCode != ERROR_SUCCESS) { lstrcpy(szServiceDisplayName, lpDriverName); } if (hKeyDriver != NULL) { RegCloseKey(hKeyDriver); } if (hKeyMachine != NULL && hKeyMachine != HKEY_LOCAL_MACHINE) { RegCloseKey(hKeyMachine); } ErrorCode = ERROR_SUCCESS; if (!BuildLanguageTables((LPWSTR)lpIniFile, &LangList)) { OUTPUT_MESSAGE (GetFormatResource(LC_LANGLIST_ERR), lpIniFile); ErrorCode = GetLastError(); goto EndOfMain; } if (!LoadIncludeFile((LPWSTR)lpIniFile, &SymbolTable)) { // open errors displayed in routine ErrorCode = GetLastError(); goto EndOfMain; } if (!UpdateRegistry((LPWSTR) lpIniFile, lpDriverName, & LangList, SymbolTable, plObjectGuidTable, & dwObjectGuidTableSize, (LPDWORD) & dwIndexValues)) { ErrorCode = GetLastError(); goto EndOfMain; } if (ComputerName[0] == 0) { // until remote is supported LodctrSetSericeAsTrusted( lpIniFile, NULL, lpDriverName); } // now it's time to load the MOF for WBEM access if (!(dwFlags & LOADPERF_FLAGS_LOAD_REGISTRY_ONLY)) { // the didn't say not to, so create if necessary and // load the MOF into the CIMOM // see if there's a mof file in the Ini file (if so, use that) ErrorCode = GetMofFileFromIni (lpIniFile, MofFilename); if (ErrorCode == ERROR_FILE_NOT_FOUND) { WCHAR wszTempFilename[MAX_PATH]; MakeTempFileName (lpDriverName, wszTempFilename); // otherwise we'll try to make one ErrorCode = OpenCounterAndBuildMofFile ( lpDriverName, wszTempFilename, plObjectGuidTable, dwObjectGuidTableSize); if (ErrorCode == ERROR_SUCCESS) { lstrcpyW (MofFilename, wszTempFilename); } else { // report unable to create mof file ReportLoadPerfEvent( EVENTLOG_WARNING_TYPE, // error type (DWORD) LDPRFMSG_NO_MOF_FILE_CREATED, // event, 2, ErrorCode, __LINE__, 0, 0, 2, (LPWSTR) lpDriverName, wszTempFilename, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_INSTALLPERFDLL, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ErrorCode, TRACE_WSTR(lpDriverName), TRACE_WSTR(wszTempFilename), NULL)); } } // now let's load it into the CIMOM if (ErrorCode == ERROR_SUCCESS) { ErrorCode = LodctrCompileMofFile ( ComputerName, MofFilename ); if (ErrorCode != ERROR_SUCCESS) { // display error message ReportLoadPerfEvent( EVENTLOG_WARNING_TYPE, // error type (DWORD) LDPRFMSG_NO_MOF_FILE_LOADED, // event, 2, ErrorCode, __LINE__, 0, 0, 2, (LPWSTR) lpDriverName, MofFilename, NULL); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_INSTALLPERFDLL, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ErrorCode, TRACE_WSTR(lpDriverName), TRACE_WSTR(MofFilename), NULL)); } } // toss the mof if they don't want it if ((ErrorCode == ERROR_SUCCESS) && (dwFlags & LOADPERF_FLAGS_DELETE_MOF_ON_EXIT)) { // display error message ReportLoadPerfEvent( EVENTLOG_WARNING_TYPE, // error type (DWORD) LDPRFMSG_CANT_DELETE_MOF, // event, 1, __LINE__, 0, 0, 0, 1, (LPWSTR) lpDriverName, NULL, NULL); } // reset the error code to success since all worked before the // MOF operations. ErrorCode = ERROR_SUCCESS; } // signal WMI with this change, ignore WMI return error. SignalWmiWithNewData (WMI_LODCTR_EVENT); } else { if (lpIniFile == NULL) { OUTPUT_MESSAGE (GetFormatResource(LC_NO_INIFILE), lpIniFile); ErrorCode = ERROR_OPEN_FAILED; } 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 (ErrorCode != ERROR_SUCCESS) { if (ErrorCode == ERROR_ALREADY_EXISTS) { ReportLoadPerfEvent( EVENTLOG_INFORMATION_TYPE, // error type (DWORD) LDPRFMSG_ALREADY_EXIST, // event, 1, __LINE__, 0, 0, 0, 2, (LPWSTR) lpDriverName, (LPWSTR) szServiceDisplayName, NULL); ErrorCode = ERROR_SUCCESS; } else if (lpDriverName != NULL) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_LOAD_FAILURE, // event, 2, ErrorCode, __LINE__, 0, 0, 1, (LPWSTR) lpDriverName, NULL, NULL); } else if (lpIniFile != NULL) { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_LOAD_FAILURE, // event, 2, ErrorCode, __LINE__, 0, 0, 1, (LPWSTR) lpIniFile, NULL, NULL); } else { ReportLoadPerfEvent( EVENTLOG_ERROR_TYPE, // error type (DWORD) LDPRFMSG_LOAD_FAILURE, // event, 2, ErrorCode, __LINE__, 0, 0, 0, NULL, NULL, NULL); } } else { // log success message ReportLoadPerfEvent( EVENTLOG_INFORMATION_TYPE, // error type (DWORD) LDPRFMSG_LOAD_SUCCESS, // event, 1, __LINE__, 0, 0, 0, 2, (LPWSTR) lpDriverName, (LPWSTR) szServiceDisplayName, NULL); } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_INSTALLPERFDLL, ARG_DEF(ARG_TYPE_WSTR, 1), ErrorCode, TRACE_WSTR(lpDriverName), NULL)); for (dwObjectIndex = 0; dwObjectIndex < dwObjectGuidTableSize; dwObjectIndex++) { if (plObjectGuidTable[dwObjectIndex].GuidString != NULL) { MemoryFree (plObjectGuidTable[dwObjectIndex].GuidString); } } if (lpDriverName) MemoryFree (lpDriverName); return (ErrorCode); } LOADPERF_FUNCTION InstallPerfDllA ( IN LPCSTR szComputerName, IN LPCSTR szIniFile, IN ULONG_PTR dwFlags ) { LPWSTR lpWideComputerName = NULL; LPWSTR lpWideFileName = NULL; DWORD dwStrLen; DWORD lReturn; if (szIniFile != NULL) { //length of string including terminator dwStrLen = lstrlenA(szIniFile) + 1; lpWideFileName = MemoryAllocate (dwStrLen * sizeof(WCHAR)); if (lpWideFileName != NULL) { mbstowcs (lpWideFileName, szIniFile, dwStrLen); lReturn = ERROR_SUCCESS; } else { lReturn = ERROR_OUTOFMEMORY; } } else { lReturn = ERROR_INVALID_PARAMETER; } if (lReturn == ERROR_SUCCESS) { if (szComputerName != NULL) { dwStrLen = lstrlenA (szComputerName) + 1; lpWideComputerName = (LPWSTR)MemoryAllocate (dwStrLen * sizeof(WCHAR)); if (lpWideComputerName != NULL) { mbstowcs (lpWideComputerName, szComputerName, dwStrLen); lReturn = ERROR_SUCCESS; } else { lReturn = ERROR_OUTOFMEMORY; } } else { lpWideComputerName = NULL; lReturn = ERROR_SUCCESS; } } if (lReturn == ERROR_SUCCESS) { lReturn = InstallPerfDllW ( lpWideComputerName, lpWideFileName, dwFlags); MemoryFree (lpWideFileName); MemoryFree (lpWideComputerName); } return lReturn; } 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. --*/ { LPWSTR lpIniFile; DWORD ErrorCode = ERROR_SUCCESS; ULONG_PTR dwFlags = 0; WinPerfStartTrace(NULL); dwFlags |= (bQuietModeArg ? 0 : LOADPERF_FLAGS_DISPLAY_USER_MSGS); lpIniFile = MemoryAllocate (MAX_PATH * sizeof (TCHAR)); if (!lpIniFile) { return (ERROR_OUTOFMEMORY); } *lpIniFile = 0; // init last error value SetLastError (ERROR_SUCCESS); // read command line to determine what to do if (GetFileFromCommandLine (lpCommandLine, &lpIniFile, &dwFlags)) { dwFlags |= LOADPERF_FLAGS_LOAD_REGISTRY_ONLY; // don't do mof's even if they want // call installation function ErrorCode = InstallPerfDllW (ComputerName, lpIniFile, dwFlags); } else { //Incorrect Command Format // display command line usage if (!bQuietModeArg) { DisplayCommandHelp(LC_FIRST_CMD_HELP, LC_LAST_CMD_HELP); } ErrorCode = ERROR_INVALID_PARAMETER; } if (lpIniFile) MemoryFree (lpIniFile); return (ErrorCode); } LOADPERF_FUNCTION LoadPerfCounterTextStringsA ( IN LPSTR lpAnsiCommandLine, IN BOOL bQuietModeArg ) { LPWSTR lpWideCommandLine; DWORD dwStrLen; DWORD lReturn; if (lpAnsiCommandLine != NULL) { //length of string including terminator dwStrLen = lstrlenA(lpAnsiCommandLine) + 1; lpWideCommandLine = MemoryAllocate (dwStrLen * sizeof(WCHAR)); if (lpWideCommandLine != NULL) { mbstowcs (lpWideCommandLine, lpAnsiCommandLine, dwStrLen); lReturn = LoadPerfCounterTextStringsW (lpWideCommandLine, bQuietModeArg ); MemoryFree (lpWideCommandLine); } else { lReturn = GetLastError(); } } else { lReturn = ERROR_INVALID_PARAMETER; } return lReturn; } LOADPERF_FUNCTION LoadMofFromInstalledServiceW ( IN LPCWSTR szServiceName, // service to create mof for IN LPCWSTR szMofFilenameArg, // name of file to create IN ULONG_PTR dwFlags // flags ) { DWORD ErrorCode; WCHAR wszTempFilename[MAX_PATH]; WinPerfStartTrace(NULL); if (szServiceName == NULL) { ErrorCode = ERROR_INVALID_PARAMETER; } else { ZeroMemory(wszTempFilename, sizeof(WCHAR) * MAX_PATH); if (szMofFilenameArg == NULL) { MakeTempFileName (szServiceName, wszTempFilename); } else { lstrcpyW (wszTempFilename, szMofFilenameArg); } // otherwise we'll try to make one ErrorCode = OpenCounterAndBuildMofFile ( szServiceName, wszTempFilename, NULL, 0L); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_LOADMOFFROMINSTALLEDSERVICE, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ErrorCode, TRACE_WSTR(szServiceName), TRACE_WSTR(wszTempFilename), NULL)); // now let's load it into the CIMOM if (ErrorCode == ERROR_SUCCESS) { ErrorCode = SignalWmiWithNewData (WMI_LODCTR_EVENT); } else { ReportLoadPerfEvent( EVENTLOG_WARNING_TYPE, // error type (DWORD) LDPRFMSG_NO_MOF_FILE_CREATED, // event, 2, ErrorCode, __LINE__, 0, 0, 1, (LPWSTR) szServiceName, NULL, NULL); } // if everything is going well and the caller // wants to delete the file created to contain the MOF // then delete it if (ErrorCode == ERROR_SUCCESS) { if ((dwFlags & LOADPERF_FLAGS_DELETE_MOF_ON_EXIT) && (szMofFilenameArg == NULL)) { if (!DeleteFile(wszTempFilename)) { ErrorCode = GetLastError(); } } } else { ReportLoadPerfEvent( EVENTLOG_WARNING_TYPE, // error type (DWORD) LDPRFMSG_NO_MOF_FILE_LOADED, // event, 2, ErrorCode, __LINE__, 0, 0, 1, (LPWSTR) szServiceName, NULL, NULL); TRACE((WINPERF_DBG_TRACE_WARNING), (& LoadPerfGuid, __LINE__, LOADPERF_LOADMOFFROMINSTALLEDSERVICE, ARG_DEF(ARG_TYPE_WSTR, 1), ErrorCode, TRACE_WSTR(szServiceName), NULL)); } } return (ErrorCode); } LOADPERF_FUNCTION LoadMofFromInstalledServiceA ( IN LPCSTR szServiceName, // service to create mof for IN LPCSTR szMofFilenameArg, // name of file to create IN ULONG_PTR dwFlags // delete mof on exit ) { DWORD ErrorCode = ERROR_SUCCESS; LPWSTR wszServiceName; DWORD dwServiceNameLen; LPWSTR wszMofFilename; DWORD dwMofFilenameLen; if (szServiceName == NULL) { ErrorCode = ERROR_INVALID_PARAMETER; } else { dwServiceNameLen = lstrlenA(szServiceName) + 1; wszServiceName = MemoryAllocate ( dwServiceNameLen * sizeof(WCHAR)); if (wszServiceName == NULL) { ErrorCode = ERROR_OUTOFMEMORY; } else { mbstowcs (wszServiceName, szServiceName, dwServiceNameLen); if (szMofFilenameArg != NULL) { dwMofFilenameLen = lstrlenA(szMofFilenameArg) + 1; wszMofFilename = MemoryAllocate (dwMofFilenameLen); if (wszMofFilename != NULL) { mbstowcs (wszMofFilename, szMofFilenameArg, dwMofFilenameLen); } else { ErrorCode = ERROR_OUTOFMEMORY; } } else { wszMofFilename = NULL; } if (ErrorCode == ERROR_SUCCESS) { ErrorCode = LoadMofFromInstalledServiceW ( wszServiceName, wszMofFilename, dwFlags); } if (wszMofFilename != NULL) MemoryFree (wszMofFilename); MemoryFree (wszServiceName); } } return ErrorCode; } LOADPERF_FUNCTION UpdatePerfNameFilesX ( IN LPCWSTR szNewCtrFilePath, // data file with new base counter strings IN LPCWSTR szNewHlpFilePath, // data file with new base counter strings IN LPWSTR szLanguageID, // Lang ID to update IN ULONG_PTR dwFlags // flags ) { DWORD dwReturn = ERROR_SUCCESS; LPWSTR szCtrNameIn = NULL; LPWSTR szHlpNameIn = NULL; LPWSTR szNewCtrStrings = NULL; LPWSTR szNewHlpStrings = NULL; LPWSTR szNewCtrMSZ = NULL; LPWSTR szNewHlpMSZ = NULL; WCHAR szSystemPath[MAX_PATH]; DWORD dwLength; LPWSTR *pszNewNameTable = NULL; LPWSTR *pszOldNameTable = NULL; LPWSTR lpThisName; LPWSTR szThisCtrString = NULL; LPWSTR szThisHlpString = NULL; WCHAR szLangSection[MAX_PATH]; DWORD dwOldLastEntry = 0; DWORD dwNewLastEntry = 0; DWORD dwStringSize; DWORD dwHlpFileSize = 0, dwCtrFileSize = 0 ; DWORD dwThisCounter; DWORD dwSize; DWORD dwLastBaseValue = 0; DWORD dwType; DWORD dwIndex; HANDLE hCtrFileIn = INVALID_HANDLE_VALUE; HANDLE hCtrFileMap = NULL; HANDLE hHlpFileIn = INVALID_HANDLE_VALUE; HANDLE hHlpFileMap = NULL; HKEY hKeyPerflib; WinPerfStartTrace(NULL); if (szNewCtrFilePath == NULL) dwReturn = ERROR_INVALID_PARAMETER; if ((szNewHlpFilePath == NULL) && !(dwFlags & LODCTR_UPNF_RESTORE)) dwReturn = ERROR_INVALID_PARAMETER; if (szLanguageID == NULL) dwReturn = ERROR_INVALID_PARAMETER; if (dwReturn == ERROR_SUCCESS) { TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEPERFNAMEFILES, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), ERROR_SUCCESS, TRACE_WSTR(szNewCtrFilePath), TRACE_WSTR(szLanguageID), NULL)); } if ((dwReturn == ERROR_SUCCESS) && !(dwFlags & LODCTR_UPNF_RESTORE)) { // save the original files, unless it's a restoration MakeBackupCopyOfLanguageFiles (szLanguageID); dwLength = ExpandEnvironmentStringsW ((LPCWSTR)L"%windir%\\system32", (LPWSTR)szSystemPath, (sizeof(szSystemPath) / sizeof(szSystemPath[0]))); } else { dwLength = 0; SetLastError (dwReturn); } if (dwLength > 0) { // create input filenames szCtrNameIn = MemoryAllocate (MAX_PATH * 2 * sizeof (WCHAR)); szHlpNameIn = MemoryAllocate (MAX_PATH * 2 * sizeof (WCHAR)); if ((szCtrNameIn != NULL) && (szHlpNameIn != NULL)) { ExpandEnvironmentStrings (szNewCtrFilePath, szCtrNameIn, (MAX_PATH * 2)); ExpandEnvironmentStrings (szNewHlpFilePath, szHlpNameIn, (MAX_PATH * 2)); } else { dwReturn = ERROR_OUTOFMEMORY; } if (dwReturn == ERROR_SUCCESS) { // open and map new files hCtrFileIn = CreateFile ( szCtrNameIn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hCtrFileIn != INVALID_HANDLE_VALUE) { // map file dwCtrFileSize = GetFileSize(hCtrFileIn, NULL); if (dwCtrFileSize == 0xFFFFFFFF){ dwReturn =GetLastError(); } hCtrFileMap = CreateFileMapping ( hCtrFileIn, NULL, PAGE_READONLY, 0, 0, NULL); if (hCtrFileMap != NULL) { szNewCtrStrings = (LPWSTR)MapViewOfFileEx ( hCtrFileMap, FILE_MAP_READ, 0, 0, 0, NULL); if (szNewCtrStrings == NULL) { dwReturn = GetLastError(); } } else { dwReturn = GetLastError(); } } else { dwReturn = GetLastError(); } } else { dwReturn = GetLastError(); } if (dwReturn == ERROR_SUCCESS) { // open and map new files hHlpFileIn = CreateFile ( szHlpNameIn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hHlpFileIn != INVALID_HANDLE_VALUE) { // map file dwHlpFileSize = GetFileSize (hHlpFileIn, NULL); if (dwHlpFileSize == 0xFFFFFFFF){ dwReturn =GetLastError(); } hHlpFileMap = CreateFileMapping ( hHlpFileIn, NULL, PAGE_READONLY, 0, 0, NULL); if (hHlpFileMap != NULL) { szNewHlpStrings = (LPWSTR)MapViewOfFileEx ( hHlpFileMap, FILE_MAP_READ, 0, 0, 0, NULL); if (szNewHlpStrings == NULL) { dwReturn = GetLastError(); } } else { dwReturn = GetLastError(); } } else { dwReturn = GetLastError(); } } else { dwReturn = GetLastError(); } } else if (dwFlags & LODCTR_UPNF_RESTORE) { szCtrNameIn = MemoryAllocate (MAX_PATH * 2 * sizeof (WCHAR)); if (szCtrNameIn != NULL) { dwLength = ExpandEnvironmentStringsW (szNewCtrFilePath, szCtrNameIn, (sizeof(szSystemPath) / sizeof(szSystemPath[0]))); dwNewLastEntry = GetPrivateProfileIntW ( (LPCWSTR)L"Perflib", (LPCWSTR)L"Last Help", -1, szCtrNameIn); if (dwNewLastEntry != (DWORD)-1) { // get the input file size hCtrFileIn = CreateFile ( szCtrNameIn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hCtrFileIn != INVALID_HANDLE_VALUE) { // map file dwCtrFileSize = GetFileSize (hCtrFileIn, NULL); } else { dwCtrFileSize = 64 * 1024; // assign 64k if unable to read it } // load new values from ini file szNewCtrStrings = (LPWSTR)MemoryAllocate (dwCtrFileSize * sizeof(WCHAR)); if (szNewCtrStrings) { lstrcpyW (szLangSection, (LPCWSTR)L"Perfstrings_"); lstrcatW (szLangSection, szLanguageID); dwSize = GetPrivateProfileSectionW ( szLangSection, szNewCtrStrings, dwCtrFileSize, szCtrNameIn); if (dwSize == 0) { lstrcpyW (szLangSection, (LPCWSTR) L"Perfstrings_009"); dwSize = GetPrivateProfileSectionW( szLangSection, szNewCtrStrings, dwCtrFileSize, szCtrNameIn); } if (dwSize == 0) { dwReturn = ERROR_FILE_INVALID; } else { // set file sizes dwHlpFileSize = 0; dwCtrFileSize = (dwSize+2) * sizeof(WCHAR); } } else { dwReturn = ERROR_OUTOFMEMORY; } } else { // unable to open input file or file is invalid dwReturn = ERROR_FILE_INVALID; } } else { dwReturn = ERROR_OUTOFMEMORY; } } if ((dwReturn == ERROR_SUCCESS) && (!(dwFlags & LODCTR_UPNF_RESTORE))) { // build name table of current strings pszOldNameTable = BuildNameTable ( HKEY_LOCAL_MACHINE, szLanguageID, &dwOldLastEntry); if (pszOldNameTable == NULL) { dwReturn = GetLastError(); } dwNewLastEntry = (dwOldLastEntry == 0) ? (PERFLIB_BASE_INDEX) : (dwOldLastEntry); } else if (dwFlags & LODCTR_UPNF_RESTORE) { dwOldLastEntry = dwNewLastEntry; } if (dwReturn == ERROR_SUCCESS) { // build name table of new strings pszNewNameTable = (LPWSTR *)MemoryAllocate( (dwNewLastEntry + 2) * sizeof(LPWSTR)); // allow for index offset if (pszNewNameTable != NULL) { for (lpThisName = szNewCtrStrings; *lpThisName; lpThisName += (lstrlen(lpThisName)+1) ) { // first string should be an integer (in decimal unicode digits) dwThisCounter = wcstoul (lpThisName, NULL, 10); if (dwThisCounter == 0) { continue; // bad entry, try next } // point to corresponding counter name if (dwFlags & LODCTR_UPNF_RESTORE) { // point to string that follows the "=" char lpThisName = wcschr (lpThisName, L'='); if (lpThisName != NULL) { lpThisName++; } else { continue; } } else { // string is next in MSZ lpThisName += (lstrlen(lpThisName)+1); } // and load array element; pszNewNameTable[dwThisCounter] = lpThisName; } if (!(dwFlags & LODCTR_UPNF_RESTORE)) { for (lpThisName = szNewHlpStrings; *lpThisName; lpThisName += (lstrlen(lpThisName)+1) ) { // first string should be an integer (in decimal unicode digits) dwThisCounter = wcstoul (lpThisName, NULL, 10); if (dwThisCounter == 0) { continue; // bad entry, try next } // point to corresponding counter name lpThisName += (lstrlen(lpThisName)+1); // and load array element; pszNewNameTable[dwThisCounter] = lpThisName; } } // allocate string buffers for the resulting string // we want to make sure there's plenty of room so we'll make it // the size of the input file + the current buffer dwStringSize = dwHlpFileSize; dwStringSize += dwCtrFileSize; if (pszOldNameTable != NULL) { dwStringSize += MemorySize(pszOldNameTable); } szNewCtrMSZ = MemoryAllocate (dwStringSize); szNewHlpMSZ = MemoryAllocate (dwStringSize); if ((szNewCtrMSZ == NULL) || (szNewHlpMSZ == NULL)) { dwReturn = ERROR_OUTOFMEMORY; } } else { dwReturn = ERROR_OUTOFMEMORY; } } if (dwReturn == ERROR_SUCCESS) { // write new strings into registry __try { dwReturn = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, NamesKey, RESERVED, KEY_READ, & hKeyPerflib); } __except (EXCEPTION_EXECUTE_HANDLER) { dwReturn = GetExceptionCode(); } dwSize = sizeof (dwLastBaseValue); dwLastBaseValue = 0; if (dwReturn == ERROR_SUCCESS) { __try { dwReturn = RegQueryValueEx ( hKeyPerflib, szBaseIndex, RESERVED, & dwType, (LPBYTE) & dwLastBaseValue, & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { dwReturn = GetExceptionCode(); } if (dwLastBaseValue == 0) { dwReturn = ERROR_BADDB; } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEPERFNAMEFILES, ARG_DEF(ARG_TYPE_WSTR, 1), dwReturn, TRACE_WSTR(szBaseIndex), TRACE_DWORD(dwLastBaseValue), NULL)); RegCloseKey (hKeyPerflib); } } else { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEPERFNAMEFILES, ARG_DEF(ARG_TYPE_WSTR, 1), dwReturn, TRACE_WSTR(NamesKey), NULL)); } if (dwReturn == ERROR_SUCCESS) { DWORD dwLoopLimit; // the strings should be mapped by now // pszNewNameTable contains the new strings from the // source path and pszOldNameTable contains the strings // from the original system. The merge will consist of // taking all base values from the new table and the // extended values from the old table. dwIndex =1; szThisCtrString = szNewCtrMSZ; szThisHlpString = szNewHlpMSZ; // index 1 is a special case and belongs in the counter string // after that even numbers (starting w/ #2) go into the counter string // and odd numbers (starting w/ #3) go into the help string assert (pszNewNameTable[dwIndex] != NULL); szThisCtrString += swprintf (szThisCtrString, (LPCWSTR)L"%d", dwIndex) + 1; szThisCtrString += swprintf (szThisCtrString, (LPCWSTR)L"%s", pszNewNameTable[dwIndex]) + 1; dwIndex++; assert (dwIndex == 2); if (dwFlags & LODCTR_UPNF_RESTORE) { // restore ALL strings from the input file only if this // is a restoration dwLoopLimit = dwOldLastEntry; } else { // only update the system counters from the input file dwLoopLimit = dwLastBaseValue; } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEPERFNAMEFILES, 0, ERROR_SUCCESS, TRACE_DWORD(dwOldLastEntry), TRACE_DWORD(dwLastBaseValue), NULL)); for (/*dwIndex from above*/; dwIndex <= dwLoopLimit; dwIndex++) { if (pszNewNameTable[dwIndex] != NULL) { TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEPERFNAMEFILES, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_SUCCESS, TRACE_WSTR(pszNewNameTable[dwIndex]), TRACE_DWORD(dwIndex), NULL)); if (dwIndex & 0x01) { // then it's a help string szThisHlpString += swprintf (szThisHlpString, (LPCWSTR)L"%d", dwIndex) + 1; szThisHlpString += swprintf (szThisHlpString, (LPCWSTR)L"%s", pszNewNameTable[dwIndex]) + 1; } else { // it's a counter string szThisCtrString += swprintf (szThisCtrString, (LPCWSTR)L"%d", dwIndex) + 1; szThisCtrString += swprintf (szThisCtrString, (LPCWSTR)L"%s", pszNewNameTable[dwIndex]) + 1; } } // else just skip it } for (/*dwIndex from last run */;dwIndex <= dwOldLastEntry; dwIndex++) { if (pszOldNameTable[dwIndex] != NULL) { TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEPERFNAMEFILES, ARG_DEF(ARG_TYPE_WSTR, 1), ERROR_SUCCESS, TRACE_WSTR(pszOldNameTable[dwIndex]), TRACE_DWORD(dwIndex), NULL)); if (dwIndex & 0x01) { // then it's a help string szThisHlpString += swprintf (szThisHlpString, (LPCWSTR)L"%d", dwIndex) + 1; szThisHlpString += swprintf (szThisHlpString, (LPCWSTR)L"%s", pszOldNameTable[dwIndex]) + 1; } else { // it's a counter string szThisCtrString += swprintf (szThisCtrString, (LPCWSTR)L"%d", dwIndex) + 1; szThisCtrString += swprintf (szThisCtrString, (LPCWSTR)L"%s", pszOldNameTable[dwIndex]) + 1; } } // else just skip it } // terminate the MSZ *szThisCtrString++ = 0; *szThisHlpString++ = 0; } // close mapped memory sections: if (szNewCtrStrings != NULL) UnmapViewOfFile(szNewCtrStrings); if (hCtrFileMap != NULL) CloseHandle(hCtrFileMap); if (hCtrFileIn != NULL) CloseHandle(hCtrFileIn); if (szNewHlpStrings != NULL) UnmapViewOfFile(szNewHlpStrings); if (hHlpFileMap != NULL) CloseHandle(hHlpFileMap); if (hHlpFileIn != NULL) CloseHandle(hHlpFileIn); if (dwReturn == ERROR_SUCCESS) { // write new values to registry LONG lStatus; WCHAR AddCounterNameBuffer[20]; WCHAR AddHelpNameBuffer[20]; lstrcpyW(AddCounterNameBuffer, AddCounterNameStr); lstrcatW(AddCounterNameBuffer, szLanguageID); lstrcpyW(AddHelpNameBuffer, AddHelpNameStr); lstrcatW(AddHelpNameBuffer, szLanguageID); // because these are perf counter strings, RegQueryValueEx // is used instead of RegSetValueEx as one might expect. dwSize = (DWORD)((DWORD_PTR)szThisCtrString - (DWORD_PTR)szNewCtrMSZ); __try { lStatus = RegQueryValueExW ( HKEY_PERFORMANCE_DATA, AddCounterNameBuffer, RESERVED, & dwType, (LPVOID) szNewCtrMSZ, & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { dwReturn = (DWORD)lStatus; TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEPERFNAMEFILES, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(AddCounterNameBuffer), TRACE_DWORD(dwSize), NULL)); } dwSize = (DWORD)((DWORD_PTR)szThisHlpString - (DWORD_PTR)szNewHlpMSZ); __try { lStatus = RegQueryValueExW ( HKEY_PERFORMANCE_DATA, AddHelpNameBuffer, RESERVED, & dwType, (LPVOID) szNewHlpMSZ, & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = GetExceptionCode(); } if (lStatus != ERROR_SUCCESS) { dwReturn = (DWORD)lStatus; TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_UPDATEPERFNAMEFILES, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(AddHelpNameBuffer), TRACE_DWORD(dwSize), NULL)); } } if (szCtrNameIn != NULL) MemoryFree (szCtrNameIn); if (szHlpNameIn != NULL) MemoryFree (szHlpNameIn); if (pszNewNameTable != NULL) MemoryFree (pszNewNameTable); if (pszOldNameTable != NULL) MemoryFree (pszOldNameTable); if (szNewCtrMSZ != NULL) MemoryFree (szNewCtrMSZ); if (szNewHlpMSZ != NULL) MemoryFree (szNewHlpMSZ); return dwReturn; } // exported version of the above function LOADPERF_FUNCTION UpdatePerfNameFilesW ( IN LPCWSTR szNewCtrFilePath, // data file with new base counter strings IN LPCWSTR szNewHlpFilePath, // data file with new base counter strings IN LPWSTR szLanguageID, // Lang ID to update IN ULONG_PTR dwFlags // flags ) { volatile DWORD dwStatus; dwStatus = UpdatePerfNameFilesX ( szNewCtrFilePath, // data file with new base counter strings szNewHlpFilePath, // data file with new base counter strings szLanguageID, // Lang ID to update dwFlags); // flags return dwStatus; } LOADPERF_FUNCTION UpdatePerfNameFilesA ( IN LPCSTR szNewCtrFilePath, // data file with new base counter strings IN LPCSTR szNewHlpFilePath, // data file with new base counter strings IN LPSTR szLanguageID, // Lang ID to update IN ULONG_PTR dwFlags // flags ) { DWORD dwError = ERROR_SUCCESS; LPWSTR wszNewCtrFilePath = NULL; LPWSTR wszNewHlpFilePath = NULL; LPWSTR wszLanguageID = NULL; DWORD dwLength; if (szNewCtrFilePath != NULL) { dwLength = lstrlenA (szNewCtrFilePath); dwLength += 1; //add term null wszNewCtrFilePath = MemoryAllocate (dwLength * sizeof(WCHAR)); if (wszNewCtrFilePath != NULL) { mbstowcs (wszNewCtrFilePath, szNewCtrFilePath, dwLength); } } else { dwError = ERROR_INVALID_PARAMETER; } if (szNewHlpFilePath != NULL) { dwLength = lstrlenA (szNewHlpFilePath); dwLength += 1; //add term null wszNewHlpFilePath = MemoryAllocate (dwLength * sizeof(WCHAR)); if (wszNewHlpFilePath != NULL) { mbstowcs (wszNewHlpFilePath, szNewHlpFilePath, dwLength); } } else { // this parameter can only be NULL if this flag bit is set. if (!(dwFlags & LODCTR_UPNF_RESTORE)) { dwError = ERROR_INVALID_PARAMETER; } else { wszNewHlpFilePath = NULL; } } if (szLanguageID != NULL) { dwLength = lstrlenA (szLanguageID); dwLength += 1; //add term null wszLanguageID= MemoryAllocate (dwLength * sizeof(WCHAR)); if (wszLanguageID != NULL) { mbstowcs (wszLanguageID, szLanguageID, dwLength); } } else { dwError = ERROR_INVALID_PARAMETER; } if (dwError == ERROR_SUCCESS) { dwError = UpdatePerfNameFilesX ( wszNewCtrFilePath, wszNewHlpFilePath, wszLanguageID, dwFlags); } if (wszNewCtrFilePath != NULL) MemoryFree (wszNewCtrFilePath); if (wszNewHlpFilePath != NULL) MemoryFree (wszNewHlpFilePath); if (wszLanguageID != NULL) MemoryFree (wszLanguageID); return dwError; } LOADPERF_FUNCTION SetServiceAsTrustedW ( LPCWSTR szMachineName, // reserved, MBZ LPCWSTR szServiceName ) { HKEY hKeyService_Perf; DWORD dwReturn; WCHAR szPerfKeyString[MAX_PATH * 2]; HKEY hKeyLM = HKEY_LOCAL_MACHINE; // until remote machine access is supported WCHAR szLibName[MAX_PATH * 2]; WCHAR szExpLibName[MAX_PATH * 2]; WCHAR szFullPathName[MAX_PATH * 2]; DWORD dwSize, dwType; HANDLE hFile; DllValidationData dvdLibrary; LARGE_INTEGER liSize; BOOL bStatus; WinPerfStartTrace(NULL); if ((szMachineName != NULL) || (szServiceName == NULL)) { // reserved for future use return ERROR_INVALID_PARAMETER; } // build path to performance subkey lstrcpyW (szPerfKeyString, DriverPathRoot); // SYSTEM\CurrentControlSet\Services lstrcatW (szPerfKeyString, Slash); lstrcatW (szPerfKeyString, szServiceName); lstrcatW (szPerfKeyString, Slash); lstrcatW (szPerfKeyString, Performance); // open performance key under the service key __try { dwReturn = RegOpenKeyExW ( hKeyLM, szPerfKeyString, 0L, KEY_READ | KEY_WRITE, & hKeyService_Perf); } __except (EXCEPTION_EXECUTE_HANDLER) { dwReturn = GetExceptionCode(); } if (dwReturn == ERROR_SUCCESS) { // get library name dwType = 0; dwSize = sizeof(szLibName) / sizeof (szLibName[0]); __try { dwReturn = RegQueryValueExW ( hKeyService_Perf, cszLibrary, NULL, & dwType, (LPBYTE) & szLibName[0], & dwSize); } __except (EXCEPTION_EXECUTE_HANDLER) { dwReturn = GetExceptionCode(); } if (dwReturn == ERROR_SUCCESS) { // expand path name if necessary if (dwType == REG_EXPAND_SZ) { dwSize = ExpandEnvironmentStringsW ( szLibName, szExpLibName, sizeof(szExpLibName) / sizeof (szExpLibName[0])); } else { lstrcpyW (szExpLibName, szLibName); // dwSize is same as returned from Fn Call. } if (dwSize != 0) { // find DLL file dwSize = SearchPathW ( NULL, szExpLibName, NULL, sizeof(szFullPathName) / sizeof (szFullPathName[0]), szFullPathName, NULL); if (dwSize > 0) { hFile = CreateFileW ( szFullPathName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { // read file date/time & size bStatus = GetFileTime ( hFile, &dvdLibrary.CreationDate, NULL, NULL); if (bStatus) { liSize.LowPart = GetFileSize ( hFile, (DWORD *)&liSize.HighPart); dvdLibrary.FileSize = liSize.QuadPart; // set registry value __try { dwReturn = RegSetValueExW ( hKeyService_Perf, szLibraryValidationCode, 0L, REG_BINARY, (LPBYTE) & dvdLibrary, sizeof(dvdLibrary)); } __except (EXCEPTION_EXECUTE_HANDLER) { dwReturn = GetExceptionCode(); } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_SETSERVICEASTRUSTED, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2) | ARG_DEF(ARG_TYPE_WSTR, 3), dwReturn, TRACE_WSTR(szServiceName), TRACE_WSTR(szExpLibName), TRACE_WSTR(szLibraryValidationCode), NULL)); } else { dwReturn = GetLastError(); } CloseHandle (hFile); } else { dwReturn = GetLastError(); } } else { dwReturn = ERROR_FILE_NOT_FOUND; } } else { // unable to expand environment strings dwReturn = GetLastError(); } } else { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_SETSERVICEASTRUSTED, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), dwReturn, TRACE_WSTR(szServiceName), TRACE_WSTR(cszLibrary), NULL)); } // close key RegCloseKey (hKeyService_Perf); } else { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_SETSERVICEASTRUSTED, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), dwReturn, TRACE_WSTR(szServiceName), TRACE_WSTR(Performance), NULL)); } return dwReturn; } LOADPERF_FUNCTION SetServiceAsTrustedA ( LPCSTR szMachineName, // reserved, MBZ LPCSTR szServiceName ) { LPWSTR lpWideServiceName; DWORD dwStrLen; DWORD lReturn; if ((szMachineName != NULL) || (szServiceName == NULL)) { // reserved for future use return ERROR_INVALID_PARAMETER; } if (szServiceName != NULL) { //length of string including terminator dwStrLen = lstrlenA(szServiceName) + 1; lpWideServiceName = MemoryAllocate (dwStrLen * sizeof(WCHAR)); if (lpWideServiceName != NULL) { mbstowcs (lpWideServiceName, szServiceName, dwStrLen); lReturn = SetServiceAsTrustedW (NULL, lpWideServiceName); MemoryFree (lpWideServiceName); } else { lReturn = GetLastError(); } } else { lReturn = ERROR_INVALID_PARAMETER; } return lReturn; } int __cdecl My_vfwprintf( FILE *str, const wchar_t *format, va_list argptr ) { HANDLE hOut; if (str == stderr) { hOut = GetStdHandle(STD_ERROR_HANDLE); } else { hOut = GetStdHandle(STD_OUTPUT_HANDLE); } if ((GetFileType(hOut) & ~FILE_TYPE_REMOTE) == FILE_TYPE_CHAR) { DWORD cchWChar; WCHAR szBufferMessage[1024]; vswprintf( szBufferMessage, format, argptr ); cchWChar = wcslen(szBufferMessage); WriteConsoleW(hOut, szBufferMessage, cchWChar, &cchWChar, NULL); return cchWChar; } return vfwprintf(str, format, argptr); }