作为这个问题的后续,我希望有人可以帮助CredEnumerate API.
据我从文档中了解,PCREDENTIALS out参数是"指向凭证指针数组的指针".我能够使用C#成功调用CredEnumerate API,但我不确定如何将PCREDENTIALS转换为有用的东西(如凭证列表).
编辑:这是我正在使用的代码:
int count = 0; IntPtr pCredentials = IntPtr.Zero; bool ret = false; ret = CredEnumerate(null, 0, out count, out pCredentials); if (ret != false) { IntPtr[] credentials = new IntPtr[count]; IntPtr p = pCredentials; for (int i = 0; i < count; i++) { p = new IntPtr(p.ToInt32() + i); credentials[i] = Marshal.ReadIntPtr(p); } Listcreds = new List (credentials.Length); foreach (IntPtr ptr in credentials) { creds.Add((Credential)Marshal.PtrToStructure(ptr, typeof(Credential))); } }
不幸的是,虽然这适用于阵列中的第一个凭证 - 它会被生成并正确地添加到列表中 - 随后的数组项目会在Marshal.PtrToStructure上轰炸,并出现以下错误:
尝试读取或写入受保护的内存.这通常表明其他内存已损坏.
有任何想法吗?任何人?Bueller?
您需要取消引用指向数组的指针才能获取数组,然后对于数组中的每个项目,您需要取消引用该项以获取PCREDENTIALS
实例.
我发现这篇文章带有一些示例代码,用于执行您想要执行的操作:
[DllImport("advapi32", SetLastError = true, CharSet=CharSet.Unicode)] static extern bool CredEnumerate(string filter, int flag, out int count, out IntPtr pCredentials);
...
int count = 0; IntPtr pCredentials = IntPtr.Zero; IntPtr[] credentials = null; bool ret = CredEnumerate(null, 0, out count, out pCredentials); if (ret != false) { credentials = new IntPtr[count]; IntPtr p = pCredentials; for (int n = 0; n < count; n++) { credentials[n] = Marshal.ReadIntPtr(pCredentials, n * Marshal.SizeOf(typeof(IntPtr))); } } else // failed....
然后对于每个指针,您需要使用它Marshal.PtrToStructure
来将指针解引用到PCREDENTIALS
结构实例中(抱歉,我找不到PCREDENTIALS
任何地方的typedef ,我假设你拥有它 - 如果你确实没有忘记正确的MarshalAs属性和StructLayout你定义它时的属性):
// assuming you have declared struct PCREDENTIALS var creds = new List(credentials.Length); foreach (var ptr in credentials) { creds.Add((PCREDENTIALS)Marshal.PtrToStructure(ptr, typeof(PCREDENTIALS))); }
您显然希望将示例和PtrToStructure
代码结合起来以获得最佳结果,但我希望保持示例的完整性.