如何从IntPtr中检索字符串

时间:2016-01-17 04:47:49

标签: c# pointers vb6

我调用了针对vb6的P / Invoke DLL函数。

它有效..我之前的问题是关于让它运行我设法让它运行但现在我无法从它的输出中检索完整的字符串。

DLL函数及其结构声明如下。

static class ModuleASM
{

    public struct REGTYPE
    {
        public byte REG_Kind; // ;1=8 bits \ 2=16 bits \ 3=32 bits \ 4=MMX \ 5=XMM \ 6=Float stack \ 7=Segment \ 8=Debug \ 9=Control \ 10=Test
        public byte REG_Ptr_Kind; // ;1=Byte PTR \ 2=Word PTR \ 3=Dword PTR \ 4=Qword PTR \ 5=mmword ptr \ 6=xmmword ptr \ 7=FWord PTR \ 8=tbyte ptr \ 9=null ptr (LEA)
        public byte REG_Type; //  ;0-7= direct register index \ 16 register=byte && 7 \ 32 register=(byte && 63)/8 \ 64=[32/16 address only] \ 128=[using x86 relatives]
        public byte REG_BaseAsReg; // ? ;1=Register only (BASE exposed)!
    }

    public struct REGSTRUCT
    {
        public uint SEG_TYPE;
        public uint Base;
        public uint INDEX;
        public uint SCALE;
        public uint DISPLACEMENTS;
        public uint DISPLACEMENT_TYPE;
        public ModuleASM.REGTYPE REG_Kind;
        public uint PTR_TYPE;
    }

    public struct IMMSTRUCT
    {
        public uint VALUE_LO;
        public uint VALUE_HI;
        public uint VALUE_TYPE; //     1=Byte \ 2=Word \ 4=Dword \ 8=ByteToWord \ 16=ByteToDword \ 32=AbsJump \ 64=ShortJump \ 128=LongJump
    }


    public struct DisAsmStruct
    {
        public uint Instruction_Prefix;
        public uint Instruction;
        public ModuleASM.REGSTRUCT Reg1;
        public ModuleASM.REGSTRUCT Reg2;
        public uint Reg_Reg; //1=from ptr
        public ModuleASM.IMMSTRUCT Imm;
        public uint Instruction_Length;
    }

    [DllImport("disASM.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    public static extern int DisAssemble(IntPtr Data, uint BaseAddress, out IntPtr DisAsmString, out DisAsmStruct DisAsmS, uint DisasmOpt);
}

//FDATA is the file data it's a huge byte array.

uint BufferLength;
uint CNT;
uint BaseAddress = 0x401000;

//The call is like this
unsafe
{
    string Opcodes = new string((char)0, 128);
    IntPtr OpcodesTest;
    ModuleASM.DisAsmStruct DisAa = new ModuleASM.DisAsmStruct();
    fixed (byte* dataPtr = &GLOBALDATA.FDATA[CNT])
    {
        IntPtr dataBuf = new IntPtr((void*)dataPtr);
        BufferLength = ModuleASM.DisAssemble(dataBuf, BaseAddress + CNT, out OpcodesTest, out DisAa, 0);

        //Kinda like it.. need more characters like, PUSH ECX
        ASCIIEncoding.ASCII.GetString(BitConverter.GetBytes(OpcodesTest.ToInt64())) //return "PUSH\0\0\0\0"

        byte testbbb = Marshal.ReadByte(OpcodesTest); //fail error
        string testa = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(OpcodesTest)); //fail error
        string testb = Marshal.PtrToStringAnsi(OpcodesTest); //blank return
        string testc = Marshal.PtrToStringUni(OpcodesTest); //fail error
        string testd = Marshal.PtrToStringUni(Marshal.ReadIntPtr(OpcodesTest)); //fail error
        string teste = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(OpcodesTest)); //fail error
        string testf = Marshal.PtrToStringAuto(OpcodesTest); //fail error
    }
}

任何人都知道我需要做些什么才能修复,所以我可以获得完整的字符串?不只是前4个字母..就像一个例子假设显示8个字符。

最初在vb6中声明如此

Declare Function DisAssemble Lib "disASM" (Data As Any, ByVal BaseAddress As Long, DisAsmString As Any, DisAsmS As Any, ByVal DisasmOpt As Long) As Long

Dim Opcodes     As String
Opcodes = String(128, 0)
Dim CleanOpCode As String
Dim DisA As DisAsmStruct

BufferLength = DisAssemble(FDATA(CNT), BaseAddress + CNT, ByVal Opcodes, DisA, 0)
CleanOpCode = Left(Opcodes, BufferLength)

1 个答案:

答案 0 :(得分:0)

修正了它们!如果你将DLLImport声明为不安全,你可以在byte*中使用C#作为参数之一。

喜欢这样

[DllImport("disASM.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern unsafe int DisAssemble(IntPtr Data, uint BaseAddress, byte* DisAsmString, out DisAsmStruct DisAsmS, uint DisasmOpt);

用法需要2个固定的陈述,因为我无法弄清楚如何在1个固定的陈述中做到这一点,它不适用于comas如何研究建议。

unsafe
{
    byte[] OpcodesBuffer = new byte[128];

    fixed (byte* dataPtr = &GLOBALDATA.FDATA[CNT])
    {
        fixed (byte* OpcodesPointer = &OpcodesBuffer[0])
        {
            BufferLength = ModuleASM.DisAssemble(new IntPtr((void*)dataPtr), BaseAddress + CNT, OpcodesPointer, out DisA, 0);
            MessageBox.Show(ASCIIEncoding.ASCII.GetString(OpcodesBuffer, 0, BufferLength));
            CNT += DisA.Instruction_Length;
         }
    }
}