/*==========================================================================*\ Module: exprflib.cpp Copyright Microsoft Corporation 1998, All Rights Reserved. Author: WayneC Descriptions: This is the implentation for exprflib, a perf library. This is the code that runs in the app exporting the counters. \*==========================================================================*/ #include "stdlib.h" #include "snprflib.h" #include "dbgtrace.h" DWORD InitializeBasicSecurityDescriptor (PSECURITY_DESCRIPTOR *ppSd); /////////////////////////////////////////////////////////////////////////////// // // Forward declaration of shared memory functions. // /////////////////////////////////////////////////////////////////////////////// BOOL FCreateFileMapping (SharedMemorySegment * pSMS, LPCWSTR pcwstrInstanceName, DWORD dwIndex, DWORD cbSize); void CloseFileMapping (SharedMemorySegment * pSMS); /////////////////////////////////////////////////////////////////////////////// // // PerfLibrary class declaration. There is one perf library instance per linkee. // /////////////////////////////////////////////////////////////////////////////// PerfLibrary::PerfLibrary (LPCWSTR pcwstrPerfName) { wcsncpy (m_wszPerfName, pcwstrPerfName, MAX_PERF_NAME); m_wszPerfName[MAX_PERF_NAME-1] = L'\0'; // Ensure NULL termination ZeroMemory (m_rgpObjDef, sizeof (m_rgpObjDef)); m_dwObjDef = 0; m_hMap = 0; m_pbMap = 0; } PerfLibrary::~PerfLibrary (void) { DeInit (); } void PerfLibrary::DeInit (void) { DWORD i; // Destroy the PerfObjectDefinition's we owned. for (i = 0; i < m_dwObjDef; i++) { delete m_rgpObjDef[i]; m_rgpObjDef[i] = NULL; } m_dwObjDef = 0; // Destroy our shared memory mapping. if (m_pbMap) { UnmapViewOfFile ((void*) m_pbMap); m_pbMap = 0; } if (m_hMap) { CloseHandle (m_hMap); m_hMap = 0; } } PerfObjectDefinition* PerfLibrary::AddPerfObjectDefinition (LPCWSTR pcwstrObjectName, DWORD dwObjectNameIndex, BOOL fInstances) { PerfObjectDefinition* ppod = NULL; if (m_dwObjDef < MAX_PERF_OBJECTS) { ppod = new PerfObjectDefinition (pcwstrObjectName, dwObjectNameIndex, fInstances); if (NULL == ppod) goto Exit; m_rgpObjDef[m_dwObjDef++] = ppod; } Exit: return ppod; } BOOL PerfLibrary::Init (void) { DWORD i = 0; WCHAR wszPerformanceKey[256] = {L'\0'}; HKEY hKey = NULL; LONG status = 0; DWORD size, type = 0; BOOL fRet = FALSE; DWORD dwErr = ERROR_SUCCESS; PSECURITY_DESCRIPTOR pSd = NULL; SECURITY_ATTRIBUTES sa; // // Get counter and help index base values from registry and // update static data structures by adding base to offset values // that are statically defined in the structure initialization // swprintf (wszPerformanceKey, L"SYSTEM\\CurrentControlSet\\Services\\%s\\Performance", m_wszPerfName ); status = RegOpenKeyExW (HKEY_LOCAL_MACHINE, wszPerformanceKey, 0L, KEY_READ, &hKey); if (status != ERROR_SUCCESS) goto Exit; // // Get FirstCounter RegValue // size = sizeof(DWORD); status = RegQueryValueEx (hKey, "First Counter", 0L, &type, (LPBYTE)&m_dwFirstCounter, &size); if (status != ERROR_SUCCESS) goto Exit; // // Get FirstHelp RegValue // size = sizeof(DWORD); status = RegQueryValueEx( hKey, "First Help", 0L, &type, (LPBYTE)&m_dwFirstHelp, &size); if (status != ERROR_SUCCESS) goto Exit; // // Initialize the security descriptor with completely open access // dwErr = InitializeBasicSecurityDescriptor (&pSd); if (dwErr) { fRet = FALSE; goto Exit; } sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = pSd; sa.bInheritHandle = TRUE; // // Create the shared memory object for the list of object names. // Return error if it already exists as we cannot operate if this // is the second instance of the app. // m_hMap = CreateFileMappingW (INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, (MAX_PERF_OBJECTS * MAX_OBJECT_NAME * sizeof (WCHAR) + sizeof (DWORD)), m_wszPerfName); if (m_hMap == NULL || GetLastError() == ERROR_ALREADY_EXISTS) goto Exit; // // Map the file into memory // m_pbMap = (BYTE*) MapViewOfFile (m_hMap, FILE_MAP_WRITE, 0, 0, 0); if (!m_pbMap) goto Exit; // // Assign pointers into the shared memory region // m_pdwObjectNames = (DWORD*) m_pbMap; m_prgObjectNames = (OBJECTNAME*) (m_pbMap+sizeof(DWORD)); // // Copy the object names into the shared memory // *m_pdwObjectNames = m_dwObjDef; for (i = 0; i < m_dwObjDef; i++) { if (m_rgpObjDef[i]->Init( this )) wcscpy (m_prgObjectNames[i], m_rgpObjDef[i]->m_wszObjectName); } fRet = TRUE; Exit: if (hKey) RegCloseKey (hKey); if (!fRet) { if (m_pbMap) { UnmapViewOfFile ((PVOID)m_pbMap); m_pbMap = 0; } if (m_hMap) { CloseHandle (m_hMap); m_hMap = 0; } } if (pSd) delete [] (BYTE *) pSd; return fRet; } /////////////////////////////////////////////////////////////////////////////// // // PerfObjectDefinition class implementation. There is one of these for each // perfmon object exported. Generally there is just one, but not neccessarily. // /////////////////////////////////////////////////////////////////////////////// PerfObjectDefinition::PerfObjectDefinition (LPCWSTR pcwstrObjectName, DWORD dwObjectNameIndex, BOOL fInstances) : m_dwObjectNameIndex (dwObjectNameIndex), m_fInstances (fInstances), m_dwCounters (0) { wcsncpy (m_wszObjectName, pcwstrObjectName, MAX_OBJECT_NAME); m_wszObjectName[MAX_OBJECT_NAME-1] = L'\0'; // Ensure NULL Terminated ZeroMemory (m_rgpCounterDef, sizeof(m_rgpCounterDef)); m_dwActiveInstances = 0; m_pSMS = NULL; m_dwShmemMappingSize = SHMEM_MAPPING_SIZE; m_fCSInit = FALSE; m_pPoiTotal = NULL; m_pPerfObjectType = NULL; } PerfObjectDefinition::~PerfObjectDefinition (void) { DeInit(); } void PerfObjectDefinition::DeInit (void) { SharedMemorySegment *pSMS, *pSMSNext; DWORD i; // First destroy the _Total instance. if (m_pPoiTotal) { delete m_pPoiTotal; m_pPoiTotal = NULL; } // // Reset these values in the shared memory so that before we unmap the memory, // perfmon won't think that we still have instances & counters running. // if (m_pPerfObjectType) { m_pPerfObjectType->NumCounters = 0; m_pPerfObjectType->NumInstances = 0; } // Destroy the PerfCounterDefinition's we owned. for (i = 0; i < m_dwCounters; i++) { delete m_rgpCounterDef[i]; m_rgpCounterDef[i] = NULL; } pSMS = m_pSMS; m_pSMS = NULL; // Enumerate through all the memory mappings we created and destroy them. while (pSMS) { pSMSNext = pSMS->m_pSMSNext; CloseFileMapping (pSMS); delete (pSMS); pSMS = pSMSNext; } // Destroy the critical section. if (m_fCSInit) { m_fCSInit = FALSE; DeleteCriticalSection (&m_csPerfObjInst); } } PerfCounterDefinition* PerfObjectDefinition::AddPerfCounterDefinition ( DWORD dwCounterNameIndex, DWORD dwCounterType, LONG lDefaultScale) { PerfCounterDefinition* ppcd = NULL; if (m_dwCounters < MAX_OBJECT_COUNTERS) { ppcd = new PerfCounterDefinition (dwCounterNameIndex, dwCounterType, lDefaultScale); if (NULL == ppcd) goto Exit; m_rgpCounterDef[m_dwCounters++] = ppcd; } Exit: return ppcd; } PerfCounterDefinition* PerfObjectDefinition::AddPerfCounterDefinition ( PerfCounterDefinition* pCtrRef, DWORD dwCounterNameIndex, DWORD dwCounterType, LONG lDefaultScale) { PerfCounterDefinition* ppcd = NULL; if (m_dwCounters < MAX_OBJECT_COUNTERS) { ppcd = new PerfCounterDefinition (pCtrRef, dwCounterNameIndex, dwCounterType, lDefaultScale); if (NULL == ppcd) goto Exit; m_rgpCounterDef[m_dwCounters++] = ppcd; } Exit: return ppcd; } BOOL PerfObjectDefinition::Init (PerfLibrary* pPerfLib) { DWORD i = 0; DWORD dwOffset = 0; DWORD dwDefinitionLength= 0; BOOL fRet = FALSE; // // Compute the size of the shared memory for this object definition // // Start with the basics: // we need a PERF_OBJECT_TYPE for the object information and // we need a PERF_COUNTER_DEFINITION for each counter in the object dwDefinitionLength = (sizeof(PERF_OBJECT_TYPE) + m_dwCounters * sizeof(PERF_COUNTER_DEFINITION)); // We also keep a DWORD in the shared memory to give the DLL // our pre-computed value for m_dwCounterData m_dwDefinitionLength = dwDefinitionLength + sizeof(DWORD); // Compute the counter data space m_dwCounterData = sizeof(PERF_COUNTER_BLOCK); for (i = 0; i < m_dwCounters; i++) { m_dwCounterData += m_rgpCounterDef[i]->m_dwCounterSize; } // Compute the per instance space m_dwPerInstanceData = (sizeof(INSTANCE_DATA) + m_dwCounterData); // Make sure our memory mapping is large enough while (m_dwShmemMappingSize < m_dwDefinitionLength || m_dwShmemMappingSize < m_dwPerInstanceData) m_dwShmemMappingSize *= 2; // Compute the number of instances can be stored in one shmem mapping. m_dwInstancesPerMapping = (DWORD)(m_dwShmemMappingSize / m_dwPerInstanceData); m_dwInstances1stMapping = (DWORD)((m_dwShmemMappingSize - m_dwDefinitionLength) / m_dwPerInstanceData); // // Create the shared memory object for the list of object names. If it // already exists, abort! // m_pSMS = new SharedMemorySegment; if (!m_pSMS) goto Exit; if (!FCreateFileMapping (m_pSMS, m_wszObjectName, 0, m_dwShmemMappingSize)) goto Exit; // // Set the pointers to the PERF API structures // m_pPerfObjectType = (PERF_OBJECT_TYPE*) m_pSMS->m_pbMap; m_rgPerfCounterDefinition = (PERF_COUNTER_DEFINITION*) (m_pPerfObjectType+1); // // Initialize the PERF API structures // m_pPerfObjectType->TotalByteLength = dwDefinitionLength; m_pPerfObjectType->DefinitionLength = dwDefinitionLength; m_pPerfObjectType->HeaderLength = sizeof (PERF_OBJECT_TYPE); m_pPerfObjectType->ObjectNameTitleIndex = m_dwObjectNameIndex + pPerfLib->m_dwFirstCounter ; m_pPerfObjectType->ObjectNameTitle = 0; m_pPerfObjectType->ObjectHelpTitleIndex = m_dwObjectNameIndex + pPerfLib->m_dwFirstHelp; m_pPerfObjectType->ObjectHelpTitle = 0; m_pPerfObjectType->DetailLevel = PERF_DETAIL_NOVICE; m_pPerfObjectType->NumCounters = m_dwCounters; m_pPerfObjectType->CodePage = (DWORD) 0xffffffff; m_pPerfObjectType->DefaultCounter = 0; if( !m_fInstances ) m_pPerfObjectType->NumInstances = PERF_NO_INSTANCES; else m_pPerfObjectType->NumInstances = 0; // // Have all of the PerfCounterDefinition's in this object intialize their // PERF_COUNTER_DEFINITION structures in the shared memory // dwOffset = sizeof (PERF_COUNTER_BLOCK); for (i = 0; i < m_dwCounters; i++) m_rgpCounterDef[i]->Init(pPerfLib, m_rgPerfCounterDefinition + i, &dwOffset); // Save value for dwCounterData in shared memory for DLL *((DWORD*) (m_pSMS->m_pbMap + dwDefinitionLength)) = m_dwCounterData; // // Initialzie the critical section to protects the creation/deletion of // perf object instances. Use AndSpinCount variation to avoid exception // handling. // if (!InitializeCriticalSectionAndSpinCount(&m_csPerfObjInst, 0x80000000)) goto Exit; m_fCSInit = TRUE; // Create the _Total instance as the 1st instance if there will be multiple instances if (m_fInstances) { m_pPoiTotal = AddPerfObjectInstance (L"_Total"); if (!m_pPoiTotal) goto Exit; } fRet = TRUE; Exit: if (!fRet) { if (m_pPoiTotal) { delete m_pPoiTotal; m_pPoiTotal = NULL; } if (m_fCSInit) { DeleteCriticalSection (&m_csPerfObjInst); m_fCSInit = FALSE; } if (m_pSMS) { CloseFileMapping (m_pSMS); delete (m_pSMS); m_pSMS = NULL; } } return fRet; } DWORD PerfObjectDefinition::GetCounterOffset (DWORD dwId) { for (DWORD i = 0; i < m_dwCounters; i++) if (m_rgpCounterDef[i]->m_dwCounterNameIndex == dwId) return m_rgpCounterDef[i]->m_dwOffset; return 0; } PerfObjectInstance* PerfObjectDefinition::AddPerfObjectInstance (LPCWSTR pwcstrInstanceName) { PerfObjectInstance* ppoi = NULL; char* pCounterData = NULL; INSTANCE_DATA* pInstData = 0; LONG lID = 0; SharedMemorySegment* pSMS = NULL; SharedMemorySegment* pSMSPrev = NULL; SharedMemorySegment* pSMSNew = NULL; DWORD dwInstances = 0; DWORD dwInstIndex = 0; DWORD dwSMS = 0; BOOL fCSEntered = FALSE; BOOL fSuccess = FALSE; // // Make sure we've been initialized // if (!m_pSMS || !m_fCSInit) goto Exit; // // Instances may be created in different threads. Need to protect the following code. // EnterCriticalSection (&m_csPerfObjInst); fCSEntered = TRUE; if (!m_fInstances) { // See if we have already created the single instance of this object if (m_dwActiveInstances != 0) goto Exit; pCounterData = (char *)(m_pSMS->m_pbMap) + m_dwDefinitionLength; } else { // // Find a free instance in current mapped segments. // pSMS = m_pSMS; lID = 0; while (pSMS) { if (0 == dwSMS++) { // // If this is the first mapping, offset pCounterData by m_dwDefinitionLength. // pCounterData = (char *)(pSMS->m_pbMap) + m_dwDefinitionLength; dwInstances = m_dwInstances1stMapping; } else { // // Otherwise, pCounterData starts from the 1st byte of the mapping. // pCounterData = (char *)(pSMS->m_pbMap); dwInstances = m_dwInstancesPerMapping; } for (dwInstIndex = 0; dwInstIndex < dwInstances; pCounterData += sizeof (INSTANCE_DATA) + m_dwCounterData, dwInstIndex++) { if (!((INSTANCE_DATA*) pCounterData)->fActive) { pInstData = (INSTANCE_DATA*) pCounterData; pCounterData = pCounterData + sizeof (INSTANCE_DATA); goto Found; } lID++; } pSMSPrev = pSMS; pSMS = pSMS->m_pSMSNext; } // // If cannot find a free instance, create a new segment. // pSMSNew = new SharedMemorySegment; if (!pSMSNew) goto Exit; if (!FCreateFileMapping (pSMSNew, m_wszObjectName, dwSMS, m_dwShmemMappingSize)) goto Exit; pInstData = (INSTANCE_DATA*) (pSMSNew->m_pbMap); pCounterData = (char*) (pSMSNew->m_pbMap) + sizeof (INSTANCE_DATA); // // Add the new segment to our segment linked list. // pSMSPrev->m_pSMSNext = pSMSNew; } Found: // // We successfully found a free space for new instance. // ppoi = new PerfObjectInstance (this, pwcstrInstanceName); if (!ppoi) goto Exit; ppoi->Init(pCounterData, pInstData, lID); m_pPerfObjectType->NumInstances++; m_dwActiveInstances++; fSuccess = TRUE; Exit: if (fCSEntered) LeaveCriticalSection (&m_csPerfObjInst); if (!fSuccess) { if (pSMSNew) { CloseFileMapping (pSMSNew); delete (pSMSNew); } if (ppoi) { delete ppoi; ppoi = NULL; } } return ppoi; } void PerfObjectDefinition::DeletePerfObjectInstance () { EnterCriticalSection (&m_csPerfObjInst); m_dwActiveInstances--; m_pPerfObjectType->NumInstances--; LeaveCriticalSection (&m_csPerfObjInst); } /////////////////////////////////////////////////////////////////////////////// // // PerfCounterDefinition class declaration. There is one of these per counter. // /////////////////////////////////////////////////////////////////////////////// PerfCounterDefinition::PerfCounterDefinition (DWORD dwCounterNameIndex, DWORD dwCounterType, LONG lDefaultScale) : m_pCtrRef (NULL), m_dwCounterNameIndex (dwCounterNameIndex), m_lDefaultScale (lDefaultScale), m_dwCounterType (dwCounterType) { if (m_dwCounterType & PERF_SIZE_LARGE) m_dwCounterSize = sizeof (LARGE_INTEGER); else m_dwCounterSize = sizeof (DWORD); } PerfCounterDefinition::PerfCounterDefinition (PerfCounterDefinition* pCtrRef, DWORD dwCounterNameIndex, DWORD dwCounterType, LONG lDefaultScale) : m_pCtrRef (pCtrRef), m_dwCounterNameIndex (dwCounterNameIndex), m_lDefaultScale (lDefaultScale), m_dwCounterType (dwCounterType), m_dwCounterSize (0) { } void PerfCounterDefinition::Init (PerfLibrary* pPerfLib, PERF_COUNTER_DEFINITION* pdef, PDWORD pdwOffset) { pdef->ByteLength = sizeof (PERF_COUNTER_DEFINITION); pdef->CounterNameTitleIndex = m_dwCounterNameIndex + pPerfLib->m_dwFirstCounter ; pdef->CounterNameTitle = 0; pdef->CounterHelpTitleIndex = m_dwCounterNameIndex + pPerfLib->m_dwFirstHelp ; pdef->CounterHelpTitle = 0; pdef->DefaultScale = m_lDefaultScale; pdef->DetailLevel = PERF_DETAIL_NOVICE; pdef->CounterType = m_dwCounterType; if (m_pCtrRef) { // // This counter uses the data of another counter. // pdef->CounterSize = m_pCtrRef->m_dwCounterSize; pdef->CounterOffset = m_pCtrRef->m_dwOffset; } else { // // This counter has its own data. // pdef->CounterSize = m_dwCounterSize; pdef->CounterOffset = *pdwOffset; // Save offset m_dwOffset = *pdwOffset; // Increment offset for next counter definition *pdwOffset += m_dwCounterSize; } } /////////////////////////////////////////////////////////////////////////////// // // PerfObjectInstance class implementation. There is one of these per instance // of an object. There is one if there are no instances (the global instance.) // /////////////////////////////////////////////////////////////////////////////// PerfObjectInstance::PerfObjectInstance (PerfObjectDefinition* pObjDef, LPCWSTR pcwstrInstanceName) { m_pObjDef = pObjDef; if (pcwstrInstanceName) { wcsncpy (m_wszInstanceName, pcwstrInstanceName, MAX_INSTANCE_NAME); m_wszInstanceName[MAX_INSTANCE_NAME-1] = L'\0'; // Ensure NULL termination! } else *m_wszInstanceName = L'\0'; m_fInitialized = FALSE; } void PerfObjectInstance::Init (char* pCounterData, INSTANCE_DATA* pInstData, LONG lID) { int cchNameLength = 0; m_pCounterData = pCounterData; m_pInstanceData = pInstData; // Clear all the counter data ZeroMemory( m_pCounterData, m_pObjDef->m_dwCounterData ); // Set the counter block length ((PERF_COUNTER_BLOCK*)m_pCounterData)->ByteLength = m_pObjDef->m_dwCounterData; if (m_pInstanceData) { m_pInstanceData->perfInstDef.ByteLength = sizeof (PERF_INSTANCE_DEFINITION); m_pInstanceData->perfInstDef.ParentObjectTitleIndex = 0; m_pInstanceData->perfInstDef.ParentObjectInstance = 0; m_pInstanceData->perfInstDef.UniqueID = PERF_NO_UNIQUE_ID; m_pInstanceData->perfInstDef.NameOffset = sizeof (PERF_INSTANCE_DEFINITION); // // The instance-name is copied to wszInstanceName. This is a variable // length NULL terminated unicode string. wszInstanceName must end on // a 32-bit boundary, so that the perf-data that follows this string // is 32-bit aligned. Therefore, if wszInstance contains an odd number // of WCHARS, we add an extra WCHAR to 32-bit align it. The length of // the instance name in bytes, including the terminating NULL and the // padding byte (if present) is written to perfInstDef.NameLength. // cchNameLength = wcslen(m_wszInstanceName) + 1; if(cchNameLength > MAX_INSTANCE_NAME) { // MAX_INSTANCE_NAME is already 32 bit aligned _ASSERT(0 == (MAX_INSTANCE_NAME & 1)); cchNameLength = MAX_INSTANCE_NAME; } else if(cchNameLength & 1) { cchNameLength++; } m_pInstanceData->perfInstDef.NameLength = cchNameLength * sizeof(WCHAR); m_pInstanceData->perfInstDef.ByteLength += cchNameLength * sizeof(WCHAR); CopyMemory(m_pInstanceData->wszInstanceName, m_wszInstanceName, cchNameLength * sizeof(WCHAR)); // If the name got truncated, there may not have been a terminating NULL m_pInstanceData->wszInstanceName[MAX_INSTANCE_NAME - 1] = L'\0'; m_pInstanceData->fActive = TRUE; } m_fInitialized = TRUE; } VOID PerfObjectInstance::DeInit (void) { if (m_fInitialized) { m_fInitialized = FALSE; if (m_pInstanceData) { m_pInstanceData->fActive = FALSE; m_pInstanceData = NULL; } } m_pObjDef->DeletePerfObjectInstance(); } DWORD* PerfObjectInstance::GetDwordCounter (DWORD dwId) { DWORD dwOffset; if (m_fInitialized) { if (dwOffset = m_pObjDef->GetCounterOffset(dwId)) return (DWORD*) (m_pCounterData + dwOffset); } return 0; } LARGE_INTEGER* PerfObjectInstance::GetLargeIntegerCounter (DWORD dwId) { DWORD dwOffset; if (m_fInitialized) { if (dwOffset = m_pObjDef->GetCounterOffset(dwId)) return (LARGE_INTEGER*) (m_pCounterData + dwOffset); } return 0; } QWORD* PerfObjectInstance::GetQwordCounter (DWORD dwId) { DWORD dwOffset; if (m_fInitialized) { if (dwOffset = m_pObjDef->GetCounterOffset(dwId)) return (QWORD*) (m_pCounterData + dwOffset); } return 0; } //--------------------------------------------------------------------------- // Description: // Allocates and returns a SECURITY_DESCRIPTOR structure initialized to // allow all users access. This security descriptor is used to set the // security for the shared memory objects created by snprflib. // Arguments: // OUT pSd Pass in a pointer to SECURITY_DESCRIPTOR, on success this will // be set to a suitably initialized SECURITY_DESCRIPTOR. Caller frees // memory pointed to by pSd. // Returns: // ERROR_SUCCESS on success. // Win32 error to indicate failure. //--------------------------------------------------------------------------- DWORD InitializeBasicSecurityDescriptor (PSECURITY_DESCRIPTOR *ppSd) { DWORD dwErr = ERROR_SUCCESS; PSID pSidWorld = NULL; PSID pSidCreator = NULL; SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY CreatorAuthority = SECURITY_CREATOR_SID_AUTHORITY; ACL *pAcl = NULL; DWORD dwAclSize = 0; *ppSd = NULL; if (!AllocateAndInitializeSid ( &WorldAuthority, 1, SECURITY_WORLD_RID, 0,0,0,0,0,0,0, &pSidWorld)){ dwErr = GetLastError (); goto Exit; } if (!AllocateAndInitializeSid ( &CreatorAuthority, 1, SECURITY_CREATOR_OWNER_RID, 0,0,0,0,0,0,0, &pSidCreator)){ dwErr = GetLastError (); goto Exit; } dwAclSize = sizeof (ACL) + (sizeof (ACCESS_ALLOWED_ACE) - sizeof (LONG)) + GetLengthSid (pSidWorld) + (sizeof (ACCESS_ALLOWED_ACE) - sizeof (LONG)) + GetLengthSid (pSidCreator); // // Allocate SD and ACL with a single alloc // *ppSd = (PSECURITY_DESCRIPTOR) new BYTE [SECURITY_DESCRIPTOR_MIN_LENGTH + dwAclSize]; if (!*ppSd) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto Exit; } if (!InitializeSecurityDescriptor (*ppSd, SECURITY_DESCRIPTOR_REVISION)) { dwErr = GetLastError (); goto Exit; } pAcl = (ACL *) ((BYTE *) *ppSd + SECURITY_DESCRIPTOR_MIN_LENGTH); if (!InitializeAcl ( pAcl, dwAclSize, ACL_REVISION)) { dwErr = GetLastError (); goto Exit; } if (!AddAccessAllowedAce ( pAcl, ACL_REVISION, GENERIC_WRITE, pSidCreator) || !AddAccessAllowedAce ( pAcl, ACL_REVISION, GENERIC_READ, pSidWorld)) { dwErr = GetLastError (); goto Exit; } if (!SetSecurityDescriptorDacl (*ppSd, TRUE, pAcl, FALSE)) dwErr = GetLastError (); Exit: if (pSidWorld) FreeSid (pSidWorld); if (pSidCreator) FreeSid (pSidCreator); return dwErr; } /////////////////////////////////////////////////////////////////////////////// // // Shared memory management functions // /////////////////////////////////////////////////////////////////////////////// BOOL FCreateFileMapping (SharedMemorySegment * pSMS, LPCWSTR pcwstrInstanceName, DWORD dwIndex, DWORD cbSize) { WCHAR pwstrShMem[MAX_PATH]; WCHAR pwstrIndex[MAX_PATH]; PSECURITY_DESCRIPTOR pSd = NULL; SECURITY_ATTRIBUTES sa; HANDLE hMap = NULL; PVOID pvMap = NULL; BOOL fSuccess = FALSE; DWORD dwErr = ERROR_SUCCESS; // // Check parameter // if (!pSMS) goto Exit; pSMS->m_hMap = NULL; pSMS->m_pbMap = NULL; pSMS->m_pSMSNext = NULL; // // Append dwIndex to instance name. // _ultow (dwIndex, pwstrIndex, 16); if (wcslen (pcwstrInstanceName) + wcslen (pwstrIndex) >= MAX_PATH) goto Exit; wcscpy (pwstrShMem, pcwstrInstanceName); wcscat (pwstrShMem, pwstrIndex); dwErr = InitializeBasicSecurityDescriptor (&pSd); if (dwErr) goto Exit; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = pSd; sa.bInheritHandle = TRUE; // // Create the shared memory object. If it already exists, abort! // hMap = CreateFileMappingW (INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, cbSize, pwstrShMem); if (hMap == NULL || GetLastError() == ERROR_ALREADY_EXISTS) goto Exit; // // Map the file into memory // pvMap = MapViewOfFile (hMap, FILE_MAP_WRITE, 0, 0, 0); if (!pvMap) goto Exit; ZeroMemory (pvMap, cbSize); // // Succeeds. Now store the results into pSMS. // pSMS->m_hMap = hMap; pSMS->m_pbMap = (BYTE *)pvMap; fSuccess = TRUE; Exit: if (!fSuccess) { if (pvMap) UnmapViewOfFile (pvMap); if (hMap) CloseHandle (hMap); } if (pSd) delete [] (BYTE *) pSd; return fSuccess; } void CloseFileMapping (SharedMemorySegment * pSMS) { if (pSMS) { if (pSMS->m_pbMap) { UnmapViewOfFile ((PVOID)pSMS->m_pbMap); pSMS->m_pbMap = NULL; } if (pSMS->m_hMap) { CloseHandle (pSMS->m_hMap); pSMS->m_hMap = NULL; } pSMS->m_pSMSNext = NULL; } }