I am trying to create a program to delete orphaned SIDs from user folders. What I have can enumerate the orphaned SIDs and list them in a listbox but doesn't purge them from the ACL. Here is what I have so far:
Imports System.ComponentModel
Imports System.IO
Imports System.Security.AccessControl
Imports System.Security.Principal
Imports System.Threading
Public Class Form1
Dim bw As BackgroundWorker = New BackgroundWorker
Public Delegate Sub PictureVisibilityDelegate(ByVal visibility As Boolean)
Dim ChangePictureVisibility As PictureVisibilityDelegate
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
AddHandler bw.DoWork, AddressOf bw_DoWork
AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted
ChangePictureVisibility = AddressOf ChangeVisibility
TextBox1.Focus()
End Sub
Private Sub BtnGo_Click(sender As Object, e As EventArgs) Handles BtnGo.Click
Me.Invoke(ChangePictureVisibility, True)
Me.BtnGo.Enabled = False
Me.BtnClear.Enabled = False
Me.BtnExit.Enabled = True
If Not bw.IsBusy = True Then
bw.RunWorkerAsync()
End If
End Sub
Private Sub FoldBrowse_Click(sender As Object, e As EventArgs) Handles FoldBrowse.Click
If FolderBrowserDialog1.ShowDialog() = DialogResult.OK Then
Me.TextBox1.Text = FolderBrowserDialog1.SelectedPath
End If
End Sub
Private Sub BtnClear_Click(sender As Object, e As EventArgs) Handles BtnClear.Click
TextBox1.Text = ""
End Sub
Private Sub BtnExit_Click(sender As Object, e As EventArgs) Handles BtnExit.Click
If bw.IsBusy Then
If bw.WorkerSupportsCancellation Then
bw.CancelAsync()
End If
End If
Me.BtnExit.Enabled = False
Me.Close()
End Sub
Private Sub bw_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
CheckForIllegalCrossThreadCalls = False
Dim setFolder As String = TextBox1.Text
HandleDir(setFolder)
End Sub
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
WaitStatus.Close()
Me.BtnGo.Enabled = True
Me.BtnClear.Enabled = True
Me.Refresh()
MessageBox.Show("Orphaned SID Cleaner has finished cleaning your selection.", "Orphaned SID Cleaner", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, MessageBoxOptions.ServiceNotification, False)
End Sub
Public Function FileInUse(ByVal sFile As String) As Boolean
If System.IO.File.Exists(sFile) Then
Try
Dim F As Short = FreeFile()
FileOpen(F, sFile, OpenMode.Binary, OpenAccess.ReadWrite, OpenShare.LockReadWrite)
FileClose(F)
Catch
Return True
End Try
End If
End Function
Sub HandleDir(Path As String)
Dim dinfo As New DirectoryInfo(TextBox1.Text)
Dim dSecurity As DirectorySecurity = dinfo.GetAccessControl(AccessControlSections.All)
Try
If FileInUse("c:\orphansid.txt") = True Then
Thread.Sleep(2)
My.Computer.FileSystem.WriteAllText("c:\orphansid.txt", "Scanning:" & Path & vbCrLf, True)
Else
My.Computer.FileSystem.WriteAllText("c:\orphansid.txt", "Scanning:" & Path & vbCrLf, True)
Thread.Sleep(2)
End If
Dim security As DirectorySecurity = Directory.GetAccessControl(Path)
Dim rules = security.GetAccessRules(True, False, GetType(SecurityIdentifier))
Dim removeList = New List(Of IdentityReference)()
For Each rule In rules.OfType(Of FileSystemAccessRule)()
Try
Dim account = rule.IdentityReference.Translate(GetType(NTAccount))
Catch generatedExceptionName As IdentityNotMappedException
If Not removeList.Any(Function(sid) sid.Value = rule.IdentityReference.Value) Then
removeList.Add(rule.IdentityReference)
End If
End Try
Next
For Each id In removeList
If FileInUse("c:\orphansid.txt") = True Then
Thread.Sleep(2)
ListBox1.Items.Add("Removed the following SID:" & id.ToString & " From " & Path & vbCrLf)
My.Computer.FileSystem.WriteAllText("c:\orphansid.txt", "Removed the following SID:" & id.ToString & " From " & Path & vbCrLf, True)
Else
ListBox1.Items.Add("Removed the following SID:" & id.ToString & " From " & Path & vbCrLf)
My.Computer.FileSystem.WriteAllText("c:\orphansid.txt", "Removed the following SID:" & id.ToString & " From " & Path & vbCrLf, True)
Thread.Sleep(2)
End If
Dim DirACLs As New Security.AccessControl.DirectorySecurity(Path, AccessControlSections.All)
DirACLs.PurgeAccessRules(id)
dinfo.SetAccessControl(dSecurity)
Next
For Each subdir As String In System.IO.Directory.GetDirectories(Path)
HandleDir(subdir)
Next subdir
Catch ex As System.Exception
End Try
End Sub
Public Sub ChangeVisibility(ByVal visibility As Boolean)
WaitStatus.Show()
End Sub
End Class
The part that is not purging the SID is:
For Each id In removeList
If FileInUse("c:\orphansid.txt") = True Then
Thread.Sleep(2)
ListBox1.Items.Add("Removed the following SID:" & id.ToString & " From " & Path & vbCrLf)
My.Computer.FileSystem.WriteAllText("c:\orphansid.txt", "Removed the following SID:" & id.ToString & " From " & Path & vbCrLf, True)
Else
ListBox1.Items.Add("Removed the following SID:" & id.ToString & " From " & Path & vbCrLf)
My.Computer.FileSystem.WriteAllText("c:\orphansid.txt", "Removed the following SID:" & id.ToString & " From " & Path & vbCrLf, True)
Thread.Sleep(2)
End If
Dim DirACLs As New Security.AccessControl.DirectorySecurity(Path, AccessControlSections.All)
DirACLs.PurgeAccessRules(id)
dinfo.SetAccessControl(dSecurity)
Next
I want the program to purge the orphaned SID and then list it in the listbox and have the ability to copy the list of orphaned SIDs to the clipboard.
Can someone help me find out why this isn't working the way I want it to work and/or find an alternate solution?
What I have tried:
I have tried the code listed above and it successfully enumerates the orphaned SIDs and adds them to the listbox in the format I want but it does not purge the orphaned SIDs.