I keep getting an AccessViolationException when calling the following from an external DLL:
FILES_GetMemoryMapping(MapFile, out size, MapName, out PacketSize, pMapping, out PagePerSector);
Which has a prototype that I've setup as such:
[DllImport("Files.DLL", SetLastError = true)]
public static extern uint FILES_GetMemoryMapping(
[MarshalAs(UnmanagedType.LPStr)]
string pPathFile,
out ushort Size,
[MarshalAs(UnmanagedType.LPStr)]
string MapName,
out ushort PacketSize,
IntPtr pMapping,
out byte PagesPerSector);
Now, the argument that is causing this is most likely the 5th one (IntPtr pMapping). I've ported this code over from a C++ app into C#. The 5th argument above is a pointer to a struct which also contains a pointer to another struct. Below is how I have these sctructs setup:
[StructLayout(LayoutKind.Sequential)]
public struct MappingSector
{
[MarshalAs(UnmanagedType.LPStr)]
public string Name;
public uint dwStartAddress;
public uint dwAliasedAddress;
public uint dwSectorIndex;
public uint dwSectorSize;
public byte bSectorType;
public bool UseForOperation;
public bool UseForErase;
public bool UseForUpload;
public bool UseForWriteProtect;
}
[StructLayout(LayoutKind.Sequential)]
public struct Mapping
{
public byte nAlternate;
[MarshalAs(UnmanagedType.LPStr, SizeConst=260)]
public string Name;
public uint NbSectors;
public IntPtr pSectors;
}
The C++ equivalent of these are as follows:
typedef struct {
char* Name;
DWORD dwStartAddress;
DWORD dwAliasedAddress;
DWORD dwSectorIndex;
DWORD dwSectorSize;
BYTE bSectorType;
BOOL UseForOperation;
BOOL UseForErase;
BOOL UseForUpload;
BOOL UseForWriteProtect;
} MAPPINGSECTOR, *PMAPPINGSECTOR;
typedef struct {
BYTE nAlternate;
char Name[MAX_PATH]; // MAX_PATH = 260
DWORD NbSectors;
PMAPPINGSECTOR pSectors;
} MAPPING, *PMAPPING;
I have a feeling I did something wrong with either porting over these structs, or porting over the function prototype. A Marshaling issue of somesort.
The function all the way at the top of this post gets called twice in my code. Once with pMapping set to null (this puts a value in "size"). Memory is then allocated for a new struct using this size parameter and the function is called again now using a pointer to this allocated memory space for pMapping. (pMapping also has a pointer for the other struct which also gets some space allocated during this time).
Here is the old c++ code that accomplished this:
FILES_GetMemoryMapping((LPSTR)(LPCTSTR)MapFile, &Size, (LPSTR)MapName, &PacketSize, pMapping, &PagePerSector);
// Allocate the mapping structure memory
pMapping = (PMAPPING)malloc(sizeof(MAPPING));
pMapping->NbSectors = 0;
pMapping->pSectors = (PMAPPINGSECTOR) malloc((Size) * sizeof(MAPPINGSECTOR));
printf("mapsectorsize: <%d>\n", football);
printf("pMappingsize: <%d>\n", f2);
// Get the mapping info
FILES_GetMemoryMapping((LPSTR)(LPCTSTR)MapFile, &Size, (LPSTR)(LPCTSTR)MapName, &PacketSize, pMapping, &PagePerSector);
I initially thought I wasn't allocating the correct amount of space so I tried the old C++ code above and found out that:
sizeof(MAPPING) = 272
and
sizeof(PMAPPINGSECTOR) = 40
I did the same check in my C# code and found the following:
Marshal.SizeOf(new Mapping()) = 16
and
Marshal.SizeOF(new MappingSector()) = 40
We got a problem here. The Mapping struct should be of size 272, but its only 16. Thinking I could just do a quick fix, I manually allocated 272 instead of 16 here, but it still errored out with an AccessViolationException.
Any idea on how to fix this? Or what might still be going wrong?