/*++ Copyright (c) 1991 Microsoft Corporation Module Name: common.c Abstract: Utility routines used by Lodctr and/or UnLodCtr Author: Bob Watson (a-robw) 12 Feb 93 Revision History: --*/ #define UNICODE 1 #define _UNICODE 1 // // "C" Include files // #include #include #include #include // // Windows Include files // #include #include #include #include #include #include #include #include #include #include #include "wmistr.h" #include "evntrace.h" // // local include files // #define _INIT_WINPERFP_ #include "winperfp.h" #include "ldprfmsg.h" #include "common.h" // // // Text string Constant definitions // LPCTSTR NamesKey = (LPCTSTR)TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib"); LPCTSTR DefaultLangId = (LPCTSTR)TEXT("009"); LPCTSTR DefaultLangTag = (LPCTSTR)TEXT("000"); LPCTSTR Counters = (LPCTSTR)TEXT("Counters"); LPCTSTR Help = (LPCTSTR)TEXT("Help"); LPCTSTR VersionStr = (LPCTSTR)TEXT("Version"); LPCTSTR LastHelp = (LPCTSTR)TEXT("Last Help"); LPCTSTR LastCounter = (LPCTSTR)TEXT("Last Counter"); LPCTSTR FirstHelp = (LPCTSTR)TEXT("First Help"); LPCTSTR cszFirstCounter = (LPCTSTR)TEXT("First Counter"); LPCTSTR Busy = (LPCTSTR)TEXT("Updating"); LPCTSTR Slash = (LPCTSTR)TEXT("\\"); LPCTSTR BlankString = (LPCTSTR)TEXT(" "); LPCTSTR DriverPathRoot = (LPCTSTR)TEXT("SYSTEM\\CurrentControlSet\\Services"); LPCTSTR Performance = (LPCTSTR)TEXT("Performance"); LPCTSTR CounterNameStr = (LPCTSTR)TEXT("Counter "); LPCTSTR HelpNameStr = (LPCTSTR)TEXT("Explain "); LPCTSTR AddCounterNameStr = (LPCTSTR)TEXT("Addcounter "); LPCTSTR AddHelpNameStr = (LPCTSTR)TEXT("Addexplain "); LPCTSTR szObjectList = (LPCTSTR)TEXT("Object List"); LPCTSTR szLibraryValidationCode = (LPCTSTR)TEXT("Library Validation Code"); LPCTSTR szDisplayName = (LPCTSTR) TEXT("DisplayName"); LPCTSTR szPerfIniPath = (LPCTSTR) TEXT("PerfIni"); BOOLEAN g_bCheckTraceLevel = FALSE; // Global (to this module) Buffers // static TCHAR DisplayStringBuffer[DISP_BUFF_SIZE]; static TCHAR TextFormat[DISP_BUFF_SIZE]; static HANDLE hMod = NULL; // process handle static DWORD dwLastError = ERROR_SUCCESS; HANDLE hEventLog = NULL; HANDLE hLoadPerfMutex = NULL; // // local static data // static TCHAR cDoubleQuote = TEXT('\"'); BOOL __stdcall DllEntryPoint( IN HANDLE DLLHandle, IN DWORD Reason, IN LPVOID ReservedAndUnused ) { BOOL bReturn = FALSE; ReservedAndUnused; DisableThreadLibraryCalls (DLLHandle); switch(Reason) { case DLL_PROCESS_ATTACH: setlocale(LC_ALL, ".OCP"); hMod = DLLHandle; // use DLL handle , not APP handle // register eventlog source hEventLog = RegisterEventSourceW ( NULL, (LPCWSTR)L"LoadPerf"); bReturn = TRUE; break; case DLL_PROCESS_DETACH: if (hEventLog != NULL) { if (DeregisterEventSource(hEventLog)) { hEventLog = NULL; } } if (hLoadPerfMutex != NULL) { CloseHandle(hLoadPerfMutex); hLoadPerfMutex = NULL; } bReturn = TRUE; break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: bReturn = TRUE; break; } return bReturn; } LPCTSTR GetStringResource ( UINT wStringId ) /*++ Retrived UNICODE strings from the resource file for display --*/ { if (!hMod) { hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module; } if (hMod) { if ((LoadString(hMod, wStringId, DisplayStringBuffer, DISP_BUFF_SIZE)) > 0) { return (LPTSTR)&DisplayStringBuffer[0]; } else { dwLastError = GetLastError(); return BlankString; } } else { return BlankString; } } LPCWSTR GetFormatResource ( UINT wStringId ) /*++ Returns an ANSI string for use as a format string in a printf fn. --*/ { if (!hMod) { hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module; } if (hMod) { if ((LoadStringW(hMod, wStringId, TextFormat, DISP_BUFF_SIZE)) > 0) { return (LPCTSTR)&TextFormat[0]; } else { dwLastError = GetLastError(); return BlankString; } } else { return BlankString; } } VOID DisplayCommandHelp ( UINT iFirstLine, UINT iLastLine ) /*++ DisplayCommandHelp displays usage of command line arguments Arguments NONE Return Value NONE --*/ { UINT iThisLine; WCHAR StringBuffer[DISP_BUFF_SIZE]; CHAR OemStringBuffer[DISP_BUFF_SIZE]; int nStringBufferLen; int nOemStringBufferLen; if (! hMod) { hMod = (HINSTANCE) GetModuleHandle(NULL); } if (hMod) { for (iThisLine = iFirstLine; iThisLine <= iLastLine; iThisLine++) { ZeroMemory(StringBuffer, DISP_BUFF_SIZE * sizeof(WCHAR)); ZeroMemory(OemStringBuffer, DISP_BUFF_SIZE * sizeof(CHAR)); nStringBufferLen = LoadStringW( hMod, iThisLine, StringBuffer, DISP_BUFF_SIZE); if (nStringBufferLen > 0) { nOemStringBufferLen = DISP_BUFF_SIZE; WideCharToMultiByte(CP_OEMCP, 0, StringBuffer, nStringBufferLen, OemStringBuffer, nOemStringBufferLen, NULL, NULL); fprintf (stdout, "\n%s", OemStringBuffer); } } } // else do nothing } // DisplayCommandHelp BOOL TrimSpaces ( IN OUT LPTSTR szString ) /*++ Routine Description: Trims leading and trailing spaces from szString argument, modifying the buffer passed in Arguments: IN OUT LPTSTR szString buffer to process Return Value: TRUE if string was modified FALSE if not --*/ { LPTSTR szSource; LPTSTR szDest; LPTSTR szLast; BOOL bChars; szLast = szSource = szDest = szString; bChars = FALSE; while (*szSource != 0) { // skip leading non-space chars if (!_istspace(*szSource)) { szLast = szDest; bChars = TRUE; } if (bChars) { // remember last non-space character // copy source to destination & increment both *szDest++ = *szSource++; } else { szSource++; } } if (bChars) { *++szLast = 0; // terminate after last non-space char } else { // string was all spaces so return an empty (0-len) string *szString = 0; } return (szLast != szSource); } BOOL IsDelimiter ( IN TCHAR cChar, IN TCHAR cDelimiter ) /*++ Routine Description: compares the characte to the delimiter. If the delimiter is a whitespace character then any whitespace char will match otherwise an exact match is required --*/ { if (_istspace(cDelimiter)) { // delimiter is whitespace so any whitespace char will do return (_istspace(cChar)); } else { // delimiter is not white space so use an exact match return (cChar == cDelimiter); } } LPCTSTR GetItemFromString ( IN LPCTSTR szEntry, IN DWORD dwItem, IN TCHAR cDelimiter ) /*++ Routine Description: returns nth item from a list delimited by the cDelimiter Char. Leaves (double)quoted strings intact. Arguments: IN LPCTSTR szEntry Source string returned to parse IN DWORD dwItem 1-based index indicating which item to return. (i.e. 1= first item in list, 2= second, etc.) IN TCHAR cDelimiter character used to separate items. Note if cDelimiter is WhiteSpace (e.g. a tab or a space) then any white space will serve as a delim. Return Value: pointer to buffer containing desired entry in string. Note, this routine may only be called 4 times before the string buffer is re-used. (i.e. don't use this function more than 4 times in single function call!!) --*/ { static TCHAR szReturnBuffer[4][MAX_PATH]; static LONG dwBuff; LPTSTR szSource, szDest; DWORD dwThisItem; DWORD dwStrLeft; dwBuff = ++dwBuff % 4; // wrap buffer index szSource = (LPTSTR)szEntry; szDest = &szReturnBuffer[dwBuff][0]; // clear previous contents memset (szDest, 0, (MAX_PATH * sizeof(TCHAR))); // find desired entry in string dwThisItem = 1; while (dwThisItem < dwItem) { if (*szSource != 0) { while (!IsDelimiter(*szSource, cDelimiter) && (*szSource != 0)) { if (*szSource == cDoubleQuote) { // if this is a quote, then go to the close quote szSource++; while ((*szSource != cDoubleQuote) && (*szSource != 0)) szSource++; } if (*szSource != 0) szSource++; } } dwThisItem++; if (*szSource != 0) szSource++; } // copy this entry to the return buffer if (*szSource != 0) { dwStrLeft = MAX_PATH-1; while (!IsDelimiter(*szSource, cDelimiter) && (*szSource != 0)) { if (*szSource == cDoubleQuote) { // if this is a quote, then go to the close quote // don't copy quotes! szSource++; while ((*szSource != cDoubleQuote) && (*szSource != 0)) { *szDest++ = *szSource++; dwStrLeft--; if (!dwStrLeft) break; // dest is full (except for term NULL } if (*szSource != 0) szSource++; } else { *szDest++ = *szSource++; dwStrLeft--; if (!dwStrLeft) break; // dest is full (except for term NULL } } *szDest = 0; } // remove any leading and/or trailing spaces TrimSpaces (&szReturnBuffer[dwBuff][0]); return &szReturnBuffer[dwBuff][0]; } void ReportLoadPerfEvent( IN WORD EventType, IN DWORD EventID, IN DWORD dwDataCount, IN DWORD dwData1, IN DWORD dwData2, IN DWORD dwData3, IN DWORD dwData4, IN WORD wStringCount, IN LPWSTR szString1, IN LPWSTR szString2, IN LPWSTR szString3 ) { DWORD dwData[5]; LPWSTR szMessageArray[4]; BOOL bResult = FALSE; WORD wLocalStringCount = 0; DWORD dwLastError = GetLastError(); if (dwDataCount > 4) dwDataCount = 4; if (wStringCount > 3) wStringCount = 3; if (dwDataCount > 0) dwData[0] = dwData1; if (dwDataCount > 1) dwData[1] = dwData2; if (dwDataCount > 2) dwData[2] = dwData3; if (dwDataCount > 3) dwData[3] = dwData4; dwDataCount *= sizeof(DWORD); if (wStringCount > 0 && szString1) { szMessageArray[wLocalStringCount] = szString1; wLocalStringCount ++; } if (wStringCount > 1 && szString2) { szMessageArray[wLocalStringCount] = szString2; wLocalStringCount ++; } if (wStringCount > 2 && szString3) { szMessageArray[wLocalStringCount] = szString3; wLocalStringCount ++; } if (hEventLog == NULL) { hEventLog = RegisterEventSourceW (NULL, (LPCWSTR)L"LoadPerf"); } if (dwDataCount > 0 && wLocalStringCount > 0) { bResult = ReportEventW(hEventLog, EventType, // event type 0, // category (not used) EventID, // event, NULL, // SID (not used), wLocalStringCount, // number of strings dwDataCount, // sizeof raw data szMessageArray, // message text array (LPVOID) & dwData[0]); // raw data } else if (dwDataCount > 0) { bResult = ReportEventW(hEventLog, EventType, // event type 0, // category (not used) EventID, // event, NULL, // SID (not used), 0, // number of strings dwDataCount, // sizeof raw data NULL, // message text array (LPVOID) & dwData[0]); // raw data } else if (wLocalStringCount > 0) { bResult = ReportEventW(hEventLog, EventType, // event type 0, // category (not used) EventID, // event, NULL, // SID (not used), wLocalStringCount, // number of strings 0, // sizeof raw data szMessageArray, // message text array NULL); // raw data } else { bResult = ReportEventW(hEventLog, EventType, // event type 0, // category (not used) EventID, // event, NULL, // SID (not used), 0, // number of strings 0, // sizeof raw data NULL, // message text array NULL); // raw data } if (! bResult) { DbgPrint("LOADPERF(0x%08X)::(%d,0x%08X,%d)(%d,%d,%d,%d,%d)(%d,%ws,%ws,%ws)\n", GetCurrentThreadId(), EventType, EventID, GetLastError(), dwDataCount, dwData1, dwData2, dwData3, dwData4, wStringCount, szString1, szString2, szString3); } SetLastError(dwLastError); } BOOLEAN LoadPerfGrabMutex() { BOOL bResult = TRUE; HANDLE hLocalMutex = NULL; DWORD dwWaitStatus = 0; SECURITY_ATTRIBUTES SecurityAttributes; PSECURITY_DESCRIPTOR pSD = NULL; EXPLICIT_ACCESS ea[3]; SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY; SID_IDENTIFIER_AUTHORITY authWorld = SECURITY_WORLD_SID_AUTHORITY; PSID psidSystem = NULL; PSID psidAdmin = NULL; PSID psidEveryone = NULL; PACL pAcl = NULL; if (hLoadPerfMutex == NULL) { ZeroMemory(& ea, 3 * sizeof(EXPLICIT_ACCESS)); // Get the system sid // bResult = AllocateAndInitializeSid(& authNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, & psidSystem); if (! bResult) { dwWaitStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LOADPERFGRABMUTEX, 0, dwWaitStatus, NULL)); goto Cleanup; } // Set the access rights for system sid // ea[0].grfAccessPermissions = MUTEX_ALL_ACCESS; ea[0].grfAccessMode = SET_ACCESS; ea[0].grfInheritance = NO_INHERITANCE; ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ea[0].Trustee.ptstrName = (LPTSTR) psidSystem; // Get the Admin sid // bResult = AllocateAndInitializeSid(& authNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, & psidAdmin); if (! bResult) { dwWaitStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LOADPERFGRABMUTEX, 0, dwWaitStatus, NULL)); goto Cleanup; } // Set the access rights for Admin sid // ea[1].grfAccessPermissions = MUTEX_ALL_ACCESS; ea[1].grfAccessMode = SET_ACCESS; ea[1].grfInheritance = NO_INHERITANCE; ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; ea[1].Trustee.ptstrName = (LPTSTR) psidAdmin; // Get the World sid // bResult = AllocateAndInitializeSid(& authWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, & psidEveryone); if (! bResult) { dwWaitStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LOADPERFGRABMUTEX, 0, dwWaitStatus, NULL)); goto Cleanup; } // Set the access rights for world // ea[2].grfAccessPermissions = READ_CONTROL | SYNCHRONIZE | MUTEX_MODIFY_STATE; ea[2].grfAccessMode = SET_ACCESS; ea[2].grfInheritance = NO_INHERITANCE; ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[2].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ea[2].Trustee.ptstrName = (LPTSTR) psidEveryone; // Create a new ACL that contains the new ACEs. // dwWaitStatus = SetEntriesInAcl(3, ea, NULL, & pAcl); if (dwWaitStatus != ERROR_SUCCESS) { bResult = FALSE; TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LOADPERFGRABMUTEX, 0, dwWaitStatus, NULL)); goto Cleanup; } // Initialize a security descriptor. // pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (pSD == NULL) { dwWaitStatus = GetLastError(); bResult = FALSE; TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LOADPERFGRABMUTEX, 0, dwWaitStatus, NULL)); goto Cleanup; } bResult = InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); if (! bResult) { dwWaitStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LOADPERFGRABMUTEX, 0, dwWaitStatus, NULL)); goto Cleanup; } // Add the ACL to the security descriptor. // bResult = SetSecurityDescriptorDacl(pSD, TRUE, pAcl, FALSE); if (! bResult) { dwWaitStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LOADPERFGRABMUTEX, 0, dwWaitStatus, NULL)); goto Cleanup; } SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); SecurityAttributes.bInheritHandle = TRUE; SecurityAttributes.lpSecurityDescriptor = pSD; __try { hLocalMutex = CreateMutex(& SecurityAttributes, FALSE, TEXT("LOADPERF_MUTEX")); if (hLocalMutex == NULL) { bResult = FALSE; dwWaitStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_ERROR), (& LoadPerfGuid, __LINE__, LOADPERF_LOADPERFGRABMUTEX, 0, dwWaitStatus, NULL)); } else if (InterlockedCompareExchangePointer(& hLoadPerfMutex, hLocalMutex, NULL) != NULL) { CloseHandle(hLocalMutex); hLocalMutex = NULL; } } __except (EXCEPTION_EXECUTE_HANDLER) { bResult = FALSE; dwWaitStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_FATAL), (& LoadPerfGuid, __LINE__, LOADPERF_LOADPERFGRABMUTEX, 0, dwWaitStatus, NULL)); } } __try { dwWaitStatus = WaitForSingleObject(hLoadPerfMutex, H_MUTEX_TIMEOUT); } __except (EXCEPTION_EXECUTE_HANDLER) { bResult = FALSE; dwWaitStatus = GetLastError(); TRACE((WINPERF_DBG_TRACE_FATAL), (& LoadPerfGuid, __LINE__, LOADPERF_LOADPERFGRABMUTEX, 0, dwWaitStatus, NULL)); } if (dwWaitStatus != WAIT_OBJECT_0 && dwWaitStatus != WAIT_ABANDONED) { bResult = FALSE; TRACE((WINPERF_DBG_TRACE_FATAL), (& LoadPerfGuid, __LINE__, LOADPERF_LOADPERFGRABMUTEX, 0, dwWaitStatus, NULL)); } Cleanup: if (psidSystem) FreeSid(psidSystem); if (psidAdmin) FreeSid(psidAdmin); if (psidEveryone) FreeSid(psidEveryone); if (pAcl) LocalFree(pAcl); if (pSD) LocalFree(pSD); if (! bResult) SetLastError(dwWaitStatus); return bResult ? TRUE : FALSE; }