123*_*123 5 .net c# pinvoke winapi
我正在尝试在C#项目中使用RtlGetCompressionWorkSpaceSize和RtlCompressBuffer函数.
这是我到目前为止:
class Program
{
const uint COMPRESSION_FORMAT_LZNT1 = 2;
const uint COMPRESSION_ENGINE_MAXIMUM = 0x100;
[DllImport("ntdll.dll")]
static extern uint RtlGetCompressionWorkSpaceSize(uint CompressionFormat, out uint pNeededBufferSize, out uint Unknown);
[DllImport("ntdll.dll")]
static extern uint RtlCompressBuffer(uint CompressionFormat, byte[] SourceBuffer, uint SourceBufferLength, out byte[] DestinationBuffer,
uint DestinationBufferLength, uint Unknown, out uint pDestinationSize, IntPtr WorkspaceBuffer);
static void Main(string[] args)
{
uint dwSize = 0;
uint dwRet = 0;
uint ret = RtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM, out dwSize, out dwRet);
IntPtr pMem = Marshal.AllocHGlobal((int)dwSize);
byte[] buffer = new byte[1024];
byte[] outBuf = new byte[1024];
uint destSize = 0;
ret = RtlCompressBuffer(COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM, buffer, 1024, out outBuf, 1024, 0, out destSize, pMem);
Console.Write(ret.ToString());
Console.Read();
}
}
Run Code Online (Sandbox Code Playgroud)
RtlGetCompressionWorkSpaceSize工作,因为它返回0(NT成功代码),但当我调用RtlCompressBuffer时,我收到内存访问冲突错误.
编辑:在大卫答案的帮助下,我已经修复了问题,下面是正确的代码.
const ushort COMPRESSION_FORMAT_LZNT1 = 2;
const ushort COMPRESSION_ENGINE_MAXIMUM = 0x100;
[DllImport("ntdll.dll")]
static extern uint RtlGetCompressionWorkSpaceSize(ushort CompressionFormat, out uint pNeededBufferSize, out uint Unknown);
[DllImport("ntdll.dll")]
static extern uint RtlCompressBuffer(ushort CompressionFormat, byte[] SourceBuffer, int SourceBufferLength, byte[] DestinationBuffer,
int DestinationBufferLength, uint Unknown, out int pDestinationSize, IntPtr WorkspaceBuffer);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern IntPtr LocalAlloc(int uFlags, IntPtr sizetdwBytes);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LocalFree(IntPtr hMem);
internal static byte[] Compress(byte[] buffer)
{
var outBuf = new byte[buffer.Length * 6];
uint dwSize = 0, dwRet = 0;
uint ret = RtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM, out dwSize, out dwRet);
if (ret != 0)
{
return null;
}
int dstSize = 0;
IntPtr hWork = LocalAlloc(0, new IntPtr(dwSize));
ret = RtlCompressBuffer(COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM, buffer,
buffer.Length, outBuf, outBuf.Length, 0, out dstSize, hWork);
if (ret != 0)
{
return null;
}
LocalFree(hWork);
Array.Resize(ref outBuf, dstSize);
return outBuf;
}
Run Code Online (Sandbox Code Playgroud)
你几乎就在那里.问题是你的P/invoke的这部分RtlCompressBuffer:
out byte[] DestinationBuffer
Run Code Online (Sandbox Code Playgroud)
默认的编组方法byte[]是将数组内容在两个方向上编组,从托管到非托管,然后在函数返回时再返回.C定义用RtlCompressBuffer注释,__out但这意味着数组内容__out而不是指针__out.
将您的P/invoke更改为
byte[] DestinationBuffer
Run Code Online (Sandbox Code Playgroud)
和同样在呼吁RtlCompressBuffer改变out outBuf对outBuf你应该是好去.
请注意,您的代码将返回状态代码,STATUS_BUFFER_ALL_ZEROS因此不要误以为此非零返回值表示失败.
最后一点,P/invokes的第一个参数CompressionFormat应该声明为ushort.
| 归档时间: |
|
| 查看次数: |
1144 次 |
| 最近记录: |