P /调用offreg.dll函数-后续调用访问冲突

问题描述 投票:0回答:1

这是我的第一个问题,因此,如果我违反某些书面或不成文规定,请多多包涵。

我正在尝试从C#中的offreg.dll P /调用功能。为了了解它们的工作原理,我编写了这个非常基本的控制台应用程序:

using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApp2
{

    class Program
    {
        [DllImport("C:\\TEMP\\offreg-x64.dll", EntryPoint = "ORGetVersion", CharSet = CharSet.Unicode)]
        public static extern void ORGetVersion(out uint MajorVersion, out uint MinorVersion);

        [DllImport("C:\\TEMP\\offreg-x64.dll", EntryPoint = "OROpenHive", CharSet = CharSet.Unicode)]
        public static extern int OROpenHive(string HivePath, out IntPtr rootKeyHandle);

        [DllImport("C:\\TEMP\\offreg-x64.dll", EntryPoint = "OROpenKey", CharSet = CharSet.Unicode)]
        public static extern int OROpenKey(IntPtr KeyHandle, string SubKeyName, out IntPtr SubKeyHandle);

        [DllImport("C:\\TEMP\\offreg-x64.dll", EntryPoint = "ORCloseKey", CharSet = CharSet.Unicode)]
        public static extern int ORCloseKey(IntPtr KeyHandle);

        [DllImport("C:\\TEMP\\offreg-x64.dll", EntryPoint = "OREnumKey", CharSet = CharSet.Unicode)]
        public static extern int OREnumKey( IntPtr KeyHandle, 
                                            uint Index, 
                                            [MarshalAs(UnmanagedType.LPWStr)]
                                            StringBuilder SubKeyName, 
                                            ref uint SubKeyLen, 
                                            [MarshalAs(UnmanagedType.LPWStr)]
                                            StringBuilder ClassName, 
                                            ref uint ClassLen, 
                                            out uint LastWriteTime
            );

        [DllImport("C:\\TEMP\\offreg-x64.dll", EntryPoint = "ORQueryInfoKey", CharSet = CharSet.Unicode)]
        public static extern int ORQueryInfoKey(IntPtr KeyHandle, 
                                            [MarshalAs(UnmanagedType.LPWStr)]
                                            StringBuilder ClassName, 
                                            ref uint ClassLen, 
                                            out uint NumKeys, 
                                            out uint MaxKeyLen, 
                                            out uint NumVals, 
                                            out uint MaxValLen, 
                                            out IntPtr SecDesc, 
                                            out uint LastWrite
            );

        [DllImport("C:\\TEMP\\offreg-x64.dll", EntryPoint = "ORCloseHive", CharSet = CharSet.Unicode)]
        public static extern int ORCloseHive(IntPtr rootKeyHandle);

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World");
            int res = 0;    // result of every OR function call
            IntPtr h;       // hive (or root key) handle


            // Get DLL version
            uint ver1 = 0;
            uint ver2 = 0;
            Program.ORGetVersion(out ver1, out ver2);
            Console.WriteLine("Library Version: " + ver1.ToString() + "." + ver2.ToString());
            // end get version

            // Open hive
            res = Program.OROpenHive(@"C:\TEMP\NTUSER.DAT", out h);
            Console.WriteLine("Open Result: " + res.ToString());
            Console.WriteLine("Open Handle: " + h.ToString());
            // end oppen hive

            // prepare variables for key operations
            StringBuilder ClassName = new StringBuilder(256);
            uint ClassLen = 256;
            StringBuilder SubKeyName = new StringBuilder(256);
            uint SubKeyLen = 256;
            uint NKeys = 0;
            uint maxKeyLen = 0;
            uint NVals = 0;
            uint maxValLen = 0;
            IntPtr SecDesc = IntPtr.Zero;
            uint LastWrite = 0;
            uint SubKeyIndex = 0;   // we are asking for the first subkey
            // end prepare variables

            // Query root key information
            res = Program.ORQueryInfoKey(h, ClassName, ref ClassLen, out NKeys, out maxKeyLen, out NVals, out maxValLen, out SecDesc, out LastWrite);
            Console.WriteLine("Query Result: " + res.ToString());
            Console.WriteLine("Query Class Name: " + ClassName.ToString());
            Console.WriteLine("Query Class Length: " + ClassLen.ToString());
            Console.WriteLine("Query Num Subkeys: " + NKeys.ToString());
            Console.WriteLine("Query Max Subkey Len: " + maxKeyLen.ToString());
            Console.WriteLine("Query Num Values: " + NVals.ToString());
            Console.WriteLine("Query Max Value Len: " + maxValLen.ToString());
            Console.WriteLine("Query Last Write: " + LastWrite.ToString());
            // end query root key information

            // enum first subkey
            res = Program.OREnumKey(h, SubKeyIndex, SubKeyName, ref SubKeyLen, ClassName, ref ClassLen, out LastWrite);
            Console.WriteLine("Enum Result: " + res.ToString());
            Console.WriteLine("Enum Builder: " + SubKeyName.ToString());
            Console.WriteLine("Enum Length: " + SubKeyLen.ToString());
            Console.WriteLine("Enum Capacity: " + SubKeyName.Capacity.ToString());
            // end enum first subkey

            // close hive
            res = Program.ORCloseHive(h);
            Console.WriteLine("Close Result: " + res.ToString());
            // end close hive

            // sayonara
            Console.WriteLine("Press [ENTER] to exit");
            Console.ReadLine();
        }
    }
}

当我如上所示运行此代码时,它将运行ORQueryInfoKey块,但在尝试调用OREnumKey时给我一个访问冲突。

如果我注释掉对[[ORQueryInfoKey的调用,它将运行正常并返回第一个子键的正确信息(但我显然没有得到有关子键和值的数量或它们的长度的信息)。] >如果我注释掉对[[OREnumKey

的调用,则访问冲突仍会发生在

ORCloseHive上。 如果我交换ORQueryInfoKey

块和

OREnumKey块,它不会引发任何异常,但是Query调用返回234(MORE_DATA_AVAILABLE),这意味着ClassLen太短。如果我交换ORQueryInfoKey

块和

OREnumKey块并在第二次调用之前将ClassLen设置为1],它将运行OK,返回正确的数据,但是在ORCloseHive上抛出访问冲突因此,在成功调用ORQueryInfoKey之后,似乎使用句柄

h

的下一次调用将产生访问冲突。我想念什么?任何见识都将不胜感激!

这是我的第一个问题,因此,如果我违反某些书面或不成文规定,请多多包涵。我正在尝试从C#中的offreg.dll P /调用函数。为了了解它们的工作原理,我写了...

c# pinvoke access-violation
1个回答
0
投票
[DllImport(@"C:\Program Files (x86)\Windows Kits\10\Redist\offreg\x64\offreg.dll", CharSet = CharSet.Unicode)] public static extern int OREnumKey(IntPtr Handle, int dwIndex, IntPtr lpName, ref int lpcName, IntPtr lpClass, ref int lpcClass, out long lpftLastWriteTime); [DllImport(@"C:\Program Files (x86)\Windows Kits\10\Redist\offreg\x64\offreg.dll", CharSet = CharSet.Unicode)] public static extern int ORQueryInfoKey( IntPtr Handle, IntPtr lpClass, ref int lpcClass, out int lpcSubKeys, out int lpcMaxSubKeyLen, out int lpcMaxClassLen, out int lpcValues, out int lpcMaxValueNameLen, out int lpcMaxValueLen, out int lpcbSecurityDescriptor, out long lpftLastWriteTime); static void Main() { const int ERROR_MORE_DATA = 234; const int ERROR_NO_MORE_ITEMS = 259; var res = OROpenHive(@"c:\TEMP\NTUSER.DAT", out var h); if (res != 0) throw new Win32Exception(res); try { var clsLen = 0; var clsPtr = IntPtr.Zero; res = ORQueryInfoKey(h, IntPtr.Zero, ref clsLen, out var subKeys, out var maxSubKeyLen, out var maxClassLen, out var values, out var maxValueNameLen, out var maxValueLen, out var securityDescriptor, out var lastWriteTime); if (res == ERROR_MORE_DATA) { clsPtr = Marshal.AllocHGlobal(clsLen); try { res = ORQueryInfoKey(h, clsPtr, ref clsLen, out subKeys, out maxSubKeyLen, out maxClassLen, out values, out maxValueNameLen, out maxValueLen, out securityDescriptor, out lastWriteTime); if (res == 0) { var cls = Marshal.PtrToStringUni(clsPtr); Console.WriteLine("Class: " + cls); } } finally { Marshal.FreeHGlobal(clsPtr); } } if (res != 0) throw new Win32Exception(res); var nameLen = 0; var i = 0; var namePtr = IntPtr.Zero; do { clsLen = 0; nameLen = 0; res = OREnumKey(h, i, IntPtr.Zero, ref nameLen, IntPtr.Zero, ref clsLen, out lastWriteTime); if (res == ERROR_NO_MORE_ITEMS) break; if (res == ERROR_MORE_DATA) { if (nameLen > 0) { namePtr = Marshal.AllocHGlobal(nameLen); } if (clsLen > 0) { clsPtr = Marshal.AllocHGlobal(clsLen); } try { res = OREnumKey(h, i, namePtr, ref nameLen, clsPtr, ref clsLen, out lastWriteTime); if (res == 0) { Console.WriteLine("LastWriteTime: " + DateTime.FromFileTime(lastWriteTime)); if (namePtr != IntPtr.Zero) { var name = Marshal.PtrToStringUni(namePtr); Console.WriteLine("Name: " + name); } if (clsPtr != IntPtr.Zero) { var cls = Marshal.PtrToStringUni(clsPtr); Console.WriteLine("Class: " + cls); } } } finally { if (namePtr != IntPtr.Zero) { Marshal.FreeHGlobal(namePtr); namePtr = IntPtr.Zero; } if (clsPtr != IntPtr.Zero) { Marshal.FreeHGlobal(clsPtr); clsPtr = IntPtr.Zero; } } } if (res != 0) throw new Win32Exception(res); i++; } while (true); } finally { ORCloseHive(h); } }
© www.soinside.com 2019 - 2024. All rights reserved.