2011-07-17 4 views
5

में RtlCompressBuffer API I 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(); 
    } 
} 

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

उत्तर

5

आप लगभग बहुत हैं। समस्या अपने पी के इस भाग है/RtlCompressBuffer के लिए आह्वान:

out byte[] DestinationBuffer 

byte[] के लिए डिफ़ॉल्ट मार्शलिंग सरणी सामग्री दोनों दिशाओं में, फिर से वापस जब समारोह रिटर्न मार्शल करने के लिए अप्रबंधित में कामयाब से, और उसके बाद है। RtlCompressBuffer की सी परिभाषा __out के साथ एनोटेट की गई है, लेकिन इसका मतलब यह है कि सूचकांक __out होने के बजाय सरणी सामग्री __out है।

अपने पी बदलें/outBuf को RtlCompressBuffer परिवर्तन out outBuf को

byte[] DestinationBuffer 

और इसी तरह कॉल में करने के लिए आह्वान और तुम जाना अच्छा होना चाहिए।

चेतावनी दीजिये कि आपका कोड खड़ा है STATUS_BUFFER_ALL_ZEROS का स्टेटस कोड लौटाएगा, इसलिए यह सोचने में धोखा न दें कि यह गैर-शून्य वापसी मूल्य विफलता को इंगित करता है।

एक अंतिम बिंदु, पी/invokes, CompressionFormat दोनों के लिए पहला पैरामीटर ushort के रूप में घोषित किया जाना चाहिए।