How to call WFSStartUp via C# application - c#

I use this code for call WFSStartUp via C# program
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public unsafe struct WFSVERSION
{
public ushort wVersion;
public ushort wLowVersion;
public ushort wHighVersion;
public fixed char szDescription[256 + 1];
public fixed char szSystemStatus[256 + 1];
}
[DllImport("msxfs.dll", CharSet = CharSet.Ansi, CallingConvention = XFSConstants.CALLINGCONVENTION)]
public static extern int WFSStartUp(int dwVersionsRequired, ref WFSVERSION lpWFSVersion);
WFSVERSION m_Version = new WFSVERSION();
int requestVersion = 0x00010202;
int hResult = WFSStartUp(requestVersion, ref m_Version);
the return value hResult is Ok but m_Version.szDescription not correct (m_Version.szDescription[0] = 'W', m_Version.szDescription[1] = 0, ...)
How to solve this problem?

Related

call C dll from C# complex structure

I have c dll came from outside of our group.
#pragma pack(push, 8)
typedef struct
{
int int1;
int int2;
int int3;
int int4;
int int5;
int int6;
int int_array1[250];
int int_array2[250];
int int_array3[250];
int int_array4[250];
int int_array5[250];
int int_array6[250];
}my_structure
#pragma pack(pop)
extern "C" {
__declspec(dllexport) void set_my_structure(my_structure mystruct);
__declspec(dllexport) my_structure get_my_structure();
}
I am using the following code to call the dll from C#.
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public class MyStructure
{
public int int1;
public int int2;
public int int3;
public int int4;
public int int5;
public int int6;
public int[] int_array1 = new int[250];
public int[] int_array2 = new int[250];
public int[] int_array3 = new int[250];
public int[] int_array4 = new int[250];
public int[] int_array5 = new int[250];
public int[] int_array6 = new int[250];
}
[DllImport(_dllName, EntryPoint = "set_my_structure", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
public static extern void SetMyStructure(MyStructure data);
[DllImport(_dllName, EntryPoint = "get_my_structure", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
public static extern MyStructure GetMyStructure();
However, the code throws exception and stuck in neutral gear when I call GetMyStructure method. What is wrong? What is the best approach to handle this?

Marshalling array of structures from c++ to c# in WinCE

I'm trying to Marshal the following structures from c++ to c# on a Windows CE program and compact framework 2.0. I'm having a lot of difficulties with the marshalling of strings.
I have this c++ code:
#define Console_Parameters_MAX 50
struct AllParameters {
Parameter Parameters[Console_Parameters_MAX];
} ;
struct Parameter {
int Index;
int Id;
char Value[20];
};
extern "C" {
BOOL GetAllConsoleParameters(AllParameters *pItem);
}
and this are the corresponding c# code:
[StructLayout(LayoutKind.Sequential)]
public struct AllParameters {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
public Parameter[] Parameters
}
[StructLayout(LayoutKind.Sequential)]
public struct Parameter {
public int Index;
public int Id;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public byte[] Value;
}
[DllImport("exemple.dll", SetLastError = true)]
public static extern bool GetAllConsoleParameters([MarshalAs(UnmanagedType.Struct)] ref AllParameters pItem);
and this is how I invoke it:
AllParameters item = new AllParameters();
if (AppAPI.GetAllConsoleParameters(ref item)) {
var array = item.Parameters;
}
When I call the GetAllConsoleParameters I get exception NotSupportedException. I've tried many configurations but with no success.
Can anyone advise on how to achieve it?
Thanks in advance
This works for me on a Windows Desktop. You might have to change the calling convention to Cdecl in the C DLL and the C# DllImport attribute, because I read here that Cdecl is standard on Windows CE: https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.callingconvention(v=vs.110).aspx
C code:
extern "C" {
__declspec(dllexport) BOOL __stdcall GetAllConsoleParameters(AllParameters *pItem)
{
pItem->Parameters[0].Index = 0;
pItem->Parameters[0].Id = 42;
CopyMemory(&pItem->Parameters[0].Value[0], "Hello World", 12);
pItem->Parameters[1].Index = 1;
pItem->Parameters[1].Id = 43;
CopyMemory(&pItem->Parameters[1].Value[0], "Hello World 43", 15);
return TRUE;
}
}
C# code:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct Parameter
{
int Index;
int Id;
//char Value[20];
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
string Value;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct AllParameters
{
//Parameter Parameters[Console_Parameters_MAX];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
Parameter[] Parameters;
};
class Program
{
[DllImport("MarshalC.dll", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetAllConsoleParameters(ref AllParameters pItem);
static void Main(string[] args)
{
var size = Marshal.SizeOf<AllParameters>();
AllParameters all = new AllParameters();
bool result = GetAllConsoleParameters(ref all);
}
}
I would do it like this
[StructLayout(LayoutKind.Sequential)]
public struct AllParameters {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
public Parameter[] Parameters;
}
[StructLayout(LayoutKind.Sequential)]
public struct Parameter {
public int Index;
public int Id;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] Value;
}
[DllImport("exemple.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
public static extern bool GetAllConsoleParameters(ref IntPtr pItem);
static void Main(string[] args)
{
AllParameters allParameters = new AllParameters();
allParameters.Parameters = new Parameter[50];
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(allParameters));
int z = Marshal.SizeOf(allParameters);
if (GetAllConsoleParameters(ref ptr))
{
Marshal.PtrToStructure(ptr, allParameters);
Parameter[] parameters = allParameters.Parameters;
}
}
following my solution, c++ code:
/* - not used
#define Console_Parameters_MAX 50
struct AllParameters {
Parameter Parameters[Console_Parameters_MAX];
} ;
*/
struct Parameter {
int Index;
int Id;
char Value[20];
};
extern "C" {
BOOL GetAllConsoleParameters(Parameter pItem[], int size);
}
and corresponding c# code:
/* - not used
[StructLayout(LayoutKind.Sequential)]
public struct AllParameters {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
public Parameter[] Parameters
}
*/
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Parameter {
public int Index;
public int Id;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] Value;
}
[DllImport("exemple.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool GetAllConsoleParameters([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] ConsoleParameter[] myStruct, int size);
and code invoke:
ConsoleParameter[] item = new ConsoleParameter[50];
if (AppAPI.GetAllConsoleParameters(item, 50)) {
var array = item;
}
thanks a lot for help

Access Violation Error when calling a function with struct parameter from C-DLL in C#

I got following definition for a function in a c-based DLL (no source available):
uint MakeReference(MemBlock* ipReferenceMemBlock);
MemBlock is defined as:
typedef struct {
HANDLE_TAG dTag;
long dLength;
BYTE* dpReference;
} MemBlock;
HANDLE_TAG is defined as:
typedef char HANDLE_TAG[10 + 1];
My take on this in a C# Wrapper Class is:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MemBlock
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string dTag;
public uint dLength;
[MarshalAs(UnmanagedType.LPStr)]
public string dpReference;
}
[DllImport("lib.dll", CharSet = CharSet.Ansi, EntryPoint = "MakeReference#24", CallingConvention = CallingConvention.StdCall)]
public static extern uint MakeReference(ref IntPtr pDDipMemBlock);
public static uint FAPIMakeReference(ref MemBlock ipMemBlock)
{
uint error = 0;
IntPtr pDDipMemBlock = Marshal.AllocHGlobal(Marshal.SizeOf(ipMemBlock));
try
{
Marshal.StructureToPtr(ipMemBlock, pDDipMemBlock, false);
error = MakeReferenceEx(ref pDDipMemBlock);
ipMemBlock = (MemBlock)Marshal.PtrToStructure(pDDipMemBlock, typeof(MemBlock));
}
finally
{
Marshal.FreeHGlobal(pDDipMemBlock);
}
return error;
}
calling this with:
MemBlock refMemBlock = new MemBlock();
uint error = MakeReferenceEx(ref refMemBlock);
resulting in an Access Violation Expection

How to marshal WCHAR* in C#

I'm trying to pinvoke a function that receives a couple of WCHAR <paramName>[1] parameters.
From what I've read in multiple places, in C/C++ you can't actually pass arrays to functions, instead they get converted to a pointer holding the first element of the array, which means that the array length becomes irrelevant and therefore WCHAR <paramName>[1] is the same as WCHAR* <paramName>.
So normally I'd declare this as a StringBuilder in C# and marshal it as LPWStr, but in this particular case that throws all sorts of errors.
Basically, the function above receives a GET_VIRTUAL_DISK_INFO, which in turn holds a union of some structs and other loose fields. And it is a couple of the structs in the union that receive a WCHAR <paramName>[1].
When I try to marshal it as LPWStr and declare my field as StringBuilder or string I get the error [...] contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field.
I've also tried declaring it as an IntPtr and then using Marshal.PtrToStringAuto(<IntPtr>) but I get an empty string.
My C# code with all the structs, enums etc:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Permissions;
namespace ConsoleApplication1
{
class Program
{
public static Guid VirtualStorageTypeVendorMicrosoft = new Guid("EC984AEC-A0F9-47e9-901F-71415A66345B");
static void Main(string[] args)
{
var handle = new VirtualDiskSafeHandle();
var storageType = new VirtualStorageType
{
DeviceId = VirtualStorageDeviceType.Vhdx,
VendorId = VirtualStorageTypeVendorMicrosoft
};
var parameters = new OpenVirtualDiskParameters
{
Version = OpenVirtualDiskVersion.Version2
};
var result = OpenVirtualDisk(ref storageType, "D:\\Test2.vhdx", VirtualDiskAccessMask.None, OpenVirtualDiskFlag.None,
ref parameters, ref handle);
if (result != 0)
{
throw new Win32Exception((int) result);
}
var info = new GetVirtualDiskInfo {Version = GetVirtualDiskInfoVersion.PhysicalDisk};
var infoSize = (uint) Marshal.SizeOf(info);
uint sizeUsed = 0;
result = GetVirtualDiskInformation(handle, ref infoSize, ref info, ref sizeUsed);
if (result != 0)
{
throw new Win32Exception((int) result);
}
Console.WriteLine($"LogicalSizeSector = {info.Union.PhysicalDisk.LogicalSectorSize}");
Console.WriteLine($"PhysicalSizeSector = {info.Union.PhysicalDisk.PhysicalSectorSize}");
Console.ReadLine();
}
[DllImport("virtdisk.dll", CharSet = CharSet.Unicode)]
public static extern uint OpenVirtualDisk(
[In] ref VirtualStorageType virtualStorageType,
[In] string path,
[In] VirtualDiskAccessMask virtualDiskAccessMask,
[In] OpenVirtualDiskFlag flags,
[In] ref OpenVirtualDiskParameters parameters,
[In, Out] ref VirtualDiskSafeHandle handle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(
[In] IntPtr hObject);
[DllImport("virtdisk.dll", CharSet = CharSet.Unicode)]
public static extern uint GetVirtualDiskInformation(
[In] VirtualDiskSafeHandle virtualDiskHandle,
[In, Out] ref uint virtualDiskInfoSize,
[In, Out] ref GetVirtualDiskInfo virtualDiskInfo,
[In, Out] ref uint sizeUsed);
[SecurityPermission(SecurityAction.Demand)]
public class VirtualDiskSafeHandle : SafeHandle
{
public VirtualDiskSafeHandle() : base(IntPtr.Zero, true) { }
public override bool IsInvalid => IsClosed || (handle == IntPtr.Zero);
public bool IsOpen => !IsInvalid;
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
public override string ToString()
{
return handle.ToString();
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct OpenVirtualDiskParameters
{
public OpenVirtualDiskVersion Version; //OPEN_VIRTUAL_DISK_VERSION
public OpenVirtualDiskParametersUnion Union;
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
public struct OpenVirtualDiskParametersUnion
{
[FieldOffset(0)]
public OpenVirtualDiskParametersVersion1 Version1;
[FieldOffset(0)]
public OpenVirtualDiskParametersVersion2 Version2;
[FieldOffset(0)]
public OpenVirtualDiskParametersVersion3 Version3;
}
/// <summary>
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct OpenVirtualDiskParametersVersion1
{
public uint RWDepth; //ULONG
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct OpenVirtualDiskParametersVersion2
{
public bool GetInfoOnly; //BOOL
public bool ReadOnly; //BOOL
public Guid ResiliencyGuid; //GUID
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct OpenVirtualDiskParametersVersion3
{
public bool GetInfoOnly; //BOOL
public bool ReadOnly; //BOOL
public Guid ResiliencyGuid; //GUID
public Guid SnapshotId; //GUID
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct GetVirtualDiskInfo
{
public GetVirtualDiskInfoVersion Version; //GET_VIRTUAL_DISK_INFO_VERSION
public GetVirtualDiskInfoUnion Union;
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
public struct GetVirtualDiskInfoUnion
{
[FieldOffset(0)] public GetVirtualDiskInfoSize Size;
[FieldOffset(0)] public Guid Identifier; //GUID
[FieldOffset(0)] public GetVirtualDiskInfoParentLocation ParentLocation;
[FieldOffset(0)] public Guid ParentIdentifier; //GUID
[FieldOffset(0)] public uint ParentTimestamp; //ULONG
[FieldOffset(0)] public VirtualStorageType VirtualStorageType; //VIRTUAL_STORAGE_TYPE
[FieldOffset(0)] public uint ProviderSubtype; //ULONG
[FieldOffset(0)] public bool Is4kAligned; //BOOL
[FieldOffset(0)] public bool IsLoaded; //BOOL
[FieldOffset(0)] public GetVirtualDiskInfoPhysicalDisk PhysicalDisk;
[FieldOffset(0)] public uint VhdPhysicalSectorSize; //ULONG
[FieldOffset(0)] public ulong SmallestSafeVirtualSize; //ULONGLONG
[FieldOffset(0)] public uint FragmentationPercentage; //ULONG
[FieldOffset(0)] public Guid VirtualDiskId; //GUID
[FieldOffset(0)] public GetVirtualDiskInfoChangeTrackingState ChangeTrackingState;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct GetVirtualDiskInfoSize
{
public ulong VirtualSize; //ULONGLONG
public ulong PhysicalSize; //ULONGLONG
public uint BlockSize; //ULONG
public uint SectorSize; //ULONG
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct GetVirtualDiskInfoParentLocation
{
public bool ParentResolved; //BOOL
public IntPtr ParentLocationBuffer; //WCHAR[1]
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct GetVirtualDiskInfoPhysicalDisk
{
public uint LogicalSectorSize; //ULONG
public uint PhysicalSectorSize; //ULONG
public bool IsRemote; //BOOL
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct GetVirtualDiskInfoChangeTrackingState
{
public bool Enabled; //BOOL
public bool NewerChanges; //BOOL
public IntPtr MostRecentId; //WCHAR[1]
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct VirtualStorageType
{
public VirtualStorageDeviceType DeviceId; //ULONG
public Guid VendorId; //GUID
}
public enum GetVirtualDiskInfoVersion
{
Unspecified = 0,
Size = 1,
Identifier = 2,
ParentLocation = 3,
ParentIdentifier = 4,
ParentTimestamp = 5,
VirtualStorageType = 6,
ProviderSubtype = 7,
Is4KAligned = 8,
PhysicalDisk = 9,
VhdPhysicalSectorSize = 10,
SmallestSafeVirtualSize = 11,
Fragmentation = 12,
IsLoaded = 13,
VirtualDiskId = 14,
ChangeTrackingState = 15
}
public enum VirtualStorageDeviceType
{
Unknown = 0,
Iso = 1,
Vhd = 2,
Vhdx = 3,
Vhdset = 4
}
public enum VirtualDiskAccessMask
{
None = 0x00000000,
AttachRo = 0x00010000,
AttachRw = 0x00020000,
Detach = 0x00040000,
GetInfo = 0x00080000,
Create = 0x00100000,
Metaops = 0x00200000,
Read = 0x000d0000,
All = 0x003f0000,
Writable = 0x00320000
}
[Flags]
public enum OpenVirtualDiskFlag
{
None = 0x00000000,
NoParents = 0x00000001,
BlankFile = 0x00000002,
BootDrive = 0x00000004,
CachedIo = 0x00000008,
CustomDiffChain = 0x00000010,
ParentCachedIo = 0x00000020,
VhdsetFileOnly = 0x00000040
}
public enum OpenVirtualDiskVersion
{
Unspecified = 0,
Version1 = 1,
Version2 = 2,
Version3 = 3,
}
}
}
Please comment out the line:
[FieldOffset(0)] public GetVirtualDiskInfoChangeTrackingState ChangeTrackingState;
Without that the struct results will be completely screwed up, still trying to figure out why.
Marshal the struct from the function call as an IntPtr. You will need to use Marshal.AllocHGlobal or another similar technique to get a block of unmanaged memory, since the Marshal isn't going to do it for you. You can then load the size member manually, or using Marshal.StructureToPtr.
From there use Marshal.OffsetOf to get the offset to the Union member. Once that's done use Marshal.Read and Marshal.PtrToStringUni to get at the data. For example with the Parent Location information:
IntPtr raw = Marshal.AllocHGlobal(1024);
// This is the GetVirtualDiskInfo from your provided code.
GetVirtualDiskInfo info = new GetVirtualDiskInfo();
info.Version = GetVirtualDiskInfoVersion.ParentLocation;
Marshal.StructureToPtr(info, raw, true);
Class1.Test(raw); // Replace this with your call to the function,
// This is a call to a C++/CLI method I wrote to stuff data
// into the structure.
IntPtr offsetToUnion = Marshal.OffsetOf(typeof(GetVirtualDiskInfo), "Union");
IntPtr data = raw + offsetToUnion.ToInt32();
bool parentResolved = Marshal.ReadInt32(data) != 0;
string parentLocationBuffer = Marshal.PtrToStringUni(data + 4);
Marshal.FreeHGlobal(raw); // Don't forget this!
Here's the method in the C++/CLI that loads the data for testing:
static void Test(IntPtr ptr)
{
GET_VIRTUAL_DISK_INFO* info = (GET_VIRTUAL_DISK_INFO*)ptr.ToPointer();
info->ParentLocation.ParentResolved = TRUE;
memcpy(info->ParentLocation.ParentLocationBuffer, L"123456789", 20);
}

ASP.NET MVC 4: Stackoverflow exception when using [DLLImport]

I'm using c++ morphology library mcr.dll and it's work fine when i use it in C# Console Application, but when I'm trying to run this code in ASP.NET MVC4 Controller it fails at "getlemma()" method, at line "LoadMcr(s)" with System.StackOverflowException. Please, help me to understand, why mvc controller doens't want to make this work like it does in console app?
P.S.: there were some problems when i've tryed to run it in Console Application, like messages about "PInvoke "ConsoleApplication1!ConsoleApplication1.morph::LoadMc unbalanced stack", but they disappeared when I add "CallingConvention = CallingConvention.Cdecl".
public string getlemma(string word)
{
InitMcr();
string s = "zal.mcr";
LoadMcr(s);
Tids tt = new Tids();
FindWID(word, ref tt);
Tid t = tt.ids[0];
Tinlexdata inlex = new Tinlexdata();
GetWordById(t, false, false, ref inlex);
return (inlex.inlex[0].anword);
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct Tid
{
/// unsigned int
public uint lnk;
/// unsigned char
public byte en;
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct Tids
{
/// Tid[200]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 200, ArraySubType = System.Runtime.InteropServices.UnmanagedType.Struct)]
public Tid[] ids;
/// int
public int count;
}
// // InitMcr() - initialize dictionary
[DllImport("mcr.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
public static extern int InitMcr();
// // LoadMcr - load dictionary
[DllImport("mcr.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
public static extern int LoadMcr([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string s);
// // FindID - (find word in lemma dictionary)
[DllImport("mcr.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
public static extern int FindWID([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string s, ref Tids ids);
// GetByID - (get lemma for a word)
[DllImport("mcr.dll", CharSet = CharSet.None, EntryPoint = "GetWordById", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetWordById(Tid id, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.I1)] bool gh_only, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.I1)] bool all, ref Tinlexdata outdata);

Categories