<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; VBS &  WMI: добавить запись в DACL каталога, сохранив наследование]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=5755</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=5755&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «VBS &  WMI: добавить запись в DACL каталога, сохранив наследование».]]></description>
		<lastBuildDate>Thu, 07 Jul 2011 12:51:58 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: VBS &  WMI: добавить запись в DACL каталога, сохранив наследование]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=49725#p49725</link>
			<description><![CDATA[<p>Предлагаю для тестирования сценарий очистки DACL дерева папок от записей с не олицетворёнными SID.<br />Тот, кому будет не лень просмотреть &quot;портянку&quot; кода до конца, найдёт достаточно подробное описание и функциональности сценария, и особенностей его работы.<br />Сценарий проверен на Win XP Pro/2008/7 Pro.<br /></p><div class="codebox"><pre><code>Option Explicit

Dim objFS, objShell, objFolder, objFile, objWShell, objWMI
Dim strTranslator, strLogFile, strComputer, strTargetPath
Dim objDict, objRegExp, arrTemp, intNumArgs, strKey, strTemp, i
Dim blnIsConsole, blnRecursive, blnCreateLog, blnSilent, blnAvailable, blnHasError

strComputer = &quot;.&quot;
blnCreateLog = True: blnSilent = True: blnAvailable = True
Set objFS = CreateObject(&quot;Scripting.FileSystemObject&quot;)
strTranslator = objFS.GetBaseName(WScript.FullName)
If StrComp(strTranslator, &quot;cscript&quot;, vbTextCompare) = 0 Then blnIsConsole = True
If blnIsConsole Then
    arrTemp = Array(&quot;tc&quot;, &quot;tlp&quot;, &quot;r&quot;, &quot;nl&quot;, &quot;s&quot;)
    Set objDict = CreateObject(&quot;Scripting.Dictionary&quot;)
    objDict.CompareMode = 1
    For i = 0 To UBound(arrTemp)
        objDict.Add arrTemp(i), vbNullString
    Next
    &#039;--- Проверка корректности набора заданных ключей, определение значений ключей
    Set objRegExp = CreateObject(&quot;VBScript.RegExp&quot;)
    objRegExp.Global = True
    objRegExp.IgnoreCase = True
    objRegExp.Pattern = &quot;^[-/]&quot;
    intNumArgs = WScript.Arguments.Count
    Select Case intNumArgs
        Case 0: Call View_Help: WScript.Quit 0
        Case 1
            strTemp = objRegExp.Replace(WScript.Arguments.Item(0), &quot;&quot;)
            If strTemp = &quot;?&quot; Then
                Call View_Help: WScript.Quit 0
            Else
                If Len(strTemp) &gt; 1 Then
                    If LCase(Left(strTemp, 4)) &lt;&gt; &quot;tlp:&quot; Then
                        Call Err_Message(1, strTemp)
                        WScript.Quit 0
                    Else
                        If Len(strTemp) &gt; 4 Then
                            objDict.Item(&quot;tlp&quot;) = Mid(strTemp, 5)
                        Else
                            Call Err_Message(11, &quot;tlp&quot;)
                            WScript.Quit 0
                        End If
                    End If
                Else
                    Call Err_Message(1, Null)
                    WScript.Quit 0
                End If
            End If
        Case Else
            For Each strTemp In WScript.Arguments
                arrTemp = Null
                strTemp = objRegExp.Replace(strTemp, &quot;&quot;)
                If Len(strTemp) &gt; 0 Then
                    If strTemp = &quot;?&quot; Then
                        Call Err_Message(2, strTemp)
                        WScript.Quit 0
                    Else
                        i = InStr(strTemp, &quot;:&quot;)
                        If i &gt; 0 Then
                            strKey = Left(strTemp, i - 1)
                            If strKey = &quot;tlp&quot; Or strKey = &quot;tc&quot; Then
                                arrTemp = Split(strTemp, strKey &amp; &quot;:&quot;, -1, vbTextCompare)
                                If Len(arrTemp(1)) = 0 Then
                                    Call Err_Message(11, strKey)
                                    WScript.Quit 0
                                End If
                            Else
                                Call Err_Message(10, strKey)
                                WScript.Quit 0
                            End If
                        Else
                            If strTemp &lt;&gt; &quot;tlp&quot; And strTemp &lt;&gt; &quot;tc&quot; Then
                                strKey = strTemp
                            Else
                                Call Err_Message(11, strTemp)
                                WScript.Quit 0
                            End If
                        End If
                        If objDict.Exists(strKey) Then
                            If Len(objDict.Item(strKey)) = 0 Then
                                If IsArray(arrTemp) Then
                                    objDict.Item(strKey) = arrTemp(1)
                                Else
                                    objDict.Item(strKey) = &quot;+&quot;
                                End If
                            Else
                                Call Err_Message(4, strKey)
                                WScript.Quit 0
                            End If
                        Else
                            Call Err_Message(3, strKey)
                            WScript.Quit 0
                        End If
                    End If
                Else
                    Call Err_Message(3, strTemp)
                    WScript.Quit 0
                End If
            Next
    End Select
    &#039;------
    &#039;--- Проверка корректности заданных значений ключей
    For Each strTemp In objDict.Keys
        Select Case LCase(strTemp)
            Case &quot;tc&quot;: If Len(objDict.Item(strTemp)) &gt; 0 Then strComputer = objDict.Item(strTemp)
            Case &quot;tlp&quot;
                If Len(objDict.Item(strTemp)) &gt; 0 Then
                    strTargetPath = Trim(objDict.Item(strTemp))
                    If Len(strTargetPath) &gt;= 3 Then
                        strTargetPath = Replace(strTargetPath, &quot;/&quot;, &quot;\&quot;)
                        objRegExp.Pattern = &quot;\\{2,}&quot;
                        strTargetPath = objRegExp.Replace(strTargetPath, &quot;\\&quot;)
                        objRegExp.Pattern = &quot;^&quot;&quot;|&quot;&quot;$&quot;
                        strTargetPath = objRegExp.Replace(strTargetPath, &quot;&quot;)
                        objRegExp.Pattern = &quot;^[c-z]:\\$&quot;
                        If objRegExp.Test(Left(strTargetPath, 3)) Then
                            If Len(strTargetPath) &gt; 3 Then
                                objRegExp.Pattern = &quot;[&lt;&gt;:&quot;&quot;\*\?\|]&quot;
                                If objRegExp.Test(Mid(strTargetPath, 4)) Then
                                    Call Err_Message(9, strTemp)
                                    WScript.Quit 0
                                End If
                                objRegExp.Pattern = &quot;\\$&quot;
                                strTargetPath = objRegExp.Replace(strTargetPath, &quot;&quot;)
                            End If
                            If strComputer = &quot;.&quot; Then
                                strTemp = strTargetPath
                            Else
                                strTemp = &quot;\\&quot; &amp; strComputer &amp; &quot;\&quot; &amp; Left(strTargetPath, 1) &amp; &quot;$&quot; &amp; _
                                            Mid(strTargetPath, 3)
                            End If
                            If Not objFS.FolderExists(strTemp) Then
                                Call Err_Message(8, strTemp)
                                WScript.Quit 0
                            End If
                        Else
                            Call Err_Message(9, strTemp)
                            WScript.Quit 0
                        End If
                    Else
                        Call Err_Message(9, strTemp)
                        WScript.Quit 0
                    End If
                Else
                    Call Err_Message(5, &quot;tlp&quot;)
                    WScript.Quit 0
                End If
            Case &quot;r&quot;: If Len(objDict.Item(strTemp)) &gt; 0 Then blnRecursive = True
            Case &quot;nl&quot;: If Len(objDict.Item(strTemp)) &gt; 0 Then blnCreateLog = False
            Case &quot;s&quot;: If Len(objDict.Item(strTemp)) = 0 Then blnSilent = False
        End Select
    Next
    Set objRegExp = Nothing
Else
    Set objShell = CreateObject(&quot;Shell.Application&quot;)
    Set objFolder = objShell.BrowseForFolder(0, &quot;Выбор каталога&quot;, &amp;h10 + &amp;h200, &amp;h11)
    If objFolder Is Nothing Then
        WScript.Quit 0
    Else
        strTargetPath = objFolder.Self.Path
        If MsgBox(&quot;Выполнять рекурсивный просмотр папок?&quot;, vbYesNo + vbQuestion, &quot;Очистка DACL&quot;) = vbYes Then
            blnRecursive = True
        End If
    End If
    Set objShell = Nothing
End If
If blnIsConsole And strComputer &lt;&gt; &quot;.&quot; Then
    blnAvailable = Available(strComputer)
    strTargetPath = &quot;\\&quot; &amp; strComputer &amp; &quot;\&quot; &amp; Left(strTargetPath, 1) &amp; &quot;$&quot; &amp; Mid(strTargetPath, 3)
End If
If blnAvailable Then
    If blnCreateLog Then
        strLogFile = objFS.BuildPath(objFS.GetParentFolderName(WScript.ScriptFullName), &quot;Clear_DACL.log&quot;)
        Set objFile = objFS.OpenTextFile(strLogFile, 2, True)
        &#039;objFile.WriteLine Now &amp; vbNewLine
    Else
        Set objFile = Nothing
    End If
    On Error Resume Next
    strTemp = objFS.GetDrive(objFS.GetDriveName(strTargetPath)).FileSystem
    If Err.Number &lt;&gt; 0 Then
        strTemp = vbNullString
        Err.Clear
    End If
    If UCase(strTemp) = &quot;NTFS&quot; Then
        Set objWMI = GetObject(&quot;winmgmts:{impersonationLevel=impersonate}!\\&quot; &amp; strComputer &amp; &quot;\root\cimv2&quot;)
        If Err.Number = 0 Then
            Set objFolder = objFS.GetFolder(strTargetPath)
            If Err.Number = 0 Then
                Call Clear_DACL(objWMI, objFolder, objFile, blnRecursive, blnIsConsole, blnSilent)
                If Not blnSilent Then WScript.Echo &quot;Обработка папки &quot; &amp; UCase(strTargetPath) &amp; &quot; завершена.&quot;
            Else
                blnHasError = True
                Call Err_Message(7, &quot;Ошибка &quot;  &amp; Err.Number &amp; &quot; при подключении к папке &quot; &amp; UCase(strTargetPath) &amp; _
                                vbNewLine &amp; Err.Description)
                Err.Clear
            End If
        Else
            blnHasError = True
            Call Err_Message(7, &quot;Ошибка &quot; &amp; Err.Number &amp; &quot; при подключении к WMI-пространству станции &quot;&quot;&quot; &amp; _
                            UCase(strComputer) &amp; &quot;&quot;&quot;&quot; &amp; vbNewLine &amp; Err.Description)
            Err.Clear
        End If
        Set objWMI = Nothing
    Else
        If Len(strTemp) &gt; 0 Then
            If Not objFile Is Nothing Then
                objFile.WriteLine &quot;Объекты файловой системы &quot; &amp; UCase(strTemp) &amp; &quot; не имеют DACL.&quot;
                objFile.Close
            End If
            If Not blnSilent Then WScript.Echo &quot;Объекты файловой системы &quot; &amp; UCase(strTemp) &amp; &quot; не имеют DACL.&quot;
        Else
            blnHasError = True
            Call Err_Message(7, &quot;Не удалось определить тип файловой системы тома папки &quot; &amp; UCase(strTargetPath))
        End If
    End If
    If Not objFile Is Nothing Then
        objFile.Close
        Set objFile = Nothing
    End If
    If blnCreateLog And Not blnIsConsole And Not blnHasError Then
        Set objWShell = CreateObject(&quot;WScript.Shell&quot;)
        objWShell.Run &quot;notepad.exe &quot; &amp; strLogFile, 1
        Set objWShell = Nothing
    End If
Else
    Call Err_Message(6, strComputer &amp; &quot; не существует или недоступен.&quot;)
End If
Set objFS = Nothing
WScript.Quit 0

&#039;======

Function Clear_DACL(objWMIServ, objDir, objLog, blnRec, blnCon, blnSil)
Dim objItem, objSecSettings, objSD, objACE, arrACE, strSID
Dim strPath, strTemp, blnHasInherited, blnHasError, blnIsFound, intRes, i
Const SE_DACL_PROTECTED = 4096 &#039;Флаг-признак отключенного режима наследования управляемым каталогом безопасности NTFS от &quot;родителя&quot;
Const INHERITED_ACE = 16 &#039;Флаг-признак того, что текущая запись DACL унаследована от &quot;родителя&quot;

On Error Resume Next
For Each objItem In objDir.SubFolders
    blnHasError = False: blnIsFound = False: strSID = vbNullString
    strPath = objItem.Path
    If Err.Number = 0 Then
        strTemp = strTemp &amp; UCase(strPath) &amp; vbNewLine
        i = InStr(strPath, &quot;$&quot;)
        If i &gt; 0 Then
            strPath = Replace(Mid(strPath, i - 1), &quot;$&quot;, &quot;:&quot;)
        End If
        Set objSecSettings = objWMIServ.Get(&quot;Win32_LogicalFileSecuritySetting.Path=&#039;&quot; &amp; strPath &amp; &quot;&#039;&quot;)
        If Err.Number = 0 Then
            If objSecSettings.GetSecurityDescriptor(objSD) = 0 Then
                If Err.Number = 0 Then
                    intRes = 0
                    If Not IsNull(objSD.DACL) Then
                        For Each objACE In objSD.DACL
                            If IsNull(objACE.Trustee.Name) Then
                                blnIsFound = True
                                Exit For
                            End If
                        Next
                        If blnIsFound Then
                            If CBool(objSD.ControlFlags And SE_DACL_PROTECTED) Then
                                arrACE = objSD.DACL
                            Else
                                blnHasInherited = True
                                arrACE = Array()
                                i = -1
                                &#039;--- Выборка из исходного DACL записей, не унаследованных от &quot;родителя&quot;
                                For Each objACE In objSD.DACL
                                    If CBool(objACE.AceFlags And INHERITED_ACE) Then
                                        If IsNull(objACE.Trustee.Name) Then
                                            blnHasError = True
                                            strTemp = strTemp &amp; objACE.Trustee.SIDString &amp; _
                                                        &quot; -&gt; запись унаследована от &quot;&quot;родителя&quot;&quot;.&quot; &amp; vbNewLine
                                        End If
                                    Else
                                        i = i + 1
                                        ReDim Preserve arrACE(i)
                                        Set arrACE(i) = objACE
                                    End If
                                Next
                                &#039;------
                                &#039;--- Отключение наследования настроек безопасности от &quot;родителя&quot;
                                objSD.ControlFlags = objSD.ControlFlags + SE_DACL_PROTECTED
                                intResult = objSecSettings.SetSecurityDescriptor(objSD)
                                &#039;------
                            End If
                            If intRes = 0 Then
                                &#039;--- Поиск в DACL записей, у свойства Trustee.Name которых отсутствует значение
                                For Each objACE In arrACE
                                    If IsNull(objACE.Trustee.Name) Then
                                        objACE.AccessMask = 0 &#039;назначение нулевой маски для последующего автоудаления записи
                                        strSID = strSID &amp; objACE.Trustee.SIDString &amp; &quot; -&gt; запись удалена.&quot; &amp; vbNewLine
                                    End If
                                Next
                                &#039;------
                                Set objACE = Nothing
                                objSD.DACL = arrACE &#039;собственно изменение DACL
                                Erase arrACE
                                &#039;--- Включение наследования настроек безопасности от &quot;родителя&quot;,
                                &#039;если первоначально оно было включено
                                If blnHasInherited Then
                                    objSD.ControlFlags = objSD.ControlFlags - SE_DACL_PROTECTED
                                End If
                                &#039;------
                                &#039;--- Итоговое сохраненение изменений, внесённых в дескриптор безопасности
                                intRes = objSecSettings.SetSecurityDescriptor(objSD)
                                Select Case intRes
                                    Case 0
                                        strTemp = strTemp &amp; strSID
                                        If blnHasError Then
                                            strTemp = strTemp &amp; &quot;Частично успешное завершение.&quot; &amp; vbNewLine
                                        Else
                                            strTemp = strTemp &amp; &quot;Полностью успешное завершение.&quot; &amp; vbNewLine
                                        End If
                                    Case 2: strTemp = strTemp &amp; &quot;Доступ запрещён.&quot; &amp; vbNewLine
                                    Case 5, 9, 1307: strTemp = strTemp &amp; &quot;Для выполнения операции недостаточно полномочий.&quot; &amp; vbNewLine
                                    Case 21: strTemp = strTemp &amp; &quot;Заданы недопустимые значения параметров.&quot; &amp; vbNewLine
                                    Case Else: strTemp = strTemp &amp; &quot;Неизвестная ошибка с кодом: &quot; &amp; intRes &amp; vbNewLine
                                End Select
                                &#039;------
                            Else
                                strTemp = strTemp &amp; &quot;Не удалось отключить наследование безопасности.&quot; &amp; vbNewLine
                            End If
                        Else
                            strTemp = strTemp &amp;  &quot;Очистка DACL не требуется.&quot; &amp; vbNewLine
                        End If
                    Else
                        strTemp = strTemp &amp; &quot;Список управления доступом пуст.&quot; &amp; vbNewLine
                    End If
                Else
                    strTemp = strTemp &amp; &quot;Ошибка &quot; &amp; Err.Number &amp; &quot; при выполнении метода GetSecurityDescriptor.&quot; &amp; _
                                vbNewLine &amp; Err.Description &amp; vbNewLine
                    Err.Clear
                End If
            Else
                strTemp = strTemp &amp; &quot;Не удалось прочитать дескриптор безопасности.&quot; &amp; vbNewLine
            End If
        Else
            strTemp = strTemp &amp; &quot;Ошибка &quot; &amp; Err.Number &amp; &quot; обращения к классу Win32_LogicalFileSecuritySetting &quot; &amp; _
                        &quot;при обработке папки &quot; &amp; UCase(strPath) &amp; vbNewLine
            Err.Clear
        End If
    Else
        blnHasError = True
        strTemp = strTemp &amp; &quot;Ошибка &quot; &amp; Err.Number &amp; &quot; при попытке рекурсивного просмотра папки &quot; &amp; _
                    UCase(objDir.Path) &amp; vbNewLine
        Err.Clear
    End If
    Set objSD = Nothing
    Set objSecSettings = Nothing
    If Not objLog Is Nothing Then objLog.WriteLine strTemp
    If blnCon And Not blnSil Then WScript.Echo strTemp
    strTemp = vbNullString
    If blnRec And Not blnHasError Then Call Clear_DACL(objWMIServ, objItem, objLog, blnRec, blnCon, blnSil)
Next
Set objItem = Nothing
On Error GoTo 0
End Function

&#039;======

Function Available(strName)
Dim objWShell, objExec, objOutStream, strTemp

Set objWShell = CreateObject(&quot;WScript.Shell&quot;)
Set objExec = objWShell.Exec(&quot;ping -n 1 -w 130 &quot; &amp; strName)
Set objOutStream = objExec.StdOut
While Not objOutStream.AtEndOfStream
    strTemp = strTemp &amp; Trim(objOutStream.ReadLine())
Wend
If InStr(1, strTemp, &quot;TTL&quot;, vbTextCompare) &gt; 0 Then
    Available = True
Else
    Available = False
End If
End Function

&#039;======

Function Err_Message(intNumber, strComment)
Select Case intNumber
    Case 1: WScript.Echo &quot;Недопустимый ключ или набор ключей.&quot;
    Case 2: WScript.Echo &quot;Недопустимое сочетание ключа &quot; &amp; UCase(strComment) &amp; &quot; с другими ключами.&quot;
    Case 3: WScript.Echo &quot;Недопустимый ключ &quot; &amp; UCase(strComment)
    Case 4: WScript.Echo &quot;Дублирование ключа &quot; &amp; UCase(strComment)
    Case 5: WScript.Echo &quot;Ключ &quot; &amp; UCase(strComment) &amp; &quot; является обязательным.&quot;
    Case 6: WScript.Echo &quot;Компьютер &quot; &amp; UCase(strComment)
    Case 7: WScript.Echo strComment
    Case 8: WScript.Echo &quot;Папка &quot; &amp; UCase(strComment) &amp; &quot; не найдена.&quot;
    Case 9: WScript.Echo &quot;Недопустимое значение ключа &quot; &amp; UCase(strComment)
    Case 10: WScript.Echo &quot;Ключ &quot; &amp; UCase(strComment) &amp; &quot; не требует указания значения.&quot;
    Case 11: WScript.Echo &quot;Ключ &quot; &amp; UCase(strComment) &amp; &quot; требует указания значения.&quot;
    Case Else: WScript.Echo &quot;Не классифицированная ошибка.&quot;
End Select
End Function

&#039;======

Function View_Help()
WScript.Echo &quot;Сценарий предназначен для очистки DACL подпапок заданной папки&quot; &amp; vbNewLine &amp; _
             &quot;от не олицетворённых DACL-записей, оставшихся после удаления учётных записей&quot; &amp; vbNewLine &amp; _
             &quot;пользователей или групп, которым ранее соответствовали эти DACL-записи.&quot; &amp; vbNewLine &amp; vbNewLine &amp; _
             &quot;Возможности сценария:&quot; &amp; vbNewLine &amp; _
             &quot;- обеспечение работы как в графическом, так и в консольном режимах;&quot; &amp; vbNewLine &amp; _
             &quot;- обеспечение работы с папками как локального, так и удалённого компьютера;&quot; &amp; vbNewLine &amp; _
             &quot;- поддержка рекурсивного просмотра подпапок (по умолчанию - отключена);&quot; &amp; vbNewLine &amp; _
             &quot;- ведение журнала работы (по умолчанию - включена);&quot; &amp; vbNewLine &amp; _
             &quot;- поддержка работы в &quot;&quot;молчаливом&quot;&quot; режиме (по умолчанию - отключена).&quot; &amp; vbNewLine &amp; vbNewLine &amp; _
             &quot;При работе в &quot;&quot;молчаливом&quot;&quot; режиме не выводятся никакие сообщения сценария,&quot; &amp; vbNewLine &amp; _
             &quot;кроме сообщений о ситуациях, приводящих к его аварийному завершению.&quot; &amp; vbNewLine &amp; _
             &quot;Данный режим никак не влияет на процедуру ведения журнала.&quot; &amp; vbNewLine &amp; vbNewLine &amp; _
             &quot;При работе в графическом режиме функциональность сценария имеет ограничения:&quot; &amp; vbNewLine &amp; _
             &quot;- доступна обработка папок только на тех томах, которые подключены локально;&quot; &amp; vbNewLine &amp; _
             &quot;- невозможен просмотр встроенной справки;&quot; &amp; vbNewLine &amp; _
             &quot;- невозможно отключение процедуры ведения журнала;&quot; &amp; vbNewLine &amp; _
             &quot;- работа ведётся в &quot;&quot;молчаливом&quot;&quot; режиме, но после завершения работы выводится&quot; &amp; vbNewLine &amp; _
             &quot;  содержимое файла журнала.&quot; &amp; vbNewLine &amp; vbNewLine &amp; _
             &quot;Ключи командной строки:&quot; &amp; vbNewLine &amp; _
             &quot;?&quot; &amp; vbTab &amp; vbTab &amp; &quot;- вывод справки; не совместим с другими ключами.&quot; &amp; vbNewLine &amp; _
             &quot;tc:&lt;компьютер&gt;&quot; &amp; vbTab &amp; &quot;- (&quot;&quot;Target Computer&quot;&quot;) NetBIOS-имя компьютера, на локальном томе&quot; &amp; vbNewLine &amp; _
                                        vbTab &amp; vbTab &amp; &quot;  которого размещена папка; необязательный;&quot; &amp; vbNewLine &amp; _
                                        vbTab &amp; vbTab &amp; &quot;  по умолчанию предполагается текущий компьютер.&quot; &amp; vbNewLine &amp; _
             &quot;tlp:&lt;путь&gt;&quot; &amp; vbTab &amp; &quot;- (&quot;&quot;Target Local Path&quot;&quot;) абсолютный локальный путь к папке;&quot; &amp; vbNewLine &amp; _
                                    vbTab &amp; vbTab &amp; &quot;  обязательный.&quot; &amp; vbNewLine &amp; _
             &quot;r&quot; &amp; vbTab &amp; vbTab &amp; &quot;- (&quot;&quot;Recursive&quot;&quot;) рекурсивный просмотр подпапок; необязательный;&quot; &amp; vbNewLine &amp; _
                                   vbTab &amp; vbTab &amp; &quot;  по умолчанию не выпоняется.&quot; &amp; vbNewLine &amp; _
             &quot;nl&quot; &amp; vbTab &amp; vbTab &amp; &quot;- (&quot;&quot;No Log&quot;&quot;) отключение ведения журнала; необязательный;&quot; &amp; vbNewLine &amp; _
                                    vbTab &amp; vbTab &amp; &quot;  по умолчанию журнал ведётся.&quot; &amp; vbNewLine &amp; _
             &quot;s&quot; &amp; vbTab &amp; vbTab &amp; &quot;- (&quot;&quot;Silent&quot;&quot;) &quot;&quot;молчаливый&quot;&quot; режим; необязательный;&quot; &amp; vbNewLine &amp; _
                                   vbTab &amp; vbTab &amp; &quot;  по умолчанию отключен.&quot; &amp; vbNewLine &amp; vbNewLine &amp; _
            &quot;Ключ может иметь перед собой один из префиксов: &quot;&quot;-&quot;&quot; или &quot;&quot;/&quot;&quot;. Порядок следования ключей произвольный.&quot;
End Function</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Dmitrii)]]></author>
			<pubDate>Thu, 07 Jul 2011 12:51:58 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=49725#p49725</guid>
		</item>
		<item>
			<title><![CDATA[Re: VBS &  WMI: добавить запись в DACL каталога, сохранив наследование]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=49152#p49152</link>
			<description><![CDATA[<p>В коллекцию, в тему <a href="http://forum.script-coding.com/viewtopic.php?pid=41393#p41393">VBS &amp;&nbsp; WMI: безопасность NTFS для каталога, DACL (чтение, изменение)</a>, добавлен (под номером 4) немного модифицированный вариант сценария, опубликованного в сообщении <a href="http://forum.script-coding.com/viewtopic.php?pid=48472#p48472">#2</a> данной темы.<br />Суть модификации - учёт типа записи не только при её создании, но и при удалении.</p>]]></description>
			<author><![CDATA[null@example.com (Dmitrii)]]></author>
			<pubDate>Thu, 16 Jun 2011 12:33:52 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=49152#p49152</guid>
		</item>
		<item>
			<title><![CDATA[Re: VBS &  WMI: добавить запись в DACL каталога, сохранив наследование]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=48507#p48507</link>
			<description><![CDATA[<p><strong>Евген</strong>, думаю, что отдельная ветка - это слишком &quot;жирно&quot; для нескольких сценариев (да и не могу я создавать ветки).<br />В коллекции же есть тема по управлению DACL, туда пока и буду размещать подобные сценарии. Вот и будет всё в одном месте.</p>]]></description>
			<author><![CDATA[null@example.com (Dmitrii)]]></author>
			<pubDate>Thu, 19 May 2011 11:48:28 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=48507#p48507</guid>
		</item>
		<item>
			<title><![CDATA[Re: VBS &  WMI: добавить запись в DACL каталога, сохранив наследование]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=48493#p48493</link>
			<description><![CDATA[<p><strong>Dmitrii</strong> предлагаю Вам в коллекции сделать веточку <strong><span class="bbu">VBS &amp;&nbsp; WMI: работа с DACL NTFS</span></strong><br />и там сделать сборник Ваших разработок, чтобы они все были в одном месте и можно было любую взять и воспользоваться.</p>]]></description>
			<author><![CDATA[null@example.com (Евген)]]></author>
			<pubDate>Thu, 19 May 2011 03:13:34 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=48493#p48493</guid>
		</item>
		<item>
			<title><![CDATA[Re: VBS &  WMI: добавить запись в DACL каталога, сохранив наследование]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=48472#p48472</link>
			<description><![CDATA[<p>По некотором размышлении решил сделать &quot;до кучи&quot; вариант сценария, который позволяет удалить заданную запись (не унаследованную) и сохранить при этом настройки, унаследованные от &quot;родителя&quot;.<br /></p><div class="codebox"><pre><code>Option Explicit

Dim objWsNet, strDomain, strComputer, strAccount, blnIsDomain
Dim objShell, objFolder, strPath, xResult, intTemp
Dim objWMI, objCollection, objItem, intOSVersion
Dim arrACEMasks, arrACEScopes, intACEType, intACEScope, lngACEMask
Const ACCESS_ALLOWED_ACE_TYPE = 0 &#039;Флаг-признак записи типа &quot;РАЗРЕШЕНИЕ&quot;
Const ACCESS_DENIED_ACE_TYPE = 1 &#039;Флаг-признак записи типа &quot;ЗАПРЕТ&quot;
Const OBJECT_INHERIT_ACE = 1 &#039;Флаг-признак области действия записи на текущий каталог и его файлы
Const CONTAINER_INHERIT_ACE = 2 &#039;Флаг-признак области действия записи на текущий каталог и его подкаталоги
Const REMOVE_ACE = 0 &#039;Значение маски для удаления записи из DACL
&#039;--- Допустимые значения для указания областей действия записи 
Const ANY_SCOPE = -1 &#039;Любая область действия записи
Const FOLDER_ONLY = 0 &#039;Только текущая папка
Const FOLDER_AND_FILES = 1 &#039;Текущая папка и её файлы
Const FOLDER_AND_SUBFOLDERS = 2 &#039;Текущая папка и её подпапки
Const FOLDER_SUBFOLDERS_FILES = 3 &#039;Текущая папка её подпапки и файлы
Const FILES_ONLY = 9 &#039;Только файлы текущей папки
Const SUBFOLDERS_ONLY = 10 &#039;Только подпапки текущей папки
Const SUBFOLDERS_AND_FILES = 11 &#039;Подпапки и файлы текущей папки
&#039;--- Набор типичных значений масок доступа
Const WRITE_ONLY = 278
Const READ_ONLY = 131209
Const READ_AND_EXECUTE = 131241
Const READ_WRITE = 131487
Const READ_WRITE_EXECUTE = 131519
Const MODIFY = 197055
Const MODIFY_AND_REMOVE_CHILDREN = 197119
Const CHANGE_DACL = 262144
Const ACCESS_WITHOUT_CHANGE_OWNER = 459263
Const CHANGE_OWNER = 524288
Const CHANGE_DACL_AND_OWNER = 786432
Const FULL_ACCESS = 983551
&#039;---
Const FLAG_SYNCHRONIZE = 1048576 &#039;Значение флага синхронизации доступа к объекту файловой системы
                                        &#039;(применим только для записей типа &quot;РАЗРЕШЕНИЕ&quot;)

arrACEMasks = Array(REMOVE_ACE, WRITE_ONLY, READ_ONLY, READ_AND_EXECUTE, READ_WRITE, READ_WRITE_EXECUTE, MODIFY, _
                    MODIFY_AND_REMOVE_CHILDREN, CHANGE_DACL, ACCESS_WITHOUT_CHANGE_OWNER, CHANGE_OWNER, _
                    CHANGE_DACL_AND_OWNER, FULL_ACCESS)
arrACEScopes = Array(ANY_SCOPE, FOLDER_ONLY, FOLDER_AND_FILES, FOLDER_AND_SUBFOLDERS, FOLDER_SUBFOLDERS_FILES, _
                    FILES_ONLY, SUBFOLDERS_ONLY, SUBFOLDERS_AND_FILES)
strAccount = InputBox(&quot;Имя учётной записи:&quot;, &quot;Настройка безопасности NTFS&quot;)
If Len(strAccount) &gt; 0 Then
    If StrComp(strAccount, &quot;Система&quot;, vbTextCompare) = 0 Then strAccount = &quot;System&quot;
    Set objShell = CreateObject(&quot;Shell.Application&quot;)
    Set objFolder = objShell.BrowseForFolder(0, &quot;Выбор каталога&quot;, &amp;H10 + &amp;H200, &amp;H11)
    If Not objFolder Is Nothing Then
        strPath = objFolder.Self.Path
        Set objWsNet = CreateObject(&quot;WScript.Network&quot;)
        strDomain = objWsNet.UserDomain
        strComputer = objWsNet.ComputerName
        Set objWsNet = Nothing
        Set objWMI = GetObject(&quot;winmgmts:{impersonationLevel=impersonate}!\\&quot; &amp; strComputer &amp; &quot;\root\cimv2&quot;)
        &#039;--- Определение версии ОС
        Set objCollection = objWMI.ExecQuery(&quot;SELECT Version FROM Win32_OperatingSystem&quot;)
        For Each objItem In objCollection
            intOSVersion = CInt(Replace(Left(objItem.Version, 3), &quot;.&quot;, &quot;&quot;))
        Next
        Set objItem = Nothing
        Set objCollection = Nothing
        Set objWMI = Nothing
        &#039;------    
        strAccount = Replace(strAccount, &quot;&quot;&quot;&quot;, &quot;&quot;)
        &#039;--- Настройка правильного наименования &quot;учётки&quot; локальной ОС в зависимости от версии ОС
        If intOSVersion &lt; 61 Then
            strAccount = Replace(strAccount, &quot;Система&quot;, &quot;System&quot;, 1, -1, vbTextCompare)
        Else
            strAccount = Replace(strAccount, &quot;System&quot;, &quot;Система&quot;, 1, -1, vbTextCompare)
        End If
        &#039;------
        If StrComp(strDomain, strComputer, vbTextCompare) &lt;&gt; 0 Then blnIsDomain = True        
        If StrComp(strAccount, &quot;System&quot;, vbTextCompare) = 0 Or StrComp(strAccount, &quot;Система&quot;, vbTextCompare) = 0 Or _
            StrComp(strAccount, &quot;Все&quot;, vbTextCompare) = 0 Then
            strDomain = vbNullString
        Else
            If blnIsDomain Then
                If MsgBox(&quot;Задана доменная учётная запись?&quot;, vbYesNo + vbQuestion, &quot;Настройка безопасности NTFS&quot;) = vbNo Then
                    strDomain = strComputer
                End If
            Else
                strDomain = strComputer
            End If
        End If
        
        intTemp = Trim(InputBox(&quot;Тип доступа и маска доступа в формате&quot; &amp; vbNewLine &amp; _
            &quot;+ЧИСЛО (разрешить) или -ЧИСЛО (запретить),&quot; &amp; vbNewLine &amp; _
            &quot;где ЧИСЛО:&quot; &amp; vbNewLine &amp; _
            &quot;1 - запись;&quot; &amp; vbNewLine &amp; _
            &quot;2 - только чтение;&quot; &amp; vbNewLine &amp; _
            &quot;3 - чтение и выполнение;&quot; &amp; vbNewLine &amp; _
            &quot;4 - чтение и запись (без выполнения);&quot; &amp; vbNewLine &amp; _
            &quot;5 - чтение, запись, выполнение;&quot; &amp; vbNewLine &amp; _
            &quot;6 - изменение (без удаления подпапок и файлов);&quot; &amp; vbNewLine &amp; _
            &quot;7 - изменение (с удалением подпапок и файлов);&quot; &amp; vbNewLine &amp; _
            &quot;8 - смена разрешений;&quot; &amp; vbNewLine &amp; _
            &quot;9 - почти полный доступ (без смены владельца);&quot; &amp; vbNewLine &amp; _
            &quot;10 - смена владельца;&quot; &amp; vbNewLine &amp; _
            &quot;11 - смена разрешений и владельца;&quot; &amp; vbNewLine &amp; _
            &quot;12 - полный доступ.&quot; &amp; vbNewLine &amp; vbNewLine &amp; _
            &quot;Если знак типа доступа (+/-) отсутствует,&quot; &amp; vbNewLine &amp; _
            &quot;то предполагается разрешение.&quot; &amp; vbNewLine &amp; vbNewLine &amp; _
            &quot;Для удаления записи из списка&quot; &amp; vbNewLine &amp; _
            &quot;в качестве значения маски укажите 0&quot;, &quot;Настройка безопасности NTFS&quot;))
        
        If IsNumeric(intTemp) Then
            intTemp = CInt(intTemp)
            If Abs(intTemp) &gt;= 0 And Abs(intTemp) &lt;= 12 Then
                lngACEMask = arrACEMasks(Abs(intTemp))
                If intTemp &lt; 0 Then
                    intACEType = 1
                    If intOSVersion &gt;= 52 And lngACEMask = FULL_ACCESS Then
                        lngACEMask = lngACEMask + FLAG_SYNCHRONIZE
                        &#039;Эта проверка позволяет учесть разницу между значениями маски &quot;Полный доступ&quot;
                        &#039;у записей разных типов в ОС версий &quot;2000/XP&quot;
                    End If
                ElseIf intTemp &gt; 0 Then
                    intACEType = 0
                    lngACEMask = lngACEMask + FLAG_SYNCHRONIZE
                Else
                    intACEType = 0
                End If
                intTemp = Trim(InputBox(&quot;Область действия записи:&quot; &amp; vbNewLine &amp; _
                    &quot;1 - только текущая папка;&quot; &amp; vbNewLine &amp; _
                    &quot;2 - текущая папка и её файлы;&quot; &amp; vbNewLine &amp; _
                    &quot;3 - текущая папка и её подпапки;&quot; &amp; vbNewLine &amp; _
                    &quot;4 - текущая папка, её подпапки и файлы;&quot; &amp; vbNewLine &amp; _
                    &quot;5 - только файлы текущей папки;&quot; &amp; vbNewLine &amp; _
                    &quot;6 - только подпапки текущей папки;&quot; &amp; vbNewLine &amp; _
                    &quot;7 - подпапки и файлы текущей папки.&quot; &amp; vbNewLine &amp; vbNewLine &amp; _
                    &quot;Для обработки записи с любой&quot; &amp; vbNewLine &amp; _
                    &quot;областью действия задайте значение 0&quot;, &quot;Настройка безопасности NTFS&quot;))
                If IsNumeric(intTemp) Then
                    intTemp = CInt(intTemp)
                    If intTemp &lt; 0 Or intTemp &gt; 7 Then
                        intTemp = 4
                        MsgBox &quot;Область действия задана неверно.&quot; &amp; vbNewLine &amp; _
                                &quot;Будет использована стандартная область:&quot; &amp; vbNewLine &amp; _
                                &quot;ТЕКУЩАЯ ПАПКА, ЕЁ ПОДПАПКИ И ФАЙЛЫ.&quot;, _
                                vbExclamation, &quot;Настройка безопасности NTFS&quot;
                    End If
                Else
                    intTemp = 4
                    MsgBox &quot;Область действия не задана или задана неверно.&quot; &amp; vbNewLine &amp; _
                            &quot;Будет использована стандартная область:&quot; &amp; vbNewLine &amp; _
                            &quot;ТЕКУЩАЯ ПАПКА, ЕЁ ПОДПАПКИ И ФАЙЛЫ.&quot;, _
                            vbExclamation, &quot;Настройка безопасности NTFS&quot;
                End If
                intACEScope = arrACEScopes(intTemp)
                xResult = ModifyEx2_DACL(strDomain, strComputer, strAccount, strPath, intACEType, intACEScope, lngACEMask)
            Else
                xResult = &quot;Маска доступа задана неверно.&quot;
            End If
        Else
            xResult = &quot;Тип доступа или маска доступа не заданы или заданы неверно.&quot;
        End If
        Wscript.Echo xResult
    Else
        WScript.Echo &quot;Каталог не выбран.&quot;
    End If
    Set objShell = Nothing
    Set objFolder = Nothing
Else
    WScript.Echo &quot;Учётная запись не указана.&quot;
End If
WScript.Quit 0

&#039;======

Function ModifyEx2_DACL(strDom, strWS, strSAN, strDir, intType, intScope, lngMask)
Dim objWMI, objSecSettings, objSD, blnHasInherited, blnHasACE, i
Dim xRes, arrACE, objCollection, objItem, strSID
Dim objSID, objTrustee, objACE
Const SE_DACL_PROTECTED = 4096 &#039;Флаг-признак отключенного режима наследования управляемым каталогом безопасности NTFS от &quot;родителя&quot;
Const INHERITED_ACE = 16 &#039;Флаг-признак того, что текущая запись DACL унаследована от &quot;родителя&quot;

On Error Resume Next
xRes = 0
Set objWMI = GetObject(&quot;winmgmts:{impersonationLevel=impersonate}!\\&quot; &amp; strWS &amp; &quot;\root\cimv2&quot;)
If Err.Number = 0 Then
    Set objSecSettings = objWMI.Get(&quot;Win32_LogicalFileSecuritySetting.Path=&#039;&quot; &amp; strDir &amp; &quot;&#039;&quot;)
    If Err.Number = 0 Then
        If objSecSettings.GetSecurityDescriptor(objSD) = 0 Then
            If Not IsNull(objSD.DACL) Then
                &#039;--- Поиск заданной &quot;учётки&quot; на локальном компьютере или в Active Directory
                If Len(strDom) &gt; 0 Then
                    Set objCollection = objWMI.ExecQuery(&quot;SELECT SID FROM Win32_Account WHERE Domain=&#039;&quot; &amp; strDom &amp; &quot;&#039; AND Name=&#039;&quot; &amp; strSAN &amp; &quot;&#039;&quot;)
                Else
                    Set objCollection = objWMI.ExecQuery(&quot;SELECT SID FROM Win32_Account WHERE Name=&#039;&quot; &amp; strSAN &amp; &quot;&#039;&quot;)
                End If
                &#039;------
                If objCollection.Count &gt; 0 Then
                    If Not CBool(objSD.ControlFlags And SE_DACL_PROTECTED) Then blnHasInherited = True
                    If blnHasInherited Then
                        arrACE = Array()
                        &#039;--- Выборка из исходного DACL записей, не унаследованных от &quot;родителя&quot;
                        i = -1
                        For Each objItem In objSD.DACL
                            If Not CBool(objItem.AceFlags And INHERITED_ACE) Then
                                i = i + 1
                                ReDim Preserve arrACE(i)
                                Set arrACE(i) = objItem
                            End If
                        Next
                        Set objItem = Nothing
                        &#039;------
                        &#039;--- Отключение наследования настроек безопасности от &quot;родителя&quot;
                        objSD.ControlFlags = objSD.ControlFlags + SE_DACL_PROTECTED
                        xRes = objSecSettings.SetSecurityDescriptor(objSD)
                        &#039;------
                    Else
                        arrACE = objSD.DACL
                    End If
                    If xRes = 0 Then
                        &#039;--- Определение SID &quot;учётки&quot;, назначенной для обработки
                        For Each objItem In objCollection
                            strSID = UCase(objItem.SID)
                        Next
                        Set objItem = Nothing
                        &#039;------
                        If lngMask &gt; 0 Then
                            &#039;--- Подготовка к добавлению в DACL новой записи
                            Set objSID = objWMI.Get(&quot;Win32_SID.SID=&#039;&quot; &amp; strSID &amp; &quot;&#039;&quot;)
                            Set objTrustee = objWMI.Get(&quot;Win32_Trustee&quot;).Spawninstance_()
                            objTrustee.Domain = strDom
                            objTrustee.Name = strSAN
                            objTrustee.SID = objSID.BinaryRepresentation
                            objTrustee.SidLength = objSID.SidLength
                            objTrustee.SIDString = strSID
                            Set objSID = Nothing
                            Set objACE = objWMI.Get(&quot;Win32_Ace&quot;).Spawninstance_()
                            objACE.AceType = intType
                            objACE.AceFlags = intScope
                            objACE.AccessMask = lngMask
                            objACE.Trustee = objTrustee
                            Set objTrustee = Nothing
                            i = UBound(arrACE) + 1
                            ReDim Preserve arrACE(i)
                            Set arrACE(i) = objACE
                            objSD.DACL = arrACE
                            &#039;------
                        Else
                            &#039;--- Подготовка к удалению из DACL указанной записи
                            For Each objACE In arrACE
                                blnHasACE = False
                                &#039;--- Поиск указанной записи по SID и области действия
                                If UCase(objACE.Trustee.SIDString) = strSID Then
                                    If intScope &gt;= 0 Then
                                        If objACE.AceFlags = intScope Then
                                            blnHasACE = True &#039;запись с искомыми SID и областью действия найдена
                                        End If
                                    Else
                                        blnHasACE = True &#039;запись с искомым SID найдена (область действия - любая)
                                    End If
                                    If blnHasACE Then
                                        objACE.AccessMask = 0
                                    End If
                                End If
                                &#039;------
                            Next
                            &#039;------
                        End If
                        objSD.DACL = arrACE &#039;Собственно изменение DACL
                        Set objACE = Nothing
                        Erase arrACE
                        If blnHasInherited Then
                            &#039;--- Включение наследования настроек безопасности от &quot;родителя&quot;,
                            &#039;если первоначально оно было включено
                            objSD.ControlFlags = objSD.ControlFlags - SE_DACL_PROTECTED
                            &#039;------
                        End If
                        &#039;--- Итоговое сохраненение изменений, внесённых в дескриптор безопасности
                        xRes = objSecSettings.SetSecurityDescriptor(objSD)
                        Select Case xRes
                            Case 0: xRes = &quot;Успешное завершение.&quot;
                            Case 2: xRes = &quot;Не удалось сохранить изменения DACL.&quot; &amp; vbNewLine &amp; &quot;Доступ запрещён.&quot;
                            Case 5, 9: xRes = &quot;Не удалось сохранить изменения DACL.&quot; &amp; vbNewLine &amp; &quot;Для выполнения операции недостаточно полномочий.&quot;
                            Case 21: xRes = &quot;Не удалось сохранить изменения DACL.&quot; &amp; vbNewLine &amp; &quot;Заданы недопустимые значения параметров.&quot;
                            Case Else: xRes = &quot;Не удалось сохранить изменения DACL.&quot; &amp; vbNewLine &amp; &quot;Неизвестная ошибка.&quot;
                        End Select
                        &#039;------
                    Else
                        xRes = &quot;Не удалось отключить наследование безопасности для папки &quot; &amp; UCase(strDir)
                    End If
                Else
                    xRes = &quot;Не найдена учётная запись объекта &quot; &amp; UCase(strDom &amp; &quot;\&quot; &amp; strSAN)
                End If
                Set objCollection = Nothing
            Else
                xRes = &quot;Список управления доступом (ACL) к заданному объекту пуст.&quot;
            End If
        Else
            xRes = &quot;Не удалось прочитать дескриптор безопасности объекта.&quot;
        End If
        Set objSD = Nothing
        Set objSecSettings = Nothing
    Else
        xRes = &quot;Ошибка &quot; &amp; CStr(Err.Number) &amp; vbNewLine &amp; Err.Description
        Err.Clear
    End If
Else
    xRes = &quot;Ошибка &quot; &amp; CStr(Err.Number) &amp; vbNewLine &amp; Err.Description
    Err.Clear
End If
Set objWMI = Nothing
On Error GoTo 0
ModifyEx2_DACL = xRes
End Function</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Dmitrii)]]></author>
			<pubDate>Wed, 18 May 2011 10:34:16 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=48472#p48472</guid>
		</item>
		<item>
			<title><![CDATA[VBS &  WMI: добавить запись в DACL каталога, сохранив наследование]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=47878#p47878</link>
			<description><![CDATA[<p>В качестве развития темы <a href="http://forum.script-coding.com/viewtopic.php?id=5142">VBS &amp;&nbsp; WMI: безопасность NTFS для каталога, DACL (чтение, изменение)</a> предлагаю для тестирования сценарий, с помощью которого можно добавлять произвольную запись в DACL заданного каталога, сохраняя при этом записи унаследованные от &quot;родителя&quot;.<br /></p><div class="codebox"><pre><code>Option Explicit

Dim objWsNet, strDomain, strComputer, strAccount, blnIsDomain
Dim objShell, objFolder, strPath, xResult, intTemp
Dim objWMI, objCollection, objItem, intOSVersion
Dim arrACEMasks, arrACEScopes, intACEType, intACEScope, lngACEMask
Const ACCESS_ALLOWED_ACE_TYPE = 0 &#039;Флаг-признак записи типа &quot;РАЗРЕШЕНИЕ&quot;
Const ACCESS_DENIED_ACE_TYPE = 1 &#039;Флаг-признак записи типа &quot;ЗАПРЕТ&quot;
Const OBJECT_INHERIT_ACE = 1 &#039;Флаг-признак области действия записи на текущий каталог и его файлы
Const CONTAINER_INHERIT_ACE = 2 &#039;Флаг-признак области действия записи на текущий каталог и его подкаталоги
&#039;--- Допустимые значения для указания областей действия записи 
Const FOLDER_ONLY = 0 &#039;Только текущая папка
Const FOLDER_AND_FILES = 1 &#039;Текущая папка и её файлы
Const FOLDER_AND_SUBFOLDERS = 2 &#039;Текущая папка и её подпапки
Const FOLDER_SUBFOLDERS_FILES = 3 &#039;Текущая папка её подпапки и файлы
Const FILES_ONLY = 9 &#039;Только файлы текущей папки
Const SUBFOLDERS_ONLY = 10 &#039;Только подпапки текущей папки
Const SUBFOLDERS_AND_FILES = 11 &#039;Подпапки и файлы текущей папки
&#039;--- Набор типичных значений масок доступа
Const WRITE_ONLY = 278
Const READ_ONLY = 131209
Const READ_AND_EXECUTE = 131241
Const READ_WRITE = 131487
Const READ_WRITE_EXECUTE = 131519
Const MODIFY = 197055
Const MODIFY_AND_REMOVE_CHILDREN = 197119
Const CHANGE_DACL = 262144
Const ACCESS_WITHOUT_CHANGE_OWNER = 459263
Const CHANGE_OWNER = 524288
Const CHANGE_DACL_AND_OWNER = 786432
Const FULL_ACCESS = 983551
&#039;---
Const FLAG_SYNCHRONIZE = 1048576 &#039;Значение флага синхронизации доступа к объекту файловой системы
                                        &#039;(применим только для записей типа &quot;РАЗРЕШЕНИЕ&quot;)

arrACEMasks = Array(WRITE_ONLY, READ_ONLY, READ_AND_EXECUTE, READ_WRITE, READ_WRITE_EXECUTE, MODIFY, _
                    MODIFY_AND_REMOVE_CHILDREN, CHANGE_DACL, ACCESS_WITHOUT_CHANGE_OWNER, CHANGE_OWNER, _
                    CHANGE_DACL_AND_OWNER, FULL_ACCESS)
arrACEScopes = Array(FOLDER_ONLY, FOLDER_AND_FILES, FOLDER_AND_SUBFOLDERS, FOLDER_SUBFOLDERS_FILES, _
                    FILES_ONLY, SUBFOLDERS_ONLY, SUBFOLDERS_AND_FILES)
strAccount = InputBox(&quot;Имя учётной записи:&quot;, &quot;Настройка безопасности NTFS&quot;)
If Len(strAccount) &gt; 0 Then
    If StrComp(strAccount, &quot;Система&quot;, vbTextCompare) = 0 Then strAccount = &quot;System&quot;
    Set objShell = CreateObject(&quot;Shell.Application&quot;)
    Set objFolder = objShell.BrowseForFolder(0, &quot;Выбор каталога&quot;, &amp;H10 + &amp;H200, &amp;H11)
    If Not objFolder Is Nothing Then
        strPath = objFolder.Self.Path
        Set objWsNet = CreateObject(&quot;WScript.Network&quot;)
        strDomain = objWsNet.UserDomain
        strComputer = objWsNet.ComputerName
        Set objWsNet = Nothing
        Set objWMI = GetObject(&quot;winmgmts:{impersonationLevel=impersonate}!\\&quot; &amp; strComputer &amp; &quot;\root\cimv2&quot;)
        &#039;--- Определение версии ОС
        Set objCollection = objWMI.ExecQuery(&quot;SELECT Version FROM Win32_OperatingSystem&quot;)
        For Each objItem In objCollection
            intOSVersion = CInt(Replace(Left(objItem.Version, 3), &quot;.&quot;, &quot;&quot;))
        Next
        Set objItem = Nothing
        Set objCollection = Nothing
        Set objWMI = Nothing
        &#039;------    
        strAccount = Replace(strAccount, &quot;&quot;&quot;&quot;, &quot;&quot;)
        &#039;--- Настройка правильного наименования &quot;учётки&quot; локальной ОС в зависимости от версии ОС
        If intOSVersion &lt; 61 Then
            strAccount = Replace(strAccount, &quot;Система&quot;, &quot;System&quot;, 1, -1, vbTextCompare)
        Else
            strAccount = Replace(strAccount, &quot;System&quot;, &quot;Система&quot;, 1, -1, vbTextCompare)
        End If
        &#039;------
        If StrComp(strDomain, strComputer, vbTextCompare) &lt;&gt; 0 Then blnIsDomain = True        
        If StrComp(strAccount, &quot;System&quot;, vbTextCompare) = 0 Or StrComp(strAccount, &quot;Система&quot;, vbTextCompare) = 0 Or _
            StrComp(strAccount, &quot;Все&quot;, vbTextCompare) = 0 Then
            strDomain = vbNullString
        Else
            If blnIsDomain Then
                If MsgBox(&quot;Задана доменная учётная запись?&quot;, vbYesNo + vbQuestion, &quot;Настройка безопасности NTFS&quot;) = vbNo Then
                    strDomain = strComputer
                End If
            Else
                strDomain = strComputer
            End If
        End If
        
        intTemp = Trim(InputBox(&quot;Тип доступа и маска доступа в формате&quot; &amp; vbNewLine &amp; _
            &quot;+ЧИСЛО (разрешить) или -ЧИСЛО (запретить),&quot; &amp; vbNewLine &amp; _
            &quot;где ЧИСЛО:&quot; &amp; vbNewLine &amp; _
            &quot;1 - запись;&quot; &amp; vbNewLine &amp; _
            &quot;2 - только чтение;&quot; &amp; vbNewLine &amp; _
            &quot;3 - чтение и выполнение;&quot; &amp; vbNewLine &amp; _
            &quot;4 - чтение и запись (без выполнения);&quot; &amp; vbNewLine &amp; _
            &quot;5 - чтение, запись, выполнение;&quot; &amp; vbNewLine &amp; _
            &quot;6 - изменение (без удаления подпапок и файлов);&quot; &amp; vbNewLine &amp; _
            &quot;7 - изменение (с удалением подпапок и файлов);&quot; &amp; vbNewLine &amp; _
            &quot;8 - смена разрешений;&quot; &amp; vbNewLine &amp; _
            &quot;9 - почти полный доступ (без смены владельца);&quot; &amp; vbNewLine &amp; _
            &quot;10 - смена владельца;&quot; &amp; vbNewLine &amp; _
            &quot;11 - смена разрешений и владельца;&quot; &amp; vbNewLine &amp; _
            &quot;12 - полный доступ.&quot; &amp; vbNewLine &amp; vbNewLine &amp; _
            &quot;Если знак типа доступа (+/-) отсутствует,&quot; &amp; vbNewLine &amp; _
            &quot;то предполагается разрешение.&quot;, &quot;Настройка безопасности NTFS&quot;))
        
        If IsNumeric(intTemp) Then
            intTemp = CInt(intTemp)
            If Abs(intTemp) - 1 &gt;= 0 And Abs(intTemp) - 1 &lt;= 11 Then
                lngACEMask = arrACEMasks(Abs(intTemp) - 1)
                If intTemp &lt; 0 Then
                    intACEType = 1
                    If intOSVersion &gt;= 52 And lngACEMask = FULL_ACCESS Then
                        lngACEMask = lngACEMask + FLAG_SYNCHRONIZE
                        &#039;Эта проверка позволяет учесть разницу между значениями маски &quot;Полный доступ&quot;
                        &#039;у записей разных типов в ОС версий &quot;2000/XP&quot;
                    End If
                ElseIf intTemp &gt; 0 Then
                    intACEType = 0
                    lngACEMask = lngACEMask + FLAG_SYNCHRONIZE
                Else
                    intACEType = 0
                End If
                intTemp = Trim(InputBox(&quot;Область действия записи:&quot; &amp; vbNewLine &amp; _
                    &quot;1 - только текущая папка;&quot; &amp; vbNewLine &amp; _
                    &quot;2 - текущая папка и её файлы;&quot; &amp; vbNewLine &amp; _
                    &quot;3 - текущая папка и её подпапки;&quot; &amp; vbNewLine &amp; _
                    &quot;4 - текущая папка, её подпапки и файлы;&quot; &amp; vbNewLine &amp; _
                    &quot;5 - только файлы текущей папки;&quot; &amp; vbNewLine &amp; _
                    &quot;6 - только подпапки текущей папки;&quot; &amp; vbNewLine &amp; _
                    &quot;7 - подпапки и файлы текущей папки.&quot;, &quot;Настройка безопасности NTFS&quot;))
                If IsNumeric(intTemp) Then
                    intTemp = CInt(intTemp)
                    If intTemp &lt; 1 Or intTemp &gt; 7 Then
                        intTemp = 4
                        MsgBox &quot;Область действия задана неверно.&quot; &amp; vbNewLine &amp; _
                                &quot;Будет использована стандартная область:&quot; &amp; vbNewLine &amp; _
                                &quot;ТЕКУЩАЯ ПАПКА, ЕЁ ПОДПАПКИ И ФАЙЛЫ.&quot;, _
                                vbExclamation, &quot;Настройка безопасности NTFS&quot;
                    End If
                Else
                    intTemp = 4
                    MsgBox &quot;Область действия не задана или задана неверно.&quot; &amp; vbNewLine &amp; _
                            &quot;Будет использована стандартная область:&quot; &amp; vbNewLine &amp; _
                            &quot;ТЕКУЩАЯ ПАПКА, ЕЁ ПОДПАПКИ И ФАЙЛЫ.&quot;, _
                            vbExclamation, &quot;Настройка безопасности NTFS&quot;
                End If
                intACEScope = arrACEScopes(intTemp - 1)
                xResult = ModifyEx_DACL(strDomain, strComputer, strAccount, strPath, intACEType, intACEScope, lngACEMask)
            Else
                xResult = &quot;Маска доступа задана неверно.&quot;
            End If
        Else
            xResult = &quot;Тип доступа или маска доступа не заданы или заданы неверно.&quot;
        End If
        Wscript.Echo xResult
    Else
        WScript.Echo &quot;Каталог не выбран.&quot;
    End If
    Set objShell = Nothing
    Set objFolder = Nothing
Else
    WScript.Echo &quot;Учётная запись не указана.&quot;
End If
WScript.Quit 0

&#039;======

Function ModifyEx_DACL(strDom, strWS, strSAN, strDir, intType, intScope, lngMask)
Dim objWMI, objSecSettings, objSD, blnHasInherited, i
Dim xRes, arrACE, objCollection, objItem, strSID
Dim objSID, objTrustee, objNewACE
Const SE_DACL_PROTECTED = 4096 &#039;Флаг-признак отключенного режима наследования управляемым каталогом безопасности NTFS от &quot;родителя&quot;
Const INHERITED_ACE = 16 &#039;Флаг-признак того, что текущая запись DACL унаследована от &quot;родителя&quot;

On Error Resume Next
xRes = 0
Set objWMI = GetObject(&quot;winmgmts:{impersonationLevel=impersonate}!\\&quot; &amp; strWS &amp; &quot;\root\cimv2&quot;)
If Err.Number = 0 Then
    Set objSecSettings = objWMI.Get(&quot;Win32_LogicalFileSecuritySetting.Path=&#039;&quot; &amp; strDir &amp; &quot;&#039;&quot;)
    If Err.Number = 0 Then
        If objSecSettings.GetSecurityDescriptor(objSD) = 0 Then
            If Not IsNull(objSD.DACL) Then
                &#039;--- Поиск заданной &quot;учётки&quot; на локальном компьютере или в Active Directory
                If Len(strDom) &gt; 0 Then
                    Set objCollection = objWMI.ExecQuery(&quot;SELECT SID FROM Win32_Account WHERE Domain=&#039;&quot; &amp; strDom &amp; &quot;&#039; AND Name=&#039;&quot; &amp; strSAN &amp; &quot;&#039;&quot;)
                Else
                    Set objCollection = objWMI.ExecQuery(&quot;SELECT SID FROM Win32_Account WHERE Name=&#039;&quot; &amp; strSAN &amp; &quot;&#039;&quot;)
                End If
                &#039;------
                If objCollection.Count &gt; 0 Then
                    If Not CBool(objSD.ControlFlags And SE_DACL_PROTECTED) Then blnHasInherited = True
                    If blnHasInherited Then
                        arrACE = Array()
                        &#039;--- Выборка из исходного DACL записей, не унаследованных от &quot;родителя&quot;
                        i = -1
                        For Each objItem In objSD.DACL
                            If Not CBool(objItem.AceFlags And INHERITED_ACE) Then
                                i = i + 1
                                ReDim Preserve arrACE(i)
                                Set arrACE(i) = objItem
                            End If
                        Next
                        Set objItem = Nothing
                        &#039;------
                        &#039;--- Отключение наследования настроек безопасности от &quot;родителя&quot;
                        objSD.ControlFlags = objSD.ControlFlags + SE_DACL_PROTECTED
                        xRes = objSecSettings.SetSecurityDescriptor(objSD)
                        &#039;------
                    Else
                        arrACE = objSD.DACL
                    End If
                    If xRes = 0 Then
                        &#039;--- Определение SID &quot;учётки&quot;, назначенной для добавления в DACL
                        For Each objItem In objCollection
                            strSID = UCase(objItem.SID)
                        Next
                        Set objItem = Nothing
                        &#039;------
                        &#039;--- Добавление в DACL новой записи
                        Set objSID = objWMI.Get(&quot;Win32_SID.SID=&#039;&quot; &amp; strSID &amp; &quot;&#039;&quot;)
                        Set objTrustee = objWMI.Get(&quot;Win32_Trustee&quot;).Spawninstance_()
                        objTrustee.Domain = strDom
                        objTrustee.Name = strSAN
                        objTrustee.SID = objSID.BinaryRepresentation
                        objTrustee.SidLength = objSID.SidLength
                        objTrustee.SIDString = strSID
                        Set objSID = Nothing
                        Set objNewACE = objWMI.Get(&quot;Win32_Ace&quot;).Spawninstance_()
                        objNewACE.AceType = intType
                        objNewACE.AceFlags = intScope
                        objNewACE.AccessMask = lngMask
                        objNewACE.Trustee = objTrustee
                        Set objTrustee = Nothing
                        i = UBound(arrACE) + 1
                        ReDim Preserve arrACE(i)
                        Set arrACE(i) = objNewACE
                        objSD.DACL = arrACE
                        Set objNewACE = Nothing
                        Erase arrACE
                        &#039;------
                        If blnHasInherited Then
                            &#039;--- Включение наследования настроек безопасности от &quot;родителя&quot;,
                            &#039;если первоначально оно было включено
                            objSD.ControlFlags = objSD.ControlFlags - SE_DACL_PROTECTED
                            &#039;------
                        End If
                        &#039;--- Итоговое сохраненение изменений, внесённых в дескриптор безопасности
                        xRes = objSecSettings.SetSecurityDescriptor(objSD)
                        Select Case xRes
                            Case 0: xRes = &quot;Успешное завершение.&quot;
                            Case 2: xRes = &quot;Не удалось сохранить изменения DACL.&quot; &amp; vbNewLine &amp; &quot;Доступ запрещён.&quot;
                            Case 5, 9: xRes = &quot;Не удалось сохранить изменения DACL.&quot; &amp; vbNewLine &amp; &quot;Для выполнения операции недостаточно полномочий.&quot;
                            Case 21: xRes = &quot;Не удалось сохранить изменения DACL.&quot; &amp; vbNewLine &amp; &quot;Заданы недопустимые значения параметров.&quot;
                            Case Else: xRes = &quot;Не удалось сохранить изменения DACL.&quot; &amp; vbNewLine &amp; &quot;Неизвестная ошибка.&quot;
                        End Select
                        &#039;------
                    Else
                        xRes = &quot;Не удалось отключить наследование безопасности для папки &quot; &amp; UCase(strDir)
                    End If
                Else
                    xRes = &quot;Не найдена учётная запись объекта &quot; &amp; UCase(strDom &amp; &quot;\&quot; &amp; strSAN)
                End If
                Set objCollection = Nothing
            Else
                xRes = &quot;Список управления доступом (ACL) к заданному объекту пуст.&quot;
            End If
        Else
            xRes = &quot;Не удалось прочитать дескриптор безопасности объекта.&quot;
        End If
        Set objSD = Nothing
        Set objSecSettings = Nothing
    Else
        xRes = &quot;Ошибка &quot; &amp; CStr(Err.Number) &amp; vbNewLine &amp; Err.Description
        Err.Clear
    End If
Else
    xRes = &quot;Ошибка &quot; &amp; CStr(Err.Number) &amp; vbNewLine &amp; Err.Description
    Err.Clear
End If
Set objWMI = Nothing
On Error GoTo 0
ModifyEx_DACL = xRes
End Function</code></pre></div><p>Примечания.<br />1. С помощью сценария можно добавлять запись в DACL и того каталога, у которого включено наследование от &quot;родителя&quot;, и того - у которого отключено.<br />2. Сценарий не позволяет удалять записей.<br />3. Имеется возможность задавать область действия добавляемой записи.<br />4. Для работы сценария необходимо задать NetBIOS-имя учётной записи, для которой необходимо добавить запись в DACL.<br />Можно указать имя объекта либо доменного, либо локального (для текущего компьютера) уровня. Допустимо указание имён ряда встроенных локальных объектов: &quot;System&quot; (или &quot;Система&quot;), &quot;Все&quot;, &quot;Администратор(ы)&quot;, &quot;Гост(ь)(и)&quot; и т.п. Имена объектов можно задавать как в кавычках, так и без них.<br />5. Сценарий требует привилегий локального администратора.<br />6. Сценарий не проверяет ни рациональности, ни, тем более, осмысленности заданного действия.<br />7. Работа сценария проверена в 32-битных версиях: 2000 Pro. + SP4/XP Pro. + SP3/2003 Std. R2 + SP2/2008 Std. + SP2/7 Pro.<br />8. Сценарий ориентирован на использование в русифицированных ОС и работу в графическом режиме.</p>]]></description>
			<author><![CDATA[null@example.com (Dmitrii)]]></author>
			<pubDate>Wed, 27 Apr 2011 13:07:33 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=47878#p47878</guid>
		</item>
	</channel>
</rss>
