如何从 IntPtr 中检索字符串

How to Retrieve character string from IntPtr

我调用了一个为 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[=10=][=10=][=10=][=10=]"

        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)

修复了,伙计们!如果您将 DLLImport 声明为不安全,那么您可以在 C# 中使用 byte* 作为参数之一。

像这样

[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 个固定语句中执行它,它不适用于研究建议的逗号。

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;
         }
    }
}