Search code examples
c#.netwinapipinvokecrc

P/Invoke definition for RtlCrc32 and RtlCrc64 functions?


I would like to request a working P/Invoke definition for the undocumented RtlCrc32 and RtlCrc64 functions.

I'm aware about existing CRC-32 algorithms in managed code, but I prefer to go the Microsoft Windows way to avoid possible human errors and/or negative performance from my side due inexperience on checksum calculation, just that.

These are the functions declared in winnt.h header file (Windows 10 SDK):

//
//  Crc32 and Crc64 routines that use standardized algorithms
//

NTSYSAPI
DWORD
NTAPI
RtlCrc32(
    _In_reads_bytes_(Size) const void *Buffer,
    _In_ size_t Size,
    _In_ DWORD InitialCrc
    );

NTSYSAPI
ULONGLONG
NTAPI
RtlCrc64(
    _In_reads_bytes_(Size) const void *Buffer,
    _In_ size_t Size,
    _In_ ULONGLONG InitialCrc
    );

And this is what I tried:

[DllImport("NtDll.dll", SetLastError=false)]
public extern static uint RtlCrc32([In] IntPtr buffer, 
                                   [In] IntPtr size, 
                                   [In] uint initialCrc);

[DllImport("NtDll.dll", SetLastError=false)]
public extern static ulong RtlCrc64([In] IntPtr buffer, 
                                    [In] IntPtr size, 
                                    [In] ulong initialCrc);

and:

byte[] bytes = File.ReadAllBytes(@"C:\File.txt");
uint initialCrc = 0; // I tried to use 0x4C11DB7
                     // standarized polynomial value 
                     // just to try something random.

IntPtr buffer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, buffer, bytes.Length);

uint crc32 = NativeMethods.RtlCrc32(buffer, new IntPtr(bytes.Length), initialCrc);

Console.WriteLine(crc32.ToString("X2"));

But when I compare the returned value with any other program that calculates CRC-32, my value does not corresponds.

Because I'm not experienced with C/C++, I have some doubts... first I don't get whether the functions returns a NTSATUS error code, or they returns DWORD and ULONGLONG respectively. Secondly, I don't get what I need to pass to InitialCrc parameter.


Solution

  • Your definitions are fine. The functions return the CRC value rather than an error code.

    It might be easier to declare the buffer as byte[] and let the marshaler pin the array for you, avoiding a copy.

    The initial value is part of the input to a CRC algorithm. When comparing against output from another CRC algorithm you need to know what initial value was used.