3

WMI を使用して、Windows 7 のローカル プリンターに関連付けられている随意アクセス制御リスト (DACL) からアクセス制御エントリ (ACE) を削除しようとしています。コードはセキュリティ記述子を取得し、 DACL。ALE のトラスティの名前が「Everyone」でない限り、ACE は一時リストに追加されます。

一時リストは配列に変換され、セキュリティ記述子の DACL プロパティを置き換えます。次にコードは、変更された記述子を使用して SetSecurityDescriptor() を呼び出します。

戻り値は 0x8007051B で、0x051B は Win32 エラー コードです: 1307、このセキュリティ ID は、このオブジェクトの所有者として割り当てられていない可能性があります。

コードのどこにも (意図的に) プリンターの所有者を変更していないため、エラー メッセージは少しわかりにくいです。

すべての ACE を一時リストに含めるようにメソッドを変更すると、SetSecurityDescriptor() の呼び出しが正常に完了します。

管理者としてアプリケーションを実行しても違いはありません。

そしてもちろん、コード:

    private void ChangeSecurity()
        {
            var query = String.Format("SELECT * from Win32_Printer where Name like \"%{0}%\"", PrinterName);
            var searcher = new ManagementObjectSearcher(query);
            var searchResults = searcher.Get();

            foreach (ManagementObject printer in searchResults)
            {
                var result = printer.InvokeMethod("GetSecurityDescriptor", null, null);
                var descriptor = (ManagementBaseObject)result["Descriptor"];
                var flags = (uint)descriptor["ControlFlags"];
                if ((flags & (uint)ControlFlags.DiscretionaryAclPresent) == (uint)ControlFlags.DiscretionaryAclPresent)
                {
                    Console.WriteLine("DACL present");
                    var dacl = (ManagementBaseObject[])descriptor["DACL"];
                    var newDaclList = new List<ManagementBaseObject>();
                    foreach (var ace in dacl)
                    {
                        var trustee = (ManagementBaseObject)ace["Trustee"];
                        var aceType = (uint)ace["AceType"];
                        if ((aceType & (uint) AceType.AccessAllowed) == (uint) AceType.AccessAllowed)
                        {
                            Console.WriteLine("{0}\\{1}", trustee["Domain"], trustee["Name"]);
                            Console.WriteLine("Access mask {0}", ace["AccessMask"]);
                            if (trustee["Name"].ToString() == "Everyone" && trustee["Domain"] == null)
                            {
                                Console.WriteLine("Remove access");
                            }
                            else
                            {
                                newDaclList.Add(ace);
                            }
                        }
                    }

                    descriptor.SetPropertyValue("DACL", newDaclList.ToArray());

                    var inParams = printer.GetMethodParameters("SetSecurityDescriptor");
                    inParams["Descriptor"] = descriptor;
                    result = printer.InvokeMethod("SetSecurityDescriptor", inParams, null);
                    Console.WriteLine("Result code: {0}", result["ReturnValue"]);
                }
            }
4

1 に答える 1

1

私も同じ問題を抱えていました。管理者以外のアカウントとグループからプリンターへのアクセスを削除したかったのです。

解決策は次のとおりです。

次の行を置き換えます。

descriptor.SetPropertyValue("DACL", newDaclList.ToArray());

これとともに:

descriptor.SetPropertyValue("DACL", newDaclList.ToArray());
descriptor.SetPropertyValue("Group", null);
descriptor.SetPropertyValue("Owner", null);
descriptor.SetPropertyValue("ControlFlags", (uint)ControlFlags.DiscretionaryAclPresent);

これを理解するのに何時間もかかりました。

Microsoft のドキュメントの「備考」セクションを参照してください。

https://msdn.microsoft.com/en-us/library/aa393594(v=vs.85).aspx

于 2017-10-11T13:08:30.063 に答える