/*++ Copyright (c) 1991-1999 Microsoft Corporation Module Name: dumpload.c Abstract: functions to dump and load the contents of the performance related registry entries Author: Bob Watson (bobw) 13 Jun 99 Revision History: --*/ #ifndef UNICODE #define UNICODE 1 #endif #ifndef _UNICODE #define _UNICODE 1 #endif // // "C" Include files // #include #include #include #include // // Windows Include files // #include #include #include #include "wmistr.h" #include "evntrace.h" // // application include files // #include "winperfp.h" #include "common.h" #include "ldprfmsg.h" static const WCHAR cszServiceKeyName[] = {L"SYSTEM\\CurrentControlSet\\Services"}; static const WCHAR cszPerflibKeyName[] = {L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib"}; static const WCHAR cszLastCounter[] = {L"Last Counter"}; static const WCHAR cszFirstHelp[] = {L"First Help"}; static const WCHAR cszLastHelp[] = {L"Last Help"}; static const WCHAR cszBaseIndex[] = {L"Base Index"}; static const WCHAR cszPerformance[] = {L"\\Performance"}; static const WCHAR cszDisablePerformanceCounters[] = {L"Disable Performance Counters"}; // headings in save file static const WCHAR cszFmtSectionHeader[] = {L"\r\n\r\n[%s]"}; static const WCHAR cszFmtServiceSectionHeader[] = {L"\r\n\r\n[PERF_%s]"}; static const WCHAR cszFmtServiceSectionName[] = {L"PERF_%s"}; static const WCHAR cszFmtStringSectionHeader[] = {L"\r\n\r\n[PerfStrings_%s]"}; static const WCHAR cszFmtExtCtrString[] = {L"\r\n%d=%s"}; static const WCHAR cszFmtDecimalParam[] = {L"\r\n%s=%d"}; static const WCHAR cszFmtNoParam[] = {L"\r\n%s="}; static const WCHAR cszExtensiblePerfStrings[] = {L"Strings"}; static const WCHAR cszPerfCounterServices[] = {L"PerfCounterServices"}; static const WCHAR cszNoPerfCounterServices[] = {L"NoPerfCounterServices"}; static const WCHAR cszPerflib[] = {L"Perflib"}; // external forward definitions 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 ); DWORD 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 static DumpNameTable ( IN HANDLE hOutputFile, IN LPCWSTR szLangId, IN LPCWSTR *pszNameTable, IN DWORD dwStartIndex, IN DWORD dwLastIndex ) { DWORD ndx; WCHAR szOutputBuffer[4096]; DWORD dwSize, dwSizeWritten; dwSize = swprintf (szOutputBuffer, cszFmtStringSectionHeader, szLangId); dwSize *= sizeof (WCHAR); WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL); for (ndx = dwStartIndex; ndx <= dwLastIndex; ndx++) { if (pszNameTable[ndx] != NULL) { dwSize = swprintf (szOutputBuffer, cszFmtExtCtrString, ndx, pszNameTable[ndx] ); dwSize *= sizeof (WCHAR); WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL); } } return ERROR_SUCCESS; } DWORD static DumpPerfServiceEntries ( IN HANDLE hOutputFile, IN LPCWSTR szServiceName ) { LONG lStatus = ERROR_SUCCESS; WCHAR szPerfSubKeyName[MAX_PATH+20]; HKEY hKeyPerformance; HKEY hKeyServices = NULL; DWORD dwItemSize, dwType, dwValue; DWORD dwRegAccessMask; DWORD dwRetStatus = ERROR_SUCCESS; DWORD dwSize, dwSizeWritten; WCHAR szOutputBuffer[4096]; // try read-only then dwRegAccessMask = KEY_READ; lStatus = RegOpenKeyExW (HKEY_LOCAL_MACHINE, cszServiceKeyName, 0L, dwRegAccessMask, &hKeyServices); if (lStatus == ERROR_SUCCESS) { //try to open the perfkey under this key. lstrcpy (szPerfSubKeyName, szServiceName); lstrcat (szPerfSubKeyName, cszPerformance); lStatus = RegOpenKeyExW ( hKeyServices, szPerfSubKeyName, 0L, dwRegAccessMask, &hKeyPerformance); if (lStatus == ERROR_SUCCESS) { // key found so service has perf data dwSize = swprintf (szOutputBuffer, cszFmtServiceSectionHeader, szServiceName); dwSize *= sizeof (WCHAR); WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL); // now check to see if the strings have been loaded dwType = dwValue = 0; dwItemSize = sizeof (dwValue); lStatus = RegQueryValueExW ( hKeyPerformance, cszFirstCounter, NULL, &dwType, (LPBYTE)&dwValue, &dwItemSize); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_DUMPPERFSERVICEENTRIES, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szServiceName), TRACE_WSTR(cszFirstCounter), TRACE_DWORD(dwValue), NULL)); if ((lStatus == ERROR_SUCCESS) && ((dwType == REG_DWORD) || dwType == REG_BINARY)) { dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszFirstCounter, dwValue); dwSize *= sizeof (WCHAR); WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL); } dwType = dwValue = 0; dwItemSize = sizeof (dwValue); lStatus = RegQueryValueExW ( hKeyPerformance, cszFirstHelp, NULL, &dwType, (LPBYTE)&dwValue, &dwItemSize); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_DUMPPERFSERVICEENTRIES, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szServiceName), TRACE_WSTR(cszFirstHelp), TRACE_DWORD(dwValue), NULL)); if ((lStatus == ERROR_SUCCESS) && ((dwType == REG_DWORD) || dwType == REG_BINARY)) { dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszFirstHelp, dwValue); dwSize *= sizeof (WCHAR); WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL); } dwType = dwValue = 0; dwItemSize = sizeof (dwValue); lStatus = RegQueryValueExW ( hKeyPerformance, cszLastCounter, NULL, &dwType, (LPBYTE)&dwValue, &dwItemSize); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_DUMPPERFSERVICEENTRIES, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szServiceName), TRACE_WSTR(cszLastCounter), TRACE_DWORD(dwValue), NULL)); if ((lStatus == ERROR_SUCCESS) && ((dwType == REG_DWORD) || dwType == REG_BINARY)) { dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszLastCounter, dwValue); dwSize *= sizeof (WCHAR); WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL); } dwType = dwValue = 0; dwItemSize = sizeof (dwValue); lStatus = RegQueryValueExW ( hKeyPerformance, cszLastHelp, NULL, &dwType, (LPBYTE)&dwValue, &dwItemSize); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_DUMPPERFSERVICEENTRIES, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szServiceName), TRACE_WSTR(cszLastHelp), TRACE_DWORD(dwValue), NULL)); if ((lStatus == ERROR_SUCCESS) && ((dwType == REG_DWORD) || dwType == REG_BINARY)) { dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszLastHelp, dwValue); dwSize *= sizeof (WCHAR); WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL); } dwType = dwValue = 0; dwItemSize = sizeof (dwValue); lStatus = RegQueryValueExW ( hKeyPerformance, cszDisablePerformanceCounters, NULL, &dwType, (LPBYTE)&dwValue, &dwItemSize); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_DUMPPERFSERVICEENTRIES, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szServiceName), TRACE_WSTR(cszDisablePerformanceCounters), TRACE_DWORD(dwValue), NULL)); if ((lStatus == ERROR_SUCCESS) && ((dwType == REG_DWORD) || dwType == REG_BINARY)) { dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszDisablePerformanceCounters, dwValue); dwSize *= sizeof (WCHAR); WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL); } RegCloseKey (hKeyPerformance); } else { dwRetStatus = lStatus; TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_DUMPPERFSERVICEENTRIES, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(szServiceName), NULL)); } RegCloseKey (hKeyServices); } else { dwRetStatus = lStatus; TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_DUMPPERFSERVICEENTRIES, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(cszServiceKeyName), NULL)); } return dwRetStatus; } DWORD static DumpPerflibEntries ( IN HANDLE hOutputFile, IN LPDWORD pdwFirstExtCtrIndex ) { HKEY hKeyPerflib = NULL; DWORD dwStatus; DWORD dwItemSize, dwType, dwValue; DWORD dwSize, dwSizeWritten; WCHAR szOutputBuffer[4096]; dwStatus = RegOpenKeyExW (HKEY_LOCAL_MACHINE, cszPerflibKeyName, 0L, KEY_READ, &hKeyPerflib); if (dwStatus == ERROR_SUCCESS) { dwSize = swprintf (szOutputBuffer, cszFmtSectionHeader, cszPerflib); dwSize *= sizeof (WCHAR); WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL); } else { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_DUMPPERFLIBENTRIES, ARG_DEF(ARG_TYPE_WSTR, 1), dwStatus, TRACE_WSTR(cszPerflibKeyName), NULL)); } if (dwStatus == ERROR_SUCCESS) { dwType = dwValue = 0; dwItemSize = sizeof (dwValue); dwStatus = RegQueryValueEx ( hKeyPerflib, cszBaseIndex, NULL, &dwType, (LPBYTE)&dwValue, &dwItemSize); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_DUMPPERFLIBENTRIES, ARG_DEF(ARG_TYPE_WSTR, 1), dwStatus, TRACE_WSTR(cszBaseIndex), TRACE_DWORD(dwValue), NULL)); if ((dwStatus == ERROR_SUCCESS) && (dwType == REG_DWORD)) { dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszBaseIndex, dwValue); dwSize *= sizeof (WCHAR); WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL); *pdwFirstExtCtrIndex = dwValue + 1; } } if (dwStatus == ERROR_SUCCESS) { dwType = dwValue = 0; dwItemSize = sizeof (dwValue); dwStatus = RegQueryValueEx ( hKeyPerflib, cszLastCounter, NULL, &dwType, (LPBYTE)&dwValue, &dwItemSize); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_DUMPPERFLIBENTRIES, ARG_DEF(ARG_TYPE_WSTR, 1), dwStatus, TRACE_WSTR(cszLastCounter), TRACE_DWORD(dwValue), NULL)); if ((dwStatus == ERROR_SUCCESS) && (dwType == REG_DWORD)) { dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszLastCounter, dwValue); dwSize *= sizeof (WCHAR); WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL); } } if (dwStatus == ERROR_SUCCESS) { dwType = dwValue = 0; dwItemSize = sizeof (dwValue); dwStatus = RegQueryValueEx ( hKeyPerflib, cszLastHelp, NULL, &dwType, (LPBYTE)&dwValue, &dwItemSize); TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_DUMPPERFLIBENTRIES, ARG_DEF(ARG_TYPE_WSTR, 1), dwStatus, TRACE_WSTR(cszLastHelp), TRACE_DWORD(dwValue), NULL)); if ((dwStatus == ERROR_SUCCESS) && (dwType == REG_DWORD)) { dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszLastHelp, dwValue); dwSize *= sizeof (WCHAR); WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL); } } if (hKeyPerflib != NULL) RegCloseKey (hKeyPerflib); return dwStatus; } DWORD static BuildServiceLists ( IN LPWSTR mszPerfServiceList, IN LPDWORD pcchPerfServiceListSize, IN LPWSTR mszNoPerfServiceList, IN LPDWORD pcchNoPerfServiceListSize ) { LONG lStatus = ERROR_SUCCESS; LONG lEnumStatus = ERROR_SUCCESS; DWORD dwServiceIndex = 0; WCHAR szServiceSubKeyName[MAX_PATH]; WCHAR szPerfSubKeyName[MAX_PATH+20]; DWORD dwNameSize = MAX_PATH; HKEY hKeyPerformance; HKEY hKeyServices = NULL; DWORD dwItemSize, dwType, dwValue; DWORD dwRegAccessMask; DWORD bServiceHasPerfCounters; DWORD dwRetStatus = ERROR_SUCCESS; LPWSTR szNextNoPerfChar, szNextPerfChar; DWORD dwNoPerfSizeRem, dwPerfSizeRem; DWORD dwPerfSizeUsed = 0, dwNoPerfSizeUsed = 0; // try read-only then dwRegAccessMask = KEY_READ; lStatus = RegOpenKeyExW (HKEY_LOCAL_MACHINE, cszServiceKeyName, 0L, dwRegAccessMask, &hKeyServices); if (lStatus == ERROR_SUCCESS) { szNextNoPerfChar = mszNoPerfServiceList; szNextPerfChar = mszPerfServiceList; dwNoPerfSizeRem = *pcchPerfServiceListSize; dwPerfSizeRem = *pcchNoPerfServiceListSize; dwPerfSizeUsed = 0; dwNoPerfSizeUsed = 0; while ((lEnumStatus = RegEnumKeyExW ( hKeyServices, dwServiceIndex, szServiceSubKeyName, &dwNameSize, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS) { //try to open the perfkey under this key. lstrcpy (szPerfSubKeyName, szServiceSubKeyName); lstrcat (szPerfSubKeyName, cszPerformance); lStatus = RegOpenKeyExW ( hKeyServices, szPerfSubKeyName, 0L, dwRegAccessMask, &hKeyPerformance); if (lStatus == ERROR_SUCCESS) { // key found so service has perf data // now check to see if the strings have been loaded dwType = dwValue = 0; dwItemSize = sizeof (dwValue); lStatus = RegQueryValueExW ( hKeyPerformance, cszFirstCounter, NULL, &dwType, (LPBYTE)&dwValue, &dwItemSize); if ((lStatus == ERROR_SUCCESS) && ((dwType == REG_DWORD) || dwType == REG_BINARY)) { bServiceHasPerfCounters = TRUE; } else { bServiceHasPerfCounters = FALSE; } RegCloseKey (hKeyPerformance); } else { // key not found so service doesn't have perfdata bServiceHasPerfCounters = FALSE; } TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_BUILDSERVICELISTS, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(szServiceSubKeyName), TRACE_DWORD(bServiceHasPerfCounters), NULL)); if (bServiceHasPerfCounters != FALSE) { // add to the perf service list if ((dwNameSize + 1)< dwPerfSizeRem) { // add to list lstrcpyW (szNextPerfChar, szServiceSubKeyName); szNextPerfChar += dwNameSize; *szNextPerfChar = 0; szNextPerfChar++; dwPerfSizeRem -= dwNameSize + 1; } else { dwRetStatus = ERROR_MORE_DATA; } dwPerfSizeUsed += dwNameSize + 1; } else { // add to the no perf list if ((dwNameSize + 1) < dwNoPerfSizeRem) { // add to list lstrcpyW (szNextNoPerfChar, szServiceSubKeyName); szNextNoPerfChar += dwNameSize; *szNextNoPerfChar = 0; szNextNoPerfChar++; dwNoPerfSizeRem -= dwNameSize + 1; } else { dwRetStatus = ERROR_MORE_DATA; } dwNoPerfSizeUsed += dwNameSize + 1; } // reset for next loop dwServiceIndex++; dwNameSize = MAX_PATH; } // zero term the MSZ if (1 < dwPerfSizeRem) { *szNextPerfChar = 0; szNextPerfChar++; dwPerfSizeRem -= 1; } else { dwRetStatus = ERROR_MORE_DATA; } dwPerfSizeUsed += 1; // zero term the no perf list if (1 < dwNoPerfSizeRem) { // add to list *szNextNoPerfChar = 0; szNextNoPerfChar++; dwNoPerfSizeRem -= 1; } else { dwRetStatus = ERROR_MORE_DATA; } dwNoPerfSizeUsed += 1; } else { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_BUILDSERVICELISTS, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(cszServiceKeyName), NULL)); } if (hKeyServices != NULL) RegCloseKey (hKeyServices); *pcchPerfServiceListSize = dwPerfSizeUsed; *pcchNoPerfServiceListSize = dwNoPerfSizeUsed; return dwRetStatus; } DWORD BackupPerfRegistryToFileW ( IN LPCWSTR szFileName, IN LPCWSTR szCommentString ) { HANDLE hOutFile; DWORD dwStatus = ERROR_SUCCESS; LPWSTR szNewFileName = NULL; DWORD dwNewFileNameLen; DWORD dwOrigFileNameLen; DWORD dwFileNameSN; LPWSTR mszPerfServiceList = NULL; DWORD dwPerfServiceListSize = 0; LPWSTR mszNoPerfServiceList = NULL; DWORD dwNoPerfServiceListSize = 0; LPWSTR *lpCounterText = NULL; DWORD dwLastElement = 0; DWORD dwFirstExtCtrIndex = 0; LPWSTR szThisServiceName; LPWSTR szLangId = (LPWSTR)L"009"; DBG_UNREFERENCED_PARAMETER (szCommentString); WinPerfStartTrace(NULL); // open output file hOutFile = CreateFileW ( szFileName, GENERIC_WRITE, 0, // no sharing NULL, // default security CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); // if the file open failed if (hOutFile == INVALID_HANDLE_VALUE) { // see if it's because the file already exists dwStatus = GetLastError(); if (dwStatus == ERROR_FILE_EXISTS) { // then try appending a serial number to the name dwOrigFileNameLen = lstrlenW (szFileName); dwNewFileNameLen = dwOrigFileNameLen + 4; szNewFileName = HeapAlloc ( GetProcessHeap(), HEAP_ZERO_MEMORY, (dwNewFileNameLen +1) * sizeof(WCHAR)); if (szNewFileName != NULL) { lstrcpyW (szNewFileName, szFileName); for (dwFileNameSN = 1; dwFileNameSN < 1000; dwFileNameSN++) { swprintf (&szNewFileName[dwOrigFileNameLen], (LPCWSTR)L"_%3.3d", dwFileNameSN); hOutFile = CreateFileW ( szNewFileName, GENERIC_WRITE, 0, // no sharing NULL, // default security CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); // if the file open failed if (hOutFile == INVALID_HANDLE_VALUE) { dwStatus = GetLastError(); if (dwStatus != ERROR_FILE_EXISTS) { // some other error occurred so bail out break; } else { continue; // with the next try } } else { // found one not in use so continue on dwStatus = ERROR_SUCCESS; break; } } } else { dwStatus = ERROR_OUTOFMEMORY; } } } else { // file opened so continue dwStatus = ERROR_SUCCESS; } if (dwStatus == ERROR_SUCCESS) { // dump perflib key entires dwStatus = DumpPerflibEntries (hOutFile, &dwFirstExtCtrIndex); } if (dwStatus == ERROR_SUCCESS) { do { if (mszPerfServiceList != NULL) { HeapFree (GetProcessHeap(), 0, mszPerfServiceList); mszPerfServiceList = NULL; } if (mszNoPerfServiceList != NULL) { HeapFree (GetProcessHeap(), 0, mszNoPerfServiceList); mszNoPerfServiceList = NULL; } // build service lists dwPerfServiceListSize += 32768; dwNoPerfServiceListSize += 65536; mszPerfServiceList = HeapAlloc ( GetProcessHeap(), HEAP_ZERO_MEMORY, (dwPerfServiceListSize) * sizeof(WCHAR)); mszNoPerfServiceList = HeapAlloc ( GetProcessHeap(), HEAP_ZERO_MEMORY, (dwNoPerfServiceListSize) * sizeof(WCHAR)); if ((mszNoPerfServiceList == NULL) || (mszPerfServiceList == NULL)) { dwStatus = ERROR_OUTOFMEMORY; break; } if (dwStatus == ERROR_SUCCESS) { dwStatus = BuildServiceLists ( mszPerfServiceList, &dwPerfServiceListSize, mszNoPerfServiceList, &dwNoPerfServiceListSize); if (dwStatus == ERROR_SUCCESS) break; // and continue on } } while (dwPerfServiceListSize < 4194304); } // dump service entries for those services with perf counters if (dwStatus == ERROR_SUCCESS) { for (szThisServiceName = mszPerfServiceList; *szThisServiceName != 0; szThisServiceName += lstrlenW(szThisServiceName)+1) { dwStatus = DumpPerfServiceEntries ( hOutFile, szThisServiceName); if (dwStatus != ERROR_SUCCESS) break; } } // dump perf string entries if (dwStatus == ERROR_SUCCESS) { // build Name table // get ENGLISH string list lpCounterText = BuildNameTable ( HKEY_LOCAL_MACHINE, // use only local machine (LPWSTR)szLangId, &dwLastElement); if (lpCounterText != NULL) { dwStatus = DumpNameTable ( hOutFile, szLangId, lpCounterText, 0, // dump the entire table for complete restore dwLastElement ); } else { dwStatus = GetLastError(); } } // free buffers if (lpCounterText != NULL) { HeapFree (GetProcessHeap(), 0, lpCounterText); lpCounterText = NULL; } if (mszNoPerfServiceList != NULL) { HeapFree (GetProcessHeap(), 0, mszNoPerfServiceList); mszNoPerfServiceList = NULL; } if (mszPerfServiceList != NULL) { HeapFree (GetProcessHeap(), 0, mszPerfServiceList); mszPerfServiceList = NULL; } if (szNewFileName != NULL) { HeapFree (GetProcessHeap(), 0, szNewFileName); szNewFileName = NULL; } // close file handles if (hOutFile != INVALID_HANDLE_VALUE) { CloseHandle (hOutFile); } return dwStatus; } DWORD RestorePerfRegistryFromFileW ( IN LPCWSTR szFileName, IN LPCWSTR szLangId ) { LONG lStatus = ERROR_SUCCESS; LONG lEnumStatus = ERROR_SUCCESS; DWORD dwServiceIndex = 0; WCHAR szServiceSubKeyName[MAX_PATH]; WCHAR szPerfSubKeyName[MAX_PATH+20]; DWORD dwNameSize = MAX_PATH; HKEY hKeyPerformance; HKEY hKeyServices = NULL; HKEY hKeyPerflib = NULL; DWORD dwItemSize; DWORD dwRegAccessMask; DWORD dwRetStatus = ERROR_SUCCESS; UINT nValue; DWORD dwnValue; BOOL bServiceRegistryOk = TRUE; WCHAR wPerfSection[MAX_PATH * 2]; LPWSTR szLocalLangId; WinPerfStartTrace(NULL); if (szLangId == NULL) { szLocalLangId = (LPWSTR)L"009"; } else { szLocalLangId = (LPWSTR)szLangId; } lStatus = RegOpenKeyExW (HKEY_LOCAL_MACHINE, cszServiceKeyName, 0L, KEY_READ, &hKeyServices); if (lStatus == ERROR_SUCCESS) { // enum service list while ((lEnumStatus = RegEnumKeyExW ( hKeyServices, dwServiceIndex, szServiceSubKeyName, &dwNameSize, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS) { //try to open the perfkey under this key. lstrcpy (szPerfSubKeyName, szServiceSubKeyName); lstrcat (szPerfSubKeyName, cszPerformance); bServiceRegistryOk = TRUE; dwRegAccessMask = KEY_READ | KEY_WRITE; // look for a performance subkey lStatus = RegOpenKeyExW ( hKeyServices, szPerfSubKeyName, 0L, dwRegAccessMask, &hKeyPerformance); if (lStatus == ERROR_SUCCESS) { // key found so service has perf data // if performance subkey then dwItemSize = swprintf (wPerfSection, cszFmtServiceSectionName, szServiceSubKeyName); // look into the file for a perf entry for this service nValue = GetPrivateProfileIntW ( wPerfSection, cszFirstCounter, -1, szFileName); if (nValue != (UINT) -1) { // if found in file then update registry with values from file lStatus = RegSetValueExW (hKeyPerformance, cszFirstCounter, 0L, REG_DWORD, (const BYTE *) & nValue, sizeof(nValue)); dwnValue = nValue; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_RESTOREPERFREGISTRYFROMFILEW, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szServiceSubKeyName), TRACE_WSTR(cszFirstCounter), TRACE_DWORD(dwnValue), NULL)); // now read the other values } else { // there's one or more missing entries so // remove the whole entry bServiceRegistryOk = FALSE; } // look into the file for a perf entry for this service nValue = GetPrivateProfileIntW ( wPerfSection, cszFirstHelp, -1, szFileName); if (nValue != (UINT)-1) { // if found in file then update registry with values from file lStatus = RegSetValueExW (hKeyPerformance, cszFirstHelp, 0L, REG_DWORD, (const BYTE *)&nValue, sizeof(nValue)); dwnValue = nValue; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_RESTOREPERFREGISTRYFROMFILEW, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szServiceSubKeyName), TRACE_WSTR(cszFirstHelp), TRACE_DWORD(dwnValue), NULL)); // now read the other values } else { // there's one or more missing entries so // remove the whole entry bServiceRegistryOk = FALSE; } // look into the file for a perf entry for this service nValue = GetPrivateProfileIntW ( wPerfSection, cszLastCounter, -1, szFileName); if (nValue != (UINT)-1) { // if found in file then update registry with values from file lStatus = RegSetValueExW (hKeyPerformance, cszLastCounter, 0L, REG_DWORD, (const BYTE *)&nValue, sizeof(nValue)); dwnValue = nValue; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_RESTOREPERFREGISTRYFROMFILEW, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szServiceSubKeyName), TRACE_WSTR(cszLastCounter), TRACE_DWORD(dwnValue), NULL)); // now read the other values } else { // there's one or more missing entries so // remove the whole entry bServiceRegistryOk = FALSE; } // look into the file for a perf entry for this service nValue = GetPrivateProfileIntW ( wPerfSection, cszLastHelp, -1, szFileName); if (nValue != (UINT)-1) { // if found in file then update registry with values from file lStatus = RegSetValueExW (hKeyPerformance, cszLastHelp, 0L, REG_DWORD, (const BYTE *)&nValue, sizeof(nValue)); dwnValue = nValue; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_RESTOREPERFREGISTRYFROMFILEW, ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2), lStatus, TRACE_WSTR(szServiceSubKeyName), TRACE_WSTR(cszLastHelp), TRACE_DWORD(dwnValue), NULL)); // now read the other values } else { // there's one or more missing entries so // remove the whole entry bServiceRegistryOk = FALSE; } if (!bServiceRegistryOk) { // an error occurred so delete the first/last counter/help values RegDeleteValue (hKeyPerformance, cszFirstCounter); RegDeleteValue (hKeyPerformance, cszFirstHelp); RegDeleteValue (hKeyPerformance, cszLastCounter); RegDeleteValue (hKeyPerformance, cszLastHelp); } // else continiue RegCloseKey (hKeyPerformance); } // else this service has no perf data so skip else { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_RESTOREPERFREGISTRYFROMFILEW, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(szServiceSubKeyName), NULL)); } // reset for next loop dwServiceIndex++; dwNameSize = MAX_PATH; } // end enum service list } else { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_RESTOREPERFREGISTRYFROMFILEW, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(cszServiceKeyName), NULL)); } if (hKeyServices != NULL) RegCloseKey (hKeyServices); if (dwRetStatus == ERROR_SUCCESS) { // merge registry string values: dwRetStatus = UpdatePerfNameFilesX ( szFileName, NULL, szLocalLangId, LODCTR_UPNF_RESTORE); if (dwRetStatus == ERROR_SUCCESS) { // update the keys in the registry lStatus = RegOpenKeyExW (HKEY_LOCAL_MACHINE, cszPerflibKeyName, 0L, KEY_ALL_ACCESS, &hKeyPerflib); if (lStatus != ERROR_SUCCESS) { TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_RESTOREPERFREGISTRYFROMFILEW, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(cszPerflibKeyName), NULL)); } if (lStatus == ERROR_SUCCESS) { nValue = GetPrivateProfileIntW ( cszPerflib, cszLastCounter, -1, szFileName); if (nValue != (UINT)-1) { // if found in file then update registry with values from file lStatus = RegSetValueExW (hKeyPerflib, cszLastCounter, 0L, REG_DWORD, (const BYTE *)&nValue, sizeof(nValue)); dwnValue = nValue; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_RESTOREPERFREGISTRYFROMFILEW, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(cszLastCounter), TRACE_DWORD(dwnValue), NULL)); } } if (lStatus == ERROR_SUCCESS) { // look into the file for a perf entry for this service nValue = GetPrivateProfileIntW ( cszPerflib, cszLastHelp, -1, szFileName); if (nValue != (UINT)-1) { // if found in file then update registry with values from file lStatus = RegSetValueExW (hKeyPerflib, cszLastHelp, 0L, REG_DWORD, (const BYTE *)&nValue, sizeof(nValue)); dwnValue = nValue; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_RESTOREPERFREGISTRYFROMFILEW, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(cszLastHelp), TRACE_DWORD(dwnValue), NULL)); } } if (lStatus == ERROR_SUCCESS) { // look into the file for a perf entry for this service nValue = GetPrivateProfileIntW ( cszPerflib, cszBaseIndex, -1, szFileName); if (nValue != (UINT)-1) { // if found in file then update registry with values from file lStatus = RegSetValueExW (hKeyPerflib, cszBaseIndex, 0L, REG_DWORD, (const BYTE *)&nValue, sizeof(nValue)); dwnValue = nValue; TRACE((WINPERF_DBG_TRACE_INFO), (& LoadPerfGuid, __LINE__, LOADPERF_RESTOREPERFREGISTRYFROMFILEW, ARG_DEF(ARG_TYPE_WSTR, 1), lStatus, TRACE_WSTR(cszBaseIndex), TRACE_DWORD(dwnValue), NULL)); } } if (hKeyPerflib != NULL) RegCloseKey (hKeyPerflib); } dwRetStatus = lStatus; } return dwRetStatus; }