質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

1回答

3272閲覧

CredEnumerate より CREDENTIAL#Attributes を エラーなく取得したい。

juner

総合スコア95

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

0クリップ

投稿2018/04/16 04:51

編集2018/04/16 04:54

前提・実現したいこと

C# でCredEnumerate で取得した値をすべて表示したく思い、プログラムサンプルを書いています。
すると CREDENTIAL#Attributes の構造体への割り当て時に次の様なエラーが発生します。

発生している問題・エラーメッセージ

text

1マネージ デバッグ アシスタント 'FatalExecutionEngineError' : 'ランタイムの重大なエラーが発生しました。エラーのアドレスは 0x7355853e、スレッド 0x3238 です。エラー コードは 0xc0000005 です。これは CLR のバグであるか、またはユーザー コードのアンセーフまたは確認不可能な部分にバグがある可能性があります。このバグの一般的な原因には、スタックが壊れる可能性のある COM-interop または PInvoke のユーザー マーシャリング エラーが含まれています。'

発生個所は次のソースコードのMain内の

csharp

1.Select(x => Marshal.PtrToStructure<CREDENTIAL_ATTRIBUTE>(x)))

の箇所となります。

該当のソースコード

csharp

1using System; 2using System.Linq; 3using System.Runtime.InteropServices; 4 5namespace CredReadExample 6{ 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 IntPtr Credentials = IntPtr.Zero; 12 try 13 { 14 var i = 0; 15 if(CredEnumerate(null, 0, out var count,out Credentials)) 16 foreach(var c in Enumerable.Range(0, count) 17 .Select(n => Marshal.ReadIntPtr(Credentials, n * Marshal.SizeOf(typeof(IntPtr)))) 18 .Select(ptr => Marshal.PtrToStructure<CREDENTIAL>(ptr))) 19 { 20 Console.WriteLine($"{++i}"); 21 Console.WriteLine($"{nameof(c.Flags)}:{c.Flags}"); 22 Console.WriteLine($"{nameof(c.Type)}:{c.Type}"); 23 Console.WriteLine($"{nameof(c.TargetName)}:{c.TargetName}"); 24 Console.WriteLine($"{nameof(c.Comment)}:{c.Comment}"); 25 Console.WriteLine($"{nameof(c.LastWritten)}:{DateTime.FromFileTime((long)(c.LastWritten.dwHighDateTime << 32) | (uint)c.LastWritten.dwLowDateTime)}"); 26 Console.WriteLine($"{nameof(c.CredentialBlobSize)}:{c.CredentialBlobSize}"); 27 var _CredentialBlob = new byte[c.CredentialBlobSize]; 28 if (c.CredentialBlobSize > 0) 29 Marshal.Copy(c.CredentialBlob, _CredentialBlob, 0, (int)c.CredentialBlobSize); 30 Console.WriteLine($"{nameof(c.CredentialBlob)}:[{string.Join(" ", _CredentialBlob.Select(b => $"{b:X2}"))}]"); 31 Console.WriteLine($"{nameof(c.Persist)}:{c.Persist}"); 32 Console.WriteLine($"{nameof(c.AttributeCount)}:{c.AttributeCount}"); 33 var ai = 0; 34 foreach(var attribute in Enumerable.Range(0, (int)c.AttributeCount) 35 .Select(x => Marshal.ReadIntPtr(c.Attributes, x * Marshal.SizeOf<CREDENTIAL_ATTRIBUTE>())) 36 .Select(x => Marshal.PtrToStructure<CREDENTIAL_ATTRIBUTE>(x))) 37 { 38 Console.WriteLine($"{nameof(c.Attributes)} - {++ai}"); 39 Console.WriteLine($"{nameof(attribute.Keyword)}:{attribute.Keyword}"); 40 Console.WriteLine($"{nameof(attribute.Flags)}:{attribute.Flags}"); 41 Console.WriteLine($"{nameof(attribute.ValueSize)}:{attribute.ValueSize}"); 42 var _AttributeValue = new byte[attribute.ValueSize]; 43 if (attribute.ValueSize > 0) 44 Marshal.Copy(attribute.Value, _AttributeValue, 0, (int)attribute.ValueSize); 45 Console.WriteLine($"{nameof(attribute.Value)}:[{string.Join(" ", _AttributeValue.Select(v => $"{v:X2}"))}]"); 46 } 47 Console.WriteLine($"{nameof(c.TargetAlias)}:{c.TargetAlias}"); 48 Console.WriteLine($"{nameof(c.UserName)}:{c.UserName}"); 49 } 50 } 51 finally 52 { 53 if (Credentials != IntPtr.Zero) 54 CredFree(Credentials); 55 } 56 Console.ReadLine(); 57 } 58 [DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)] 59 private static extern bool CredEnumerate(string filter, CRED_FLAGS flag, out int count, out IntPtr Credentials); 60 [DllImport("advapi32.dll", SetLastError = true)] 61 static extern bool CredFree([In] IntPtr buffer); 62 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 63 internal struct CREDENTIAL 64 { 65 public CRED_FLAGS Flags; 66 public CRED_TYPE Type; 67 public string TargetName; 68 public string Comment; 69 public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten; 70 public uint CredentialBlobSize; 71 public IntPtr CredentialBlob; 72 public CRED_PERSIST Persist; 73 public uint AttributeCount; 74 public IntPtr Attributes; 75 public string TargetAlias; 76 public string UserName; 77 } 78 public enum CRED_TYPE : uint 79 { 80 GENERIC = 1, 81 DOMAIN_PASSWORD = 2, 82 DOMAIN_CERTIFICATE = 3, 83 DOMAIN_VISIBLE_PASSWORD = 4, 84 GENERIC_CERTIFICATE = 5, 85 DOMAIN_EXTENDED = 6, 86 MAXIMUM = 7, 87 MAXIMUM_EX = (MAXIMUM + 1000), 88 } 89 90 public enum CRED_PERSIST : uint 91 { 92 SESSION = 1, 93 LOCAL_MACHINE = 2, 94 ENTERPRISE = 3, 95 } 96 97 public enum CRED_FLAGS : uint 98 { 99 PROMPT_NOW = 0x2, 100 USERNAME_TARGET = 0x4 101 } 102 103 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 104 public struct CREDENTIAL_ATTRIBUTE 105 { 106 public string Keyword; 107 public uint Flags; 108 public uint ValueSize; 109 public IntPtr Value; 110 } 111 } 112} 113

試したこと

エラーが発生する箇所の.Select を次のコードにしたところ、 Keyword値は正常に取得することができたが、他の値は不正な値となった。※勿論、 Value 及び ValueSize を設定しない様にして実行すれば最後まで実行できるが、 Flags の値は不正であろう値となる。

csharp

1.Select(x => 2{ 3 var pos = 0; 4 var Keyword = Marshal.PtrToStringUni(x); 5 pos += Marshal.SizeOf<IntPtr>(); 6 var Flags = (uint)Marshal.ReadInt32(x, pos); 7 pos += sizeof(uint); 8 var ValueSize = (uint)Marshal.ReadInt32(x, pos); 9 pos += sizeof(uint); 10 var Value = Marshal.SizeOf<IntPtr>() == 4 ? new IntPtr(x.ToInt32() * pos) 11 : Marshal.SizeOf<IntPtr>() == 8 ? new IntPtr(x.ToInt64() * pos) 12 : new IntPtr(x.ToInt32() * pos); 13 pos += Marshal.SizeOf<IntPtr>(); 14 return new CREDENTIAL_ATTRIBUTE 15 { 16 Keyword = Keyword, 17 Flags = Flags, 18 ValueSize = ValueSize, 19 Value = Value, 20 }; 21})

補足情報(FW/ツールのバージョンなど)

VisualStudio 2017 15.6.6
.NET Frameworks 4.6.1
32bit/64bit
Windows10 1709

実際のソリューションファイル(上記ソース位置)
https://github.com/juner/testproject20180416
最新のソリューション(試したこと適用時の最終)
https://github.com/juner/testproject20180416

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2018/04/16 04:56

文法が間違っているのでコンパイルできません。該当のエラーが出るソースを書いてください。
Zuishin

2018/04/16 04:58

失礼しました。こちらのミスでした。
guest

回答1

0

自己解決

原因は エラーが発生していた .Select の箇所ではなく、その手前の位置の取得部分である、

csharp

1.Select(x => Marshal.ReadIntPtr(c.Attributes, x * Marshal.SizeOf<CREDENTIAL_ATTRIBUTE>()))

が原因。ポインタの先を読みに行くのではなく、 その場所自体に値があるので正しくは

csharp

1.Select(x => IntPtr.Add(c.Attributes,x * Marshal.SizeOf<CREDENTIAL_ATTRIBUTE>()))

の様にしなくてはならない。(CREDENTIAL_ATTRIBUTE の取り方を CREDENTIAL の取り方とごっちゃにしていた可能性)

参考:当該修正方法を適用した時点のソリューション
https://github.com/juner/testproject20180416

投稿2018/04/16 05:37

juner

総合スコア95

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問