/// <summary> /// Retrieves a DsObject structure from the "array" in our DsObjectNames structure. /// Because marshalling cannot properly marshal a nested, variable sized /// array in a struct, we have to do this the hard way. /// That is, the "array" of DsObjects that's in our managed DsObjectNames structure /// definition is merely a pointer to a big chunk of data that we have to manually /// retrieve DsObjects from by manipulating pointers, rather than doing aObjects[i]. /// </summary> /// <param name="index">The index of the DsObject to retrieve</param> /// <returns></returns> private UnsafeNativeMethods.DsObject GetDsObjectForIndex(int index) { ThrowIfDisposed(); //Ensure we're within proper bounds. if (index < 0 || index >= Count) { throw new ArgumentOutOfRangeException("index"); } //Now we calculate the offset of the specified array index. //This is the address of the first element in the array, plus //the number of entries past that times the size of an entry, or: //offset = StartOfStructAddress + FirstArrayEntryOffset + index * SizeOfEntry IntPtr offset = new IntPtr(_ptrToDsObjectNames.ToInt64() + _dsObjectArrayFieldOffset + index * _sizeOfDsObject); //Marshal that to a DsObject structure. UnsafeNativeMethods.DsObject dsObject = (UnsafeNativeMethods.DsObject)Marshal.PtrToStructure(offset, typeof(UnsafeNativeMethods.DsObject)); return dsObject; }
/// <summary> /// Extracts the name for the specified entry number from the DsObjectNames data /// </summary> /// <param name="index">The index of the name to retrieve</param> /// <returns></returns> private String BuildStringForItemName(int index) { ThrowIfDisposed(); //Ensure we're within proper bounds. if (index < 0 || index >= Count) { throw new ArgumentOutOfRangeException("index"); } //First we have to get a DsObject out of the array (aObjects) of DsObjects. //The information in this struct will tell us where to find the name data //we want. UnsafeNativeMethods.DsObject dsObject = GetDsObjectForIndex(index); //The offset of the name from the start of the DsObjectNames structure is stored in //the corresponding DsObject's offsetName field, so the pointer to the beginning of the //string can be computed as: // // offset = StartOfStructAddress + dsObject.offsetName; IntPtr nameOffset = new IntPtr(_ptrToDsObjectNames.ToInt64() + dsObject.offsetName); //We marshal this pointer to a string and return it. return Marshal.PtrToStringAuto(nameOffset); }