internal unsafe CategorySample(byte[] data, CategoryEntry entry, PerformanceCounterLib library) {
            this.entry = entry;
            this.library = library;
            int categoryIndex = entry.NameIndex;
            NativeMethods.PERF_DATA_BLOCK dataBlock = new NativeMethods.PERF_DATA_BLOCK();
            fixed (byte* dataPtr = data) {
                IntPtr dataRef = new IntPtr((void*) dataPtr);

                Marshal.PtrToStructure(dataRef, dataBlock);
                this.SystemFrequency = dataBlock.PerfFreq;
                this.TimeStamp = dataBlock.PerfTime;
                this.TimeStamp100nSec = dataBlock.PerfTime100nSec;
                dataRef = (IntPtr)((long)dataRef + dataBlock.HeaderLength);
                int numPerfObjects = dataBlock.NumObjectTypes;
                if (numPerfObjects == 0) {
                    this.CounterTable = new Hashtable();
                    this.InstanceNameTable = new Hashtable(StringComparer.OrdinalIgnoreCase);
                    return;
                }

                //Need to find the right category, GetPerformanceData might return
                //several of them.
                NativeMethods.PERF_OBJECT_TYPE perfObject = null;
                bool foundCategory = false;
                for (int index = 0; index < numPerfObjects; index++) {
                    perfObject = new NativeMethods.PERF_OBJECT_TYPE();
                    Marshal.PtrToStructure(dataRef, perfObject);

                   if (perfObject.ObjectNameTitleIndex == categoryIndex) {
                        foundCategory = true;
                        break;
                    }

                    dataRef = (IntPtr)((long)dataRef + perfObject.TotalByteLength);
                }

                if (!foundCategory)
                    throw new InvalidOperationException(SR.GetString(SR.CantReadCategoryIndex, categoryIndex.ToString(CultureInfo.CurrentCulture)));

                this.CounterFrequency = perfObject.PerfFreq;
                this.CounterTimeStamp = perfObject.PerfTime;
                int counterNumber = perfObject.NumCounters;
                int instanceNumber = perfObject.NumInstances;

                if (instanceNumber == -1)
                    IsMultiInstance = false;
                else
                    IsMultiInstance = true;
                
                // Move pointer forward to end of PERF_OBJECT_TYPE
                dataRef = (IntPtr)((long)dataRef + perfObject.HeaderLength);

                CounterDefinitionSample[] samples = new CounterDefinitionSample[counterNumber];
                this.CounterTable = new Hashtable(counterNumber);
                for (int index = 0; index < samples.Length; ++ index) {
                    NativeMethods.PERF_COUNTER_DEFINITION perfCounter = new NativeMethods.PERF_COUNTER_DEFINITION();
                    Marshal.PtrToStructure(dataRef, perfCounter);
                    samples[index] = new CounterDefinitionSample(perfCounter, this, instanceNumber);
                    dataRef = (IntPtr)((long)dataRef + perfCounter.ByteLength);

                    int currentSampleType = samples[index].CounterType;
                    if (!PerformanceCounterLib.IsBaseCounter(currentSampleType)) {
                        // We'll put only non-base counters in the table. 
                        if (currentSampleType != NativeMethods.PERF_COUNTER_NODATA)
                            this.CounterTable[samples[index].NameIndex] = samples[index];
                    }
                    else {
                        // it's a base counter, try to hook it up to the main counter. 
                        Debug.Assert(index > 0, "Index > 0 because base counters should never be at index 0");
                        if (index > 0)
                            samples[index-1].BaseCounterDefinitionSample = samples[index];
                    }
                }

                // now set up the InstanceNameTable.  
                if (!IsMultiInstance) {
                    this.InstanceNameTable = new Hashtable(1, StringComparer.OrdinalIgnoreCase);
                    this.InstanceNameTable[PerformanceCounterLib.SingleInstanceName] = 0;

                    for (int index = 0; index < samples.Length; ++ index)  {
                        samples[index].SetInstanceValue(0, dataRef);
                    }
                }
                else {
                    string[] parentInstanceNames = null;
                    this.InstanceNameTable = new Hashtable(instanceNumber, StringComparer.OrdinalIgnoreCase);
                    for (int i = 0; i < instanceNumber; i++) {
                        NativeMethods.PERF_INSTANCE_DEFINITION perfInstance = new NativeMethods.PERF_INSTANCE_DEFINITION();
                        Marshal.PtrToStructure(dataRef, perfInstance);
                        if (perfInstance.ParentObjectTitleIndex > 0 && parentInstanceNames == null)
                            parentInstanceNames = GetInstanceNamesFromIndex(perfInstance.ParentObjectTitleIndex);

                        string instanceName;
                        if (parentInstanceNames != null && perfInstance.ParentObjectInstance >= 0 && perfInstance.ParentObjectInstance < parentInstanceNames.Length - 1)
                            instanceName = parentInstanceNames[perfInstance.ParentObjectInstance] + "/" + Marshal.PtrToStringUni((IntPtr)((long)dataRef + perfInstance.NameOffset));
                        else
                            instanceName = Marshal.PtrToStringUni((IntPtr)((long)dataRef + perfInstance.NameOffset));

                        //In some cases instance names are not unique (Process), same as perfmon
                        //generate a unique name.
                        string newInstanceName = instanceName;
                        int newInstanceNumber = 1;
                        while (true) {
                            if (!this.InstanceNameTable.ContainsKey(newInstanceName)) {
                                this.InstanceNameTable[newInstanceName] = i;
                                break;
                            }
                            else {
                                newInstanceName =  instanceName + "#" + newInstanceNumber.ToString(CultureInfo.InvariantCulture);
                                ++  newInstanceNumber;
                            }
                        }


                        dataRef = (IntPtr)((long)dataRef + perfInstance.ByteLength);
                        for (int index = 0; index < samples.Length; ++ index)
                            samples[index].SetInstanceValue(i, dataRef);

                        dataRef = (IntPtr)((long)dataRef + Marshal.ReadInt32(dataRef));
                    }
                }
            }
        }
        //
        // FindCategory -
        //
        // * when the function returns true the returnCategoryPointerReference is set to the CategoryEntry
        //   that matches 'categoryNameHashCode' and 'categoryName'
        //
        // * when the function returns false the returnCategoryPointerReference is set to the last CategoryEntry
        //   in the linked list
        // 
        private unsafe bool FindCategory(CategoryEntry** returnCategoryPointerReference) {
            CategoryEntry* firstCategoryPointer =  (CategoryEntry*)(ResolveOffset(InitialOffset, CategoryEntrySize));
            CategoryEntry* currentCategoryPointer = firstCategoryPointer;
            CategoryEntry* previousCategoryPointer = firstCategoryPointer;

            for(;;) {
                if (currentCategoryPointer->IsConsistent == 0)
                    Verify(currentCategoryPointer);
                
                if (currentCategoryPointer->CategoryNameHashCode == categoryNameHashCode) {
                    if (StringEquals(categoryName,  currentCategoryPointer->CategoryNameOffset)) {
                        *returnCategoryPointerReference = currentCategoryPointer;
                        return true;
                    }
                }

                previousCategoryPointer = currentCategoryPointer;
                if (currentCategoryPointer->NextCategoryOffset != 0)
                    currentCategoryPointer = (CategoryEntry*)(ResolveOffset(currentCategoryPointer->NextCategoryOffset, CategoryEntrySize));
                else {
                    *returnCategoryPointerReference = previousCategoryPointer;
                    return false;
                }
            }
        }
        private unsafe bool FindInstance(int instanceNameHashCode, string instanceName, 
                                           CategoryEntry* categoryPointer, InstanceEntry** returnInstancePointerReference, 
                                           bool activateUnusedInstances, PerformanceCounterInstanceLifetime lifetime, 
                                           out bool foundFreeInstance) {

            InstanceEntry* currentInstancePointer = (InstanceEntry*)(ResolveOffset(categoryPointer->FirstInstanceOffset, InstanceEntrySize));
            InstanceEntry* previousInstancePointer = currentInstancePointer;
            foundFreeInstance = false;
            // Look at the first instance to determine if this is single or multi instance. 
            if (currentInstancePointer->InstanceNameHashCode == SingleInstanceHashCode) {
                if (StringEquals(SingleInstanceName, currentInstancePointer->InstanceNameOffset)){
                    if (instanceName != SingleInstanceName)
                        throw new InvalidOperationException(SR.GetString(SR.SingleInstanceOnly, categoryName));
                }
                else {
                    if (instanceName == SingleInstanceName)
                        throw new InvalidOperationException(SR.GetString(SR.MultiInstanceOnly, categoryName));
                }
            }
            else {
                if (instanceName == SingleInstanceName)
                    throw new InvalidOperationException(SR.GetString(SR.MultiInstanceOnly, categoryName));
            }

            //
            // 1st pass find exact matching!
            // 
            // We don't need to aggressively claim unused instances. For performance, we would proactively 
            // verify lifetime of instances if activateUnusedInstances is specified and certain time 
            // has elapsed since last sweep or we are running out of shared memory.  
            bool verifyLifeTime = activateUnusedInstances;
            if (activateUnusedInstances) {
                
                int totalSize = InstanceEntrySize + ProcessLifetimeEntrySize + InstanceNameSlotSize +  (CounterEntrySize * categoryData.CounterNames.Count);
                int freeMemoryOffset = *((int *) baseAddress);
                int alignmentAdjustment;
                int newOffset = CalculateMemoryNoBoundsCheck(freeMemoryOffset, totalSize, out alignmentAdjustment);

                if (!(newOffset > FileView.FileMappingSize || newOffset < 0)) {
                    long tickDelta = (DateTime.Now.Ticks - Volatile.Read(ref LastInstanceLifetimeSweepTick));  
                    if (tickDelta < InstanceLifetimeSweepWindow) 
                        verifyLifeTime = false;    
                }
            }

            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
            try {
                for(;;) {
                    bool verifiedLifetimeOfThisInstance = false;
                    if (verifyLifeTime && (currentInstancePointer->RefCount != 0)) {
                        verifiedLifetimeOfThisInstance = true;
                        VerifyLifetime(currentInstancePointer);
                    }
                    
                    if (currentInstancePointer->InstanceNameHashCode == instanceNameHashCode) {
                        if (StringEquals(instanceName, currentInstancePointer->InstanceNameOffset)){
                            // we found a matching instance. 
                            *returnInstancePointerReference = currentInstancePointer;
    
                            CounterEntry* firstCounter = (CounterEntry*) ResolveOffset(currentInstancePointer->FirstCounterOffset, CounterEntrySize);
                            ProcessLifetimeEntry* lifetimeEntry;
                            if (categoryData.UseUniqueSharedMemory) 
                                lifetimeEntry = (ProcessLifetimeEntry*) ResolveOffset(firstCounter->LifetimeOffset, ProcessLifetimeEntrySize);
                            else
                                lifetimeEntry = null;
                            
                            // ensure that we have verified the lifetime of the matched instance
                            if (!verifiedLifetimeOfThisInstance && currentInstancePointer->RefCount != 0) 
                                VerifyLifetime(currentInstancePointer);
                                
                            if (currentInstancePointer->RefCount != 0) {
                                if (lifetimeEntry != null && lifetimeEntry->ProcessId != 0) {
                                    if (lifetime != PerformanceCounterInstanceLifetime.Process)
                                        throw new InvalidOperationException(SR.GetString(SR.CantConvertProcessToGlobal));
                                        
                                    // make sure only one process is using this instance. 
                                    if (ProcessData.ProcessId != lifetimeEntry->ProcessId)
                                        throw new InvalidOperationException(SR.GetString(SR.InstanceAlreadyExists, instanceName));

                                   // compare start time of the process, account for ACL issues in querying process information
                                    if ((lifetimeEntry->StartupTime != -1) && (ProcessData.StartupTime != -1)) { 
                                        if (ProcessData.StartupTime != lifetimeEntry->StartupTime)
                                            throw new InvalidOperationException(SR.GetString(SR.InstanceAlreadyExists, instanceName));
                                    }
                                }
                                else {
                                    if (lifetime == PerformanceCounterInstanceLifetime.Process)
                                        throw new InvalidOperationException(SR.GetString(SR.CantConvertGlobalToProcess));
                                }
                                return true;
                            }
                            
                            if (activateUnusedInstances) {
                                Mutex mutex = null;
                                RuntimeHelpers.PrepareConstrainedRegions();
                                try {
                                    SharedUtils.EnterMutexWithoutGlobal(categoryData.MutexName, ref mutex);
                                    ClearCounterValues(currentInstancePointer);
                                    if (lifetimeEntry != null)
                                        PopulateLifetimeEntry(lifetimeEntry, lifetime);
                                    
                                    currentInstancePointer->RefCount = 1;
                                    return true;
                                }
                                finally {
                                    if (mutex != null) {
                                        mutex.ReleaseMutex();
                                        mutex.Close();
                                    }
                                }
                            }
                            else
                                return false;
                        }
                    }
    
                    if (currentInstancePointer->RefCount == 0) {
                        foundFreeInstance = true;
                    }
    
                    previousInstancePointer = currentInstancePointer;
                    if (currentInstancePointer->NextInstanceOffset != 0)
                        currentInstancePointer =  (InstanceEntry*)(ResolveOffset(currentInstancePointer->NextInstanceOffset, InstanceEntrySize));
                    else {
                        *returnInstancePointerReference = previousInstancePointer;
                        return false;
                    }
                }
            }
            finally  {
                SecurityPermission.RevertAssert();
                
                if (verifyLifeTime) 
                    Volatile.Write(ref LastInstanceLifetimeSweepTick, DateTime.Now.Ticks);
            }
        }
        private unsafe int CreateCategory(CategoryEntry* lastCategoryPointer, 
                                            int instanceNameHashCode, string instanceName, 
                                            PerformanceCounterInstanceLifetime lifetime) {
            int categoryNameLength;
            int instanceNameLength;
            int alignmentAdjustment;
            int freeMemoryOffset;
            int newOffset = 0;
            int totalSize;

            categoryNameLength = (categoryName.Length + 1) * 2;
            totalSize = CategoryEntrySize + InstanceEntrySize + (CounterEntrySize * categoryData.CounterNames.Count) + categoryNameLength;
            for (int i=0; i<categoryData.CounterNames.Count; i++) {
                totalSize += (((string)categoryData.CounterNames[i]).Length + 1) * 2;
            }

            if (categoryData.UseUniqueSharedMemory) {
                instanceNameLength = InstanceNameSlotSize;
                totalSize += ProcessLifetimeEntrySize + instanceNameLength;

                // If we're in a separate shared memory, we need to do a two stage update of the free memory pointer.
                // First we calculate our alignment adjustment and where the new free offset is.  Then we 
                // write the new structs and data.  The last two operations are to link the new structs into the 
                // existing ones and update the next free offset.  Our process could get killed in between those two,
                // leaving the memory in an inconsistent state.  We use the "IsConsistent" flag to help determine 
                // when that has happened. 
                freeMemoryOffset = *((int *) baseAddress);
                newOffset = CalculateMemory(freeMemoryOffset, totalSize, out alignmentAdjustment);

                if (freeMemoryOffset == InitialOffset)
                    lastCategoryPointer->IsConsistent = 0;
            }
            else {
                instanceNameLength = (instanceName.Length +1) * 2;
                totalSize += instanceNameLength;
                freeMemoryOffset = CalculateAndAllocateMemory(totalSize, out alignmentAdjustment);
            }

            long nextPtr = ResolveOffset(freeMemoryOffset, totalSize + alignmentAdjustment);
            
            CategoryEntry* newCategoryEntryPointer;
            InstanceEntry* newInstanceEntryPointer;
            // We need to decide where to put the padding returned in alignmentAdjustment.  There are several things that
            // need to be aligned.  First, we need to align each struct on a 4 byte boundary so we can use interlocked 
            // operations on the int Spinlock field.  Second, we need to align the CounterEntry on an 8 byte boundary so that
            // on 64 bit platforms we can use interlocked operations on the Value field.  alignmentAdjustment guarantees 8 byte
            // alignemnt, so we use that for both.  If we're creating the very first category, however, we can't move that 
            // CategoryEntry.  In this case we put the alignmentAdjustment before the InstanceEntry. 
            if (freeMemoryOffset == InitialOffset) {
                newCategoryEntryPointer = (CategoryEntry*) nextPtr;
                nextPtr += CategoryEntrySize + alignmentAdjustment;
                newInstanceEntryPointer = (InstanceEntry*) nextPtr;
            }
            else {
                nextPtr += alignmentAdjustment;
                newCategoryEntryPointer = (CategoryEntry*) nextPtr;
                nextPtr += CategoryEntrySize;
                newInstanceEntryPointer = (InstanceEntry*) nextPtr;
            }
            nextPtr += InstanceEntrySize;

            // create the first CounterEntry and reserve space for all of the rest.  We won't 
            // finish creating them until the end
            CounterEntry* newCounterEntryPointer = (CounterEntry*) nextPtr;
            nextPtr += CounterEntrySize * categoryData.CounterNames.Count;

            if (categoryData.UseUniqueSharedMemory) {
                ProcessLifetimeEntry* newLifetimeEntry = (ProcessLifetimeEntry*) nextPtr;
                nextPtr += ProcessLifetimeEntrySize;
                
                newCounterEntryPointer->LifetimeOffset = (int)((long)newLifetimeEntry - baseAddress);
                PopulateLifetimeEntry(newLifetimeEntry, lifetime);
            }

            newCategoryEntryPointer->CategoryNameHashCode = categoryNameHashCode;
            newCategoryEntryPointer->NextCategoryOffset = 0;
            newCategoryEntryPointer->FirstInstanceOffset = (int)((long)newInstanceEntryPointer - baseAddress);
            newCategoryEntryPointer->CategoryNameOffset = (int) (nextPtr - baseAddress);
            SafeMarshalCopy(categoryName, (IntPtr)nextPtr);
            nextPtr += categoryNameLength;

            newInstanceEntryPointer->InstanceNameHashCode = instanceNameHashCode;
            newInstanceEntryPointer->NextInstanceOffset = 0;
            newInstanceEntryPointer->FirstCounterOffset = (int)((long)newCounterEntryPointer - baseAddress);
            newInstanceEntryPointer->RefCount = 1;
            newInstanceEntryPointer->InstanceNameOffset = (int) (nextPtr - baseAddress);
            SafeMarshalCopy(instanceName, (IntPtr)nextPtr);
            nextPtr += instanceNameLength;

            string counterName = (string) categoryData.CounterNames[0];
            newCounterEntryPointer->CounterNameHashCode = GetWstrHashCode(counterName);
            SetValue(newCounterEntryPointer, 0);
            newCounterEntryPointer->CounterNameOffset = (int) (nextPtr - baseAddress);
            SafeMarshalCopy(counterName, (IntPtr)nextPtr);
            nextPtr += (counterName.Length + 1) * 2;
                
            CounterEntry* previousCounterEntryPointer;
            for (int i=1; i<categoryData.CounterNames.Count; i++) {
                previousCounterEntryPointer = newCounterEntryPointer;
                counterName = (string) categoryData.CounterNames[i];
                
                newCounterEntryPointer++;
                newCounterEntryPointer->CounterNameHashCode = GetWstrHashCode(counterName);
                SetValue(newCounterEntryPointer, 0);
                newCounterEntryPointer->CounterNameOffset = (int) (nextPtr - baseAddress);
                SafeMarshalCopy(counterName, (IntPtr)nextPtr);

                nextPtr += (counterName.Length + 1) * 2;
                previousCounterEntryPointer->NextCounterOffset = (int)((long)newCounterEntryPointer - baseAddress);
            }
            
            Debug.Assert(nextPtr - baseAddress == freeMemoryOffset + totalSize + alignmentAdjustment, "We should have used all of the space we requested at this point");
            
            int offset = (int) ((long) newCategoryEntryPointer - baseAddress);
            lastCategoryPointer->IsConsistent = 0;
            // If not the first category node, link it.
            if (offset != InitialOffset)
                lastCategoryPointer->NextCategoryOffset = offset;

            if (categoryData.UseUniqueSharedMemory) {
                *((int*) baseAddress) = newOffset;
                lastCategoryPointer->IsConsistent = 1;
            }
            return offset;
        }
        private unsafe int CreateInstance(CategoryEntry* categoryPointer, 
                                            int instanceNameHashCode, string instanceName, 
                                            PerformanceCounterInstanceLifetime lifetime) {
            int instanceNameLength;
            int totalSize = InstanceEntrySize +  (CounterEntrySize * categoryData.CounterNames.Count);
            int alignmentAdjustment;
            int freeMemoryOffset;
            int newOffset = 0;


            if (categoryData.UseUniqueSharedMemory) {
                instanceNameLength = InstanceNameSlotSize;
                totalSize += ProcessLifetimeEntrySize + instanceNameLength;

                // If we're in a separate shared memory, we need to do a two stage update of the free memory pointer.
                // First we calculate our alignment adjustment and where the new free offset is.  Then we 
                // write the new structs and data.  The last two operations are to link the new structs into the 
                // existing ones and update the next free offset.  Our process could get killed in between those two,
                // leaving the memory in an inconsistent state.  We use the "IsConsistent" flag to help determine 
                // when that has happened. 
                freeMemoryOffset = *((int *) baseAddress);
                newOffset = CalculateMemory(freeMemoryOffset, totalSize, out alignmentAdjustment);
            }
            else {
                instanceNameLength = (instanceName.Length +1) * 2;
                totalSize += instanceNameLength;

                // add in the counter names for the global shared mem.
                for (int i=0; i<categoryData.CounterNames.Count; i++) {
                    totalSize += (((string)categoryData.CounterNames[i]).Length + 1) * 2;
                }
                freeMemoryOffset = CalculateAndAllocateMemory(totalSize, out alignmentAdjustment);
            }

            freeMemoryOffset += alignmentAdjustment;
            long nextPtr = ResolveOffset(freeMemoryOffset, totalSize);    // don't add alignmentAdjustment since it's already
                                                                          // been added to freeMemoryOffset 

            InstanceEntry* newInstanceEntryPointer = (InstanceEntry*) nextPtr;
            nextPtr += InstanceEntrySize;

            // create the first CounterEntry and reserve space for all of the rest.  We won't 
            // finish creating them until the end
            CounterEntry* newCounterEntryPointer = (CounterEntry*) nextPtr;
            nextPtr += CounterEntrySize * categoryData.CounterNames.Count;
            
            if (categoryData.UseUniqueSharedMemory) {
                ProcessLifetimeEntry* newLifetimeEntry = (ProcessLifetimeEntry*) nextPtr;
                nextPtr += ProcessLifetimeEntrySize;
                
                newCounterEntryPointer->LifetimeOffset = (int)((long)newLifetimeEntry - baseAddress);
                PopulateLifetimeEntry(newLifetimeEntry, lifetime);
            }

            // set up the InstanceEntry
            newInstanceEntryPointer->InstanceNameHashCode = instanceNameHashCode;
            newInstanceEntryPointer->NextInstanceOffset = 0;
            newInstanceEntryPointer->FirstCounterOffset = (int)((long)newCounterEntryPointer - baseAddress);
            newInstanceEntryPointer->RefCount = 1;
            newInstanceEntryPointer->InstanceNameOffset = (int) (nextPtr - baseAddress);
            SafeMarshalCopy(instanceName, (IntPtr)nextPtr);

            nextPtr += instanceNameLength;


            if (categoryData.UseUniqueSharedMemory) {
                // in the unique shared mem we'll assume that the CounterEntries of the first instance
                // are all created.  Then we can just refer to the old counter name rather than copying in a new one.
                InstanceEntry* firstInstanceInCategoryPointer = (InstanceEntry*) ResolveOffset(categoryPointer->FirstInstanceOffset, InstanceEntrySize);
                CounterEntry* firstCounterInCategoryPointer = (CounterEntry*) ResolveOffset(firstInstanceInCategoryPointer->FirstCounterOffset, CounterEntrySize);
                newCounterEntryPointer->CounterNameHashCode = firstCounterInCategoryPointer->CounterNameHashCode;
                SetValue(newCounterEntryPointer, 0);
                newCounterEntryPointer->CounterNameOffset = firstCounterInCategoryPointer->CounterNameOffset;

                // now create the rest of the CounterEntrys
                CounterEntry* previousCounterEntryPointer;
                for (int i=1; i<categoryData.CounterNames.Count; i++) {
                    previousCounterEntryPointer = newCounterEntryPointer;
                    
                    newCounterEntryPointer++;
                    Debug.Assert(firstCounterInCategoryPointer->NextCounterOffset != 0, "The unique shared memory should have all of its counters created by the time we hit CreateInstance");
                    firstCounterInCategoryPointer = (CounterEntry*) ResolveOffset(firstCounterInCategoryPointer->NextCounterOffset, CounterEntrySize);
                    newCounterEntryPointer->CounterNameHashCode = firstCounterInCategoryPointer->CounterNameHashCode;
                    SetValue(newCounterEntryPointer, 0);
                    newCounterEntryPointer->CounterNameOffset = firstCounterInCategoryPointer->CounterNameOffset;

                    previousCounterEntryPointer->NextCounterOffset = (int)((long)newCounterEntryPointer - baseAddress);
                }
            }
            else {
                // now create the rest of the CounterEntrys
                CounterEntry* previousCounterEntryPointer = null;
                for (int i=0; i<categoryData.CounterNames.Count; i++) {
                    string counterName = (string) categoryData.CounterNames[i];
                    newCounterEntryPointer->CounterNameHashCode = GetWstrHashCode(counterName);
                    newCounterEntryPointer->CounterNameOffset = (int) (nextPtr - baseAddress);
                    SafeMarshalCopy(counterName, (IntPtr)nextPtr);
                    nextPtr += (counterName.Length + 1) * 2;

                    SetValue(newCounterEntryPointer, 0);

                    if (i != 0)
                        previousCounterEntryPointer->NextCounterOffset = (int)((long)newCounterEntryPointer - baseAddress);

                    previousCounterEntryPointer = newCounterEntryPointer;
                    newCounterEntryPointer++;
                }
            }
            
            Debug.Assert(nextPtr - baseAddress == freeMemoryOffset + totalSize, "We should have used all of the space we requested at this point");

            int offset = (int) ((long) newInstanceEntryPointer - baseAddress);
            categoryPointer->IsConsistent = 0;
            
            // prepend the new instance rather than append, helps with perf of hooking up subsequent counters 
            newInstanceEntryPointer->NextInstanceOffset = categoryPointer->FirstInstanceOffset;
            categoryPointer->FirstInstanceOffset = offset;

            if (categoryData.UseUniqueSharedMemory) {
                *((int*) baseAddress) = newOffset;
                categoryPointer->IsConsistent = 1;
            }

            return freeMemoryOffset;
        }
 private unsafe void Verify(CategoryEntry* currentCategoryPointer) {
     if (!categoryData.UseUniqueSharedMemory)
         return;
     
     Mutex mutex = null;
     RuntimeHelpers.PrepareConstrainedRegions();
     try {
         SharedUtils.EnterMutexWithoutGlobal(categoryData.MutexName, ref mutex);               
         VerifyCategory(currentCategoryPointer);
     }
     finally {
         if (mutex != null) {
             mutex.ReleaseMutex();
             mutex.Close();
         }
     }
  }
        private unsafe void VerifyCategory(CategoryEntry* currentCategoryPointer) {
            int freeOffset = *((int*)baseAddress);
            ResolveOffset(freeOffset, 0);        // verify next free offset

            // begin by verifying the head node's offset
            int currentOffset = ResolveAddress((long)currentCategoryPointer, CategoryEntrySize);
            if (currentOffset >= freeOffset) {
                // zero out the bad head node entry
                currentCategoryPointer->SpinLock             = 0;
                currentCategoryPointer->CategoryNameHashCode = 0;
                currentCategoryPointer->CategoryNameOffset   = 0;
                currentCategoryPointer->FirstInstanceOffset  = 0;
                currentCategoryPointer->NextCategoryOffset   = 0;
                currentCategoryPointer->IsConsistent         = 0;
                return;
            }

            if (currentCategoryPointer->NextCategoryOffset > freeOffset)
                currentCategoryPointer->NextCategoryOffset = 0;
            else if (currentCategoryPointer->NextCategoryOffset != 0)
                VerifyCategory((CategoryEntry*) ResolveOffset(currentCategoryPointer->NextCategoryOffset, CategoryEntrySize));

            if (currentCategoryPointer->FirstInstanceOffset != 0) {
                // In V3, we started prepending the new instances rather than appending (as in V2) for performance.
                // Check whether the recently added instance at the head of the list is committed. If not, rewire 
                // the head of the list to point to the next instance 
                if (currentCategoryPointer->FirstInstanceOffset > freeOffset) {
                    InstanceEntry* currentInstancePointer = (InstanceEntry*) ResolveOffset(currentCategoryPointer->FirstInstanceOffset, InstanceEntrySize);
                    currentCategoryPointer->FirstInstanceOffset = currentInstancePointer->NextInstanceOffset; 
                    if (currentCategoryPointer->FirstInstanceOffset > freeOffset)
                        currentCategoryPointer->FirstInstanceOffset = 0;
                }
                // 




                if (currentCategoryPointer->FirstInstanceOffset != 0) {
                    Debug.Assert(currentCategoryPointer->FirstInstanceOffset <= freeOffset, "The head of the list is inconsistent - possible mismatch of V2 & V3 instances?");
                    VerifyInstance((InstanceEntry*) ResolveOffset(currentCategoryPointer->FirstInstanceOffset, InstanceEntrySize));
                }
            }
           
            currentCategoryPointer->IsConsistent = 1;
        }
 private unsafe bool FindInstance(int instanceNameHashCode, string instanceName, CategoryEntry* categoryPointer, InstanceEntry** returnInstancePointerReference, bool activateUnusedInstances, PerformanceCounterInstanceLifetime lifetime, out bool foundFreeInstance)
 {
     bool flag3;
     InstanceEntry* currentInstancePointer = (InstanceEntry*) this.ResolveOffset(categoryPointer.FirstInstanceOffset, InstanceEntrySize);
     InstanceEntry* entryPtr2 = currentInstancePointer;
     foundFreeInstance = false;
     if (currentInstancePointer->InstanceNameHashCode == SingleInstanceHashCode)
     {
         if (!this.StringEquals("systemdiagnosticssharedsingleinstance", currentInstancePointer->InstanceNameOffset))
         {
             if (instanceName == "systemdiagnosticssharedsingleinstance")
             {
                 throw new InvalidOperationException(SR.GetString("MultiInstanceOnly", new object[] { this.categoryName }));
             }
         }
         else if (instanceName != "systemdiagnosticssharedsingleinstance")
         {
             throw new InvalidOperationException(SR.GetString("SingleInstanceOnly", new object[] { this.categoryName }));
         }
     }
     else if (instanceName == "systemdiagnosticssharedsingleinstance")
     {
         throw new InvalidOperationException(SR.GetString("MultiInstanceOnly", new object[] { this.categoryName }));
     }
     bool flag = activateUnusedInstances;
     if (activateUnusedInstances)
     {
         int num3;
         int totalSize = ((InstanceEntrySize + ProcessLifetimeEntrySize) + 0x100) + (CounterEntrySize * this.categoryData.CounterNames.Count);
         int oldOffset = *((int*) this.baseAddress);
         int num4 = this.CalculateMemoryNoBoundsCheck(oldOffset, totalSize, out num3);
         if ((num4 <= this.FileView.FileMappingSize) && (num4 >= 0))
         {
             long num5 = DateTime.Now.Ticks - LastInstanceLifetimeSweepTick;
             if (num5 < InstanceLifetimeSweepWindow)
             {
                 flag = false;
             }
         }
     }
     new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
     try
     {
         bool flag2;
     Label_0156:
         flag2 = false;
         if (flag && (currentInstancePointer->RefCount != 0))
         {
             flag2 = true;
             this.VerifyLifetime(currentInstancePointer);
         }
         if ((currentInstancePointer->InstanceNameHashCode == instanceNameHashCode) && this.StringEquals(instanceName, currentInstancePointer->InstanceNameOffset))
         {
             ProcessLifetimeEntry* entryPtr4;
             *((IntPtr*) returnInstancePointerReference) = currentInstancePointer;
             CounterEntry* entryPtr3 = (CounterEntry*) this.ResolveOffset(currentInstancePointer->FirstCounterOffset, CounterEntrySize);
             if (this.categoryData.UseUniqueSharedMemory)
             {
                 entryPtr4 = (ProcessLifetimeEntry*) this.ResolveOffset(entryPtr3->LifetimeOffset, ProcessLifetimeEntrySize);
             }
             else
             {
                 entryPtr4 = null;
             }
             if (!flag2 && (currentInstancePointer->RefCount != 0))
             {
                 this.VerifyLifetime(currentInstancePointer);
             }
             if (currentInstancePointer->RefCount != 0)
             {
                 if ((entryPtr4 != null) && (entryPtr4->ProcessId != 0))
                 {
                     if (lifetime != PerformanceCounterInstanceLifetime.Process)
                     {
                         throw new InvalidOperationException(SR.GetString("CantConvertProcessToGlobal"));
                     }
                     if (ProcessData.ProcessId != entryPtr4->ProcessId)
                     {
                         throw new InvalidOperationException(SR.GetString("InstanceAlreadyExists", new object[] { instanceName }));
                     }
                     if (((entryPtr4->StartupTime != -1L) && (ProcessData.StartupTime != -1L)) && (ProcessData.StartupTime != entryPtr4->StartupTime))
                     {
                         throw new InvalidOperationException(SR.GetString("InstanceAlreadyExists", new object[] { instanceName }));
                     }
                 }
                 else if (lifetime == PerformanceCounterInstanceLifetime.Process)
                 {
                     throw new InvalidOperationException(SR.GetString("CantConvertGlobalToProcess"));
                 }
                 return true;
             }
             if (activateUnusedInstances)
             {
                 Mutex mutex = null;
                 RuntimeHelpers.PrepareConstrainedRegions();
                 try
                 {
                     SharedUtils.EnterMutexWithoutGlobal(this.categoryData.MutexName, ref mutex);
                     this.ClearCounterValues(currentInstancePointer);
                     if (entryPtr4 != null)
                     {
                         PopulateLifetimeEntry(entryPtr4, lifetime);
                     }
                     currentInstancePointer->RefCount = 1;
                     return true;
                 }
                 finally
                 {
                     if (mutex != null)
                     {
                         mutex.ReleaseMutex();
                         mutex.Close();
                     }
                 }
             }
             return false;
         }
         if (currentInstancePointer->RefCount == 0)
         {
             foundFreeInstance = true;
         }
         entryPtr2 = currentInstancePointer;
         if (currentInstancePointer->NextInstanceOffset != 0)
         {
             currentInstancePointer = (InstanceEntry*) this.ResolveOffset(currentInstancePointer->NextInstanceOffset, InstanceEntrySize);
             goto Label_0156;
         }
         *((IntPtr*) returnInstancePointerReference) = entryPtr2;
         flag3 = false;
     }
     finally
     {
         CodeAccessPermission.RevertAssert();
         if (flag)
         {
             LastInstanceLifetimeSweepTick = DateTime.Now.Ticks;
         }
     }
     return flag3;
 }
        private unsafe bool TryReuseInstance(int instanceNameHashCode, string instanceName, 
                                               CategoryEntry* categoryPointer, InstanceEntry** returnInstancePointerReference, 
                                               PerformanceCounterInstanceLifetime lifetime,
                                               InstanceEntry* lockInstancePointer) {
            //
            // 2nd pass find a free instance slot
            // 
            InstanceEntry* currentInstancePointer = (InstanceEntry*)(ResolveOffset(categoryPointer->FirstInstanceOffset, InstanceEntrySize));
            InstanceEntry* previousInstancePointer = currentInstancePointer;
            for (;;) {
                if (currentInstancePointer->RefCount == 0) {

                    bool hasFit;
                    long instanceNamePtr;       // we need cache this to avoid race conditions. 
                    
                    if (categoryData.UseUniqueSharedMemory) {
                        instanceNamePtr = ResolveOffset(currentInstancePointer->InstanceNameOffset, InstanceNameSlotSize);
                        // In the separate shared memory case we should always have enough space for instances.  The
                        // name slot size is fixed. 
                        Debug.Assert(((instanceName.Length + 1) * 2) <= InstanceNameSlotSize, "The instance name length should always fit in our slot size");
                        hasFit = true;
                    }
                    else {
                        // we don't know the string length yet. 
                        instanceNamePtr = ResolveOffset(currentInstancePointer->InstanceNameOffset, 0);

                        // In the global shared memory, we require names to be exactly the same length in order
                        // to reuse them.  This way we don't end up leaking any space and we don't need to 
                        // depend on the layout of the memory to calculate the space we have. 
                        int length = GetStringLength((char*) instanceNamePtr);
                        hasFit = (length == instanceName.Length);
                    }

                    bool noSpinLock = (lockInstancePointer == currentInstancePointer) || categoryData.UseUniqueSharedMemory;
                    // Instance name fit
                    if (hasFit) {
                        // don't bother locking again if we're using a separate shared memory.  
                        bool sectionEntered;
                        if (noSpinLock)
                            sectionEntered = true;
                        else
                            WaitAndEnterCriticalSection(&(currentInstancePointer->SpinLock), out sectionEntered);

                        if (sectionEntered) {
                            try {
                                // Make copy with zero-term
                                SafeMarshalCopy(instanceName, (IntPtr)instanceNamePtr);
                                currentInstancePointer->InstanceNameHashCode = instanceNameHashCode;

                                // return
                                *returnInstancePointerReference = currentInstancePointer;
                                // clear the counter values. 
                                ClearCounterValues(*returnInstancePointerReference);

                                if (categoryData.UseUniqueSharedMemory) {
                                    CounterEntry* counterPointer = (CounterEntry*)ResolveOffset(currentInstancePointer->FirstCounterOffset, CounterEntrySize);
                                    ProcessLifetimeEntry* lifetimeEntry = (ProcessLifetimeEntry*) ResolveOffset(counterPointer->LifetimeOffset, ProcessLifetimeEntrySize);
                                    PopulateLifetimeEntry(lifetimeEntry, lifetime);
                                }
                                
                                (*returnInstancePointerReference)->RefCount = 1;
                                return true;
                            }
                            finally {
                                if (!noSpinLock)
                                    ExitCriticalSection(&(currentInstancePointer->SpinLock));
                            }
                        }
                    }
                 }
            
                previousInstancePointer = currentInstancePointer;
                if (currentInstancePointer->NextInstanceOffset != 0)
                    currentInstancePointer = (InstanceEntry*)(ResolveOffset(currentInstancePointer->NextInstanceOffset, InstanceEntrySize));
                else
                {
                    *returnInstancePointerReference = previousInstancePointer;
                    return false;
                }
            }
        }
 private unsafe bool FindCategory(CategoryEntry** returnCategoryPointerReference)
 {
     CategoryEntry* entryPtr = (CategoryEntry*) this.ResolveOffset(this.InitialOffset, CategoryEntrySize);
     CategoryEntry* currentCategoryPointer = entryPtr;
     CategoryEntry* entryPtr3 = entryPtr;
 Label_0017:
     if (currentCategoryPointer->IsConsistent == 0)
     {
         this.Verify(currentCategoryPointer);
     }
     if ((currentCategoryPointer->CategoryNameHashCode == this.categoryNameHashCode) && this.StringEquals(this.categoryName, currentCategoryPointer->CategoryNameOffset))
     {
         *((IntPtr*) returnCategoryPointerReference) = currentCategoryPointer;
         return true;
     }
     entryPtr3 = currentCategoryPointer;
     if (currentCategoryPointer->NextCategoryOffset != 0)
     {
         currentCategoryPointer = (CategoryEntry*) this.ResolveOffset(currentCategoryPointer->NextCategoryOffset, CategoryEntrySize);
         goto Label_0017;
     }
     *((IntPtr*) returnCategoryPointerReference) = entryPtr3;
     return false;
 }
 private unsafe int CreateInstance(CategoryEntry* categoryPointer, int instanceNameHashCode, string instanceName, PerformanceCounterInstanceLifetime lifetime)
 {
     int num;
     int num3;
     int num4;
     int totalSize = InstanceEntrySize + (CounterEntrySize * this.categoryData.CounterNames.Count);
     int num5 = 0;
     if (this.categoryData.UseUniqueSharedMemory)
     {
         num = 0x100;
         totalSize += ProcessLifetimeEntrySize + num;
         num4 = *((int*) this.baseAddress);
         num5 = this.CalculateMemory(num4, totalSize, out num3);
     }
     else
     {
         num = (instanceName.Length + 1) * 2;
         totalSize += num;
         for (int i = 0; i < this.categoryData.CounterNames.Count; i++)
         {
             totalSize += (((string) this.categoryData.CounterNames[i]).Length + 1) * 2;
         }
         num4 = this.CalculateAndAllocateMemory(totalSize, out num3);
     }
     num4 += num3;
     long num7 = this.ResolveOffset(num4, totalSize);
     InstanceEntry* entryPtr = (InstanceEntry*) num7;
     num7 += InstanceEntrySize;
     CounterEntry* counterEntry = (CounterEntry*) num7;
     num7 += CounterEntrySize * this.categoryData.CounterNames.Count;
     if (this.categoryData.UseUniqueSharedMemory)
     {
         ProcessLifetimeEntry* lifetimeEntry = (ProcessLifetimeEntry*) num7;
         num7 += ProcessLifetimeEntrySize;
         counterEntry->LifetimeOffset = (int) (((ulong) lifetimeEntry) - this.baseAddress);
         PopulateLifetimeEntry(lifetimeEntry, lifetime);
     }
     entryPtr->InstanceNameHashCode = instanceNameHashCode;
     entryPtr->NextInstanceOffset = 0;
     entryPtr->FirstCounterOffset = (int) (((ulong) counterEntry) - this.baseAddress);
     entryPtr->RefCount = 1;
     entryPtr->InstanceNameOffset = (int) (num7 - this.baseAddress);
     SafeMarshalCopy(instanceName, (IntPtr) num7);
     num7 += num;
     if (this.categoryData.UseUniqueSharedMemory)
     {
         InstanceEntry* entryPtr4 = (InstanceEntry*) this.ResolveOffset(categoryPointer.FirstInstanceOffset, InstanceEntrySize);
         CounterEntry* entryPtr5 = (CounterEntry*) this.ResolveOffset(entryPtr4->FirstCounterOffset, CounterEntrySize);
         counterEntry->CounterNameHashCode = entryPtr5->CounterNameHashCode;
         SetValue(counterEntry, 0L);
         counterEntry->CounterNameOffset = entryPtr5->CounterNameOffset;
         for (int j = 1; j < this.categoryData.CounterNames.Count; j++)
         {
             CounterEntry* entryPtr6 = counterEntry;
             counterEntry++;
             entryPtr5 = (CounterEntry*) this.ResolveOffset(entryPtr5->NextCounterOffset, CounterEntrySize);
             counterEntry->CounterNameHashCode = entryPtr5->CounterNameHashCode;
             SetValue(counterEntry, 0L);
             counterEntry->CounterNameOffset = entryPtr5->CounterNameOffset;
             entryPtr6->NextCounterOffset = (int) (((ulong) counterEntry) - this.baseAddress);
         }
     }
     else
     {
         CounterEntry* entryPtr7 = null;
         for (int k = 0; k < this.categoryData.CounterNames.Count; k++)
         {
             string wstr = (string) this.categoryData.CounterNames[k];
             counterEntry->CounterNameHashCode = GetWstrHashCode(wstr);
             counterEntry->CounterNameOffset = (int) (num7 - this.baseAddress);
             SafeMarshalCopy(wstr, (IntPtr) num7);
             num7 += (wstr.Length + 1) * 2;
             SetValue(counterEntry, 0L);
             if (k != 0)
             {
                 entryPtr7->NextCounterOffset = (int) (((ulong) counterEntry) - this.baseAddress);
             }
             entryPtr7 = counterEntry;
             counterEntry++;
         }
     }
     int num10 = (int) (((ulong) entryPtr) - this.baseAddress);
     categoryPointer.IsConsistent = 0;
     entryPtr->NextInstanceOffset = categoryPointer.FirstInstanceOffset;
     categoryPointer.FirstInstanceOffset = num10;
     if (this.categoryData.UseUniqueSharedMemory)
     {
         this.baseAddress[0] = num5;
         categoryPointer.IsConsistent = 1;
     }
     return num4;
 }
 private unsafe int CreateCategory(CategoryEntry* lastCategoryPointer, int instanceNameHashCode, string instanceName, PerformanceCounterInstanceLifetime lifetime)
 {
     int num2;
     int num3;
     int num4;
     CategoryEntry* entryPtr;
     InstanceEntry* entryPtr2;
     int num5 = 0;
     int num = (this.categoryName.Length + 1) * 2;
     int totalSize = ((CategoryEntrySize + InstanceEntrySize) + (CounterEntrySize * this.categoryData.CounterNames.Count)) + num;
     for (int i = 0; i < this.categoryData.CounterNames.Count; i++)
     {
         totalSize += (((string) this.categoryData.CounterNames[i]).Length + 1) * 2;
     }
     if (this.categoryData.UseUniqueSharedMemory)
     {
         num2 = 0x100;
         totalSize += ProcessLifetimeEntrySize + num2;
         num4 = *((int*) this.baseAddress);
         num5 = this.CalculateMemory(num4, totalSize, out num3);
         if (num4 == this.InitialOffset)
         {
             lastCategoryPointer.IsConsistent = 0;
         }
     }
     else
     {
         num2 = (instanceName.Length + 1) * 2;
         totalSize += num2;
         num4 = this.CalculateAndAllocateMemory(totalSize, out num3);
     }
     long num8 = this.ResolveOffset(num4, totalSize + num3);
     if (num4 == this.InitialOffset)
     {
         entryPtr = (CategoryEntry*) num8;
         num8 += CategoryEntrySize + num3;
         entryPtr2 = (InstanceEntry*) num8;
     }
     else
     {
         num8 += num3;
         entryPtr = (CategoryEntry*) num8;
         num8 += CategoryEntrySize;
         entryPtr2 = (InstanceEntry*) num8;
     }
     num8 += InstanceEntrySize;
     CounterEntry* counterEntry = (CounterEntry*) num8;
     num8 += CounterEntrySize * this.categoryData.CounterNames.Count;
     if (this.categoryData.UseUniqueSharedMemory)
     {
         ProcessLifetimeEntry* lifetimeEntry = (ProcessLifetimeEntry*) num8;
         num8 += ProcessLifetimeEntrySize;
         counterEntry->LifetimeOffset = (int) (((ulong) lifetimeEntry) - this.baseAddress);
         PopulateLifetimeEntry(lifetimeEntry, lifetime);
     }
     entryPtr->CategoryNameHashCode = this.categoryNameHashCode;
     entryPtr->NextCategoryOffset = 0;
     entryPtr->FirstInstanceOffset = (int) (((ulong) entryPtr2) - this.baseAddress);
     entryPtr->CategoryNameOffset = (int) (num8 - this.baseAddress);
     SafeMarshalCopy(this.categoryName, (IntPtr) num8);
     num8 += num;
     entryPtr2->InstanceNameHashCode = instanceNameHashCode;
     entryPtr2->NextInstanceOffset = 0;
     entryPtr2->FirstCounterOffset = (int) (((ulong) counterEntry) - this.baseAddress);
     entryPtr2->RefCount = 1;
     entryPtr2->InstanceNameOffset = (int) (num8 - this.baseAddress);
     SafeMarshalCopy(instanceName, (IntPtr) num8);
     num8 += num2;
     string wstr = (string) this.categoryData.CounterNames[0];
     counterEntry->CounterNameHashCode = GetWstrHashCode(wstr);
     SetValue(counterEntry, 0L);
     counterEntry->CounterNameOffset = (int) (num8 - this.baseAddress);
     SafeMarshalCopy(wstr, (IntPtr) num8);
     num8 += (wstr.Length + 1) * 2;
     for (int j = 1; j < this.categoryData.CounterNames.Count; j++)
     {
         CounterEntry* entryPtr5 = counterEntry;
         wstr = (string) this.categoryData.CounterNames[j];
         counterEntry++;
         counterEntry->CounterNameHashCode = GetWstrHashCode(wstr);
         SetValue(counterEntry, 0L);
         counterEntry->CounterNameOffset = (int) (num8 - this.baseAddress);
         SafeMarshalCopy(wstr, (IntPtr) num8);
         num8 += (wstr.Length + 1) * 2;
         entryPtr5->NextCounterOffset = (int) (((ulong) counterEntry) - this.baseAddress);
     }
     int num10 = (int) (((ulong) entryPtr) - this.baseAddress);
     lastCategoryPointer.IsConsistent = 0;
     if (num10 != this.InitialOffset)
     {
         lastCategoryPointer.NextCategoryOffset = num10;
     }
     if (this.categoryData.UseUniqueSharedMemory)
     {
         this.baseAddress[0] = num5;
         lastCategoryPointer.IsConsistent = 1;
     }
     return num10;
 }
 private unsafe void VerifyCategory(CategoryEntry* currentCategoryPointer)
 {
     int offset = *((int*) this.baseAddress);
     this.ResolveOffset(offset, 0);
     if (this.ResolveAddress((long) ((ulong) currentCategoryPointer), CategoryEntrySize) >= offset)
     {
         currentCategoryPointer.SpinLock = 0;
         currentCategoryPointer.CategoryNameHashCode = 0;
         currentCategoryPointer.CategoryNameOffset = 0;
         currentCategoryPointer.FirstInstanceOffset = 0;
         currentCategoryPointer.NextCategoryOffset = 0;
         currentCategoryPointer.IsConsistent = 0;
     }
     else
     {
         if (currentCategoryPointer.NextCategoryOffset > offset)
         {
             currentCategoryPointer.NextCategoryOffset = 0;
         }
         else if (currentCategoryPointer.NextCategoryOffset != 0)
         {
             this.VerifyCategory((CategoryEntry*) this.ResolveOffset(currentCategoryPointer.NextCategoryOffset, CategoryEntrySize));
         }
         if (currentCategoryPointer.FirstInstanceOffset != 0)
         {
             if (currentCategoryPointer.FirstInstanceOffset > offset)
             {
                 InstanceEntry* entryPtr = (InstanceEntry*) this.ResolveOffset(currentCategoryPointer.FirstInstanceOffset, InstanceEntrySize);
                 currentCategoryPointer.FirstInstanceOffset = entryPtr->NextInstanceOffset;
                 if (currentCategoryPointer.FirstInstanceOffset > offset)
                 {
                     currentCategoryPointer.FirstInstanceOffset = 0;
                 }
             }
             if (currentCategoryPointer.FirstInstanceOffset != 0)
             {
                 this.VerifyInstance((InstanceEntry*) this.ResolveOffset(currentCategoryPointer.FirstInstanceOffset, InstanceEntrySize));
             }
         }
         currentCategoryPointer.IsConsistent = 1;
     }
 }
 private unsafe bool TryReuseInstance(int instanceNameHashCode, string instanceName, CategoryEntry* categoryPointer, InstanceEntry** returnInstancePointerReference, PerformanceCounterInstanceLifetime lifetime, InstanceEntry* lockInstancePointer)
 {
     InstanceEntry* entryPtr = (InstanceEntry*) this.ResolveOffset(categoryPointer.FirstInstanceOffset, InstanceEntrySize);
     InstanceEntry* entryPtr2 = entryPtr;
 Label_0015:
     if (entryPtr->RefCount == 0)
     {
         bool flag;
         long num;
         if (this.categoryData.UseUniqueSharedMemory)
         {
             num = this.ResolveOffset(entryPtr->InstanceNameOffset, 0x100);
             flag = true;
         }
         else
         {
             num = this.ResolveOffset(entryPtr->InstanceNameOffset, 0);
             flag = this.GetStringLength((char*) num) == instanceName.Length;
         }
         bool flag2 = (lockInstancePointer == entryPtr) || this.categoryData.UseUniqueSharedMemory;
         if (flag)
         {
             bool flag3;
             if (flag2)
             {
                 flag3 = true;
             }
             else
             {
                 WaitAndEnterCriticalSection(&entryPtr->SpinLock, out flag3);
             }
             if (flag3)
             {
                 try
                 {
                     SafeMarshalCopy(instanceName, (IntPtr) num);
                     entryPtr->InstanceNameHashCode = instanceNameHashCode;
                     *((IntPtr*) returnInstancePointerReference) = entryPtr;
                     this.ClearCounterValues(returnInstancePointerReference[0]);
                     if (this.categoryData.UseUniqueSharedMemory)
                     {
                         CounterEntry* entryPtr3 = (CounterEntry*) this.ResolveOffset(entryPtr->FirstCounterOffset, CounterEntrySize);
                         ProcessLifetimeEntry* lifetimeEntry = (ProcessLifetimeEntry*) this.ResolveOffset(entryPtr3->LifetimeOffset, ProcessLifetimeEntrySize);
                         PopulateLifetimeEntry(lifetimeEntry, lifetime);
                     }
                     *(((IntPtr*) returnInstancePointerReference)).RefCount = 1;
                     return true;
                 }
                 finally
                 {
                     if (!flag2)
                     {
                         ExitCriticalSection(&entryPtr->SpinLock);
                     }
                 }
             }
         }
     }
     entryPtr2 = entryPtr;
     if (entryPtr->NextInstanceOffset != 0)
     {
         entryPtr = (InstanceEntry*) this.ResolveOffset(entryPtr->NextInstanceOffset, InstanceEntrySize);
         goto Label_0015;
     }
     *((IntPtr*) returnInstancePointerReference) = entryPtr2;
     return false;
 }