Merged r16363:16600 from trunk.
Modified: branches/cache_manager_rewrite/reactos/lib/aclui/aclui.c
Modified: branches/cache_manager_rewrite/reactos/lib/aclui/aclui.xml
Modified: branches/cache_manager_rewrite/reactos/lib/aclui/aclui_De.rc
Modified: branches/cache_manager_rewrite/reactos/lib/aclui/aclui_En.rc
Modified: branches/cache_manager_rewrite/reactos/lib/aclui/aclui_Sv.rc
Added: branches/cache_manager_rewrite/reactos/lib/aclui/acluilib.h
Added: branches/cache_manager_rewrite/reactos/lib/aclui/checklist.c
Deleted: branches/cache_manager_rewrite/reactos/lib/aclui/internal.h
Added: branches/cache_manager_rewrite/reactos/lib/aclui/misc.c
Modified: branches/cache_manager_rewrite/reactos/lib/aclui/resource.h
Property changes on: branches/cache_manager_rewrite/reactos/lib/aclui
___________________________________________________________________
Name: svn:ignore
   - *.coff
*.dll
*.d
*.a
*.o
*.sym
*.map
*.tmp
makefile
   + *.coff
*.dll
*.d
*.a
*.o
*.sym
*.map
*.tmp
*.gch
makefile

Modified: branches/cache_manager_rewrite/reactos/lib/aclui/aclui.c
--- branches/cache_manager_rewrite/reactos/lib/aclui/aclui.c	2005-08-14 16:42:46 UTC (rev 17385)
+++ branches/cache_manager_rewrite/reactos/lib/aclui/aclui.c	2005-08-14 17:10:07 UTC (rev 17386)
@@ -21,100 +21,719 @@
  * PROJECT:         ReactOS Access Control List Editor
  * FILE:            lib/aclui/aclui.c
  * PURPOSE:         Access Control List Editor
- * PROGRAMMER:      Thomas Weidenmueller (w3seek@users.sourceforge.net)
+ * PROGRAMMER:      Thomas Weidenmueller <w3seek@reactos.com>
  *
  * UPDATE HISTORY:
  *      08/10/2004  Created
  */
-#define INITGUID
-#include <windows.h>
-#include <commctrl.h>
-#include <prsht.h>
-#include <aclui.h>
-#include "internal.h"
-#include "resource.h"
+#include "acluilib.h"
 
 HINSTANCE hDllInstance;
 
-UINT CALLBACK
-SecurityPageCallback(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
+static VOID
+DestroySecurityPage(IN PSECURITY_PAGE sp)
 {
-  switch(uMsg)
-  {
-    case PSPCB_CREATE:
+    if(sp->hiUsrs != NULL)
     {
-      PSECURITY_PAGE sp;
+        ImageList_Destroy(sp->hiUsrs);
+    }
 
-      sp = LocalAlloc(LHND, sizeof(SECURITY_PAGE));
-      if(sp != NULL)
-      {
-        /* save the pointer to the ISecurityInformation interface */
-        sp->psi = (LPSECURITYINFO)ppsp->lParam;
-        /* set the lParam to the allocated structure */
-        ppsp->lParam = (LPARAM)sp;
-        return TRUE;
-      }
-      return FALSE;
+    HeapFree(GetProcessHeap(),
+             0,
+             sp);
+}
+
+static VOID
+FreeAceList(IN PACE_LISTITEM *AceListHead)
+{
+    PACE_LISTITEM CurItem, NextItem;
+    
+    CurItem = *AceListHead;
+    while (CurItem != NULL)
+    {
+        /* free the SID string if present */
+        if (CurItem->DisplayString != NULL)
+        {
+            LocalFree((HLOCAL)CurItem->DisplayString);
+        }
+
+        /* free the ACE list item */
+        NextItem = CurItem->Next;
+        HeapFree(GetProcessHeap(),
+                 0,
+                 CurItem);
+        CurItem = NextItem;
     }
-    case PSPCB_RELEASE:
+    
+    *AceListHead = NULL;
+}
+
+static PACE_LISTITEM
+FindSidInAceList(IN PACE_LISTITEM AceListHead,
+                 IN PSID Sid)
+{
+    PACE_LISTITEM CurItem;
+    
+    for (CurItem = AceListHead;
+         CurItem != NULL;
+         CurItem = CurItem->Next)
     {
-      if(ppsp->lParam != 0)
-      {
-        PSECURITY_PAGE sp = (PSECURITY_PAGE)ppsp->lParam;
-        if(sp->hiUsrs != NULL)
+        if (EqualSid((PSID)(CurItem + 1),
+                     Sid))
         {
-          ImageList_Destroy(sp->hiUsrs);
+            return CurItem;
         }
-        LocalFree((HLOCAL)sp);
-      }
-      return FALSE;
     }
-  }
+    
+    return NULL;
+}
 
-  return FALSE;
+static VOID
+ReloadUsersGroupsList(IN PSECURITY_PAGE sp)
+{
+    PSECURITY_DESCRIPTOR SecurityDescriptor;
+    BOOL DaclPresent, DaclDefaulted;
+    PACL Dacl = NULL;
+    HRESULT hRet;
+
+    /* delete the cached ACL */
+    FreeAceList(&sp->AceListHead);
+
+    /* query the ACL */
+    hRet = sp->psi->lpVtbl->GetSecurity(sp->psi,
+                                        DACL_SECURITY_INFORMATION,
+                                        &SecurityDescriptor,
+                                        FALSE);
+    if (SUCCEEDED(hRet) && SecurityDescriptor != NULL)
+    {
+        if (GetSecurityDescriptorDacl(SecurityDescriptor,
+                                      &DaclPresent,
+                                      &Dacl,
+                                      &DaclDefaulted))
+        {
+            PACE_LISTITEM AceListItem, *NextAcePtr;
+            PSID Sid;
+            PVOID Ace;
+            ULONG AceIndex;
+            DWORD AccountNameSize, DomainNameSize, SidLength;
+            SID_NAME_USE SidNameUse;
+            DWORD LookupResult;
+            
+            NextAcePtr = &sp->AceListHead;
+            
+            for (AceIndex = 0;
+                 AceIndex < Dacl->AceCount;
+                 AceIndex++)
+            {
+                GetAce(Dacl,
+                       AceIndex,
+                       &Ace);
+
+                Sid = (PSID)&((PACCESS_ALLOWED_ACE)Ace)->SidStart;
+
+                if (!FindSidInAceList(sp->AceListHead,
+                                      Sid))
+                {
+                    SidLength = GetLengthSid(Sid);
+                    
+                    AccountNameSize = 0;
+                    DomainNameSize = 0;
+
+                    /* calculate the size of the buffer we need to calculate */
+                    LookupAccountSid(sp->ServerName,
+                                     Sid,
+                                     NULL,
+                                     &AccountNameSize,
+                                     NULL,
+                                     &DomainNameSize,
+                                     &SidNameUse);
+
+                    /* allocate the ace */
+                    AceListItem = HeapAlloc(GetProcessHeap(),
+                                            0,
+                                            sizeof(ACE_LISTITEM) +
+                                            SidLength +
+                                            ((AccountNameSize + DomainNameSize) * sizeof(WCHAR)));
+                    if (AceListItem != NULL)
+                    {
+                        AceListItem->AccountName = (LPWSTR)((ULONG_PTR)(AceListItem + 1) + SidLength);
+                        AceListItem->DomainName = AceListItem->AccountName + AccountNameSize;
+
+                        CopySid(SidLength,
+                                (PSID)(AceListItem + 1),
+                                Sid);
+
+                        LookupResult = ERROR_SUCCESS;
+                        if (!LookupAccountSid(sp->ServerName,
+                                              Sid,
+                                              AceListItem->AccountName,
+                                              &AccountNameSize,
+                                              AceListItem->DomainName,
+                                              &DomainNameSize,
+                                              &SidNameUse))
+                        {
+                            LookupResult = GetLastError();
+                            if (LookupResult != ERROR_NONE_MAPPED)
+                            {
+                                HeapFree(GetProcessHeap(),
+                                         0,
+                                         AceListItem);
+                                continue;
+                            }
+                        }
+                        
+                        if (AccountNameSize == 0)
+                        {
+                            AceListItem->AccountName = NULL;
+                        }
+                        if (DomainNameSize == 0)
+                        {
+                            AceListItem->DomainName = NULL;
+                        }
+
+                        AceListItem->Next = NULL;
+                        if (LookupResult == ERROR_NONE_MAPPED)
+                        {
+                            if (!ConvertSidToStringSid(Sid,
+                                                       &AceListItem->DisplayString))
+                            {
+                                AceListItem->DisplayString = NULL;
+                            }
+                        }
+                        else
+                        {
+                            LSA_HANDLE LsaHandle;
+                            NTSTATUS Status;
+                            
+                            AceListItem->DisplayString = NULL;
+                            
+                            /* read the domain of the SID */
+                            if (OpenLSAPolicyHandle(sp->ServerName,
+                                                    POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
+                                                    &LsaHandle))
+                            {
+                                PLSA_REFERENCED_DOMAIN_LIST ReferencedDomain;
+                                PLSA_TRANSLATED_NAME Names;
+                                PLSA_TRUST_INFORMATION Domain;
+                                PLSA_UNICODE_STRING DomainName;
+                                PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo = NULL;
+
+                                Status = LsaLookupSids(LsaHandle,
+                                                       1,
+                                                       &Sid,
+                                                       &ReferencedDomain,
+                                                       &Names);
+                                if (NT_SUCCESS(Status))
+                                {
+                                    if (ReferencedDomain != NULL &&
+                                        Names->DomainIndex >= 0)
+                                    {
+                                        Domain = &ReferencedDomain->Domains[Names->DomainIndex];
+                                        DomainName = &Domain->Name;
+                                    }
+                                    else
+                                    {
+                                        Domain = NULL;
+                                        DomainName = NULL;
+                                    }
+                                    
+                                    AceListItem->SidNameUse = Names->Use;
+
+                                    switch (Names->Use)
+                                    {
+                                        case SidTypeAlias:
+                                            if (Domain != NULL)
+                                            {
+                                                /* query the domain name for BUILTIN accounts */
+                                                Status = LsaQueryInformationPolicy(LsaHandle,
+                                                                                   PolicyAccountDomainInformation,
+                                                                                   (PVOID*)&PolicyAccountDomainInfo);
+                                                if (NT_SUCCESS(Status))
+                                                {
+                                                    DomainName = &PolicyAccountDomainInfo->DomainName;
+
+                                                    /* make the user believe this is a group */
+                                                    AceListItem->SidNameUse = SidTypeGroup;
+                                                }
+                                            }
+                                            /* fall through */
+
+                                        case SidTypeUser:
+                                        {
+                                            if (Domain != NULL)
+                                            {
+                                                AceListItem->DisplayString = (LPWSTR)LocalAlloc(LMEM_FIXED,
+                                                                                                (AccountNameSize * sizeof(WCHAR)) +
+                                                                                                (DomainName->Length + sizeof(WCHAR)) +
+                                                                                                (Names->Name.Length + sizeof(WCHAR)) +
+                                                                                                (4 * sizeof(WCHAR)));
+                                                if (AceListItem->DisplayString != NULL)
+                                                {
+                                                    WCHAR *s;
+                                                    
+                                                    /* NOTE: LSA_UNICODE_STRINGs are not always NULL-terminated! */
+
+                                                    wcscpy(AceListItem->DisplayString,
+                                                           AceListItem->AccountName);
+                                                    wcscat(AceListItem->DisplayString,
+                                                           L" (");
+                                                    s = AceListItem->DisplayString + wcslen(AceListItem->DisplayString);
+                                                    CopyMemory(s,
+                                                               DomainName->Buffer,
+                                                               DomainName->Length);
+                                                    s += DomainName->Length / sizeof(WCHAR);
+                                                    *(s++) = L'\\';
+                                                    CopyMemory(s,
+                                                               Names->Name.Buffer,
+                                                               Names->Name.Length);
+                                                    s += Names->Name.Length / sizeof(WCHAR);
+                                                    *(s++) = L')';
+                                                    *s = L'\0';
+                                                }
+                                                
+                                                /* mark the ace as a user unless it's a
+                                                   BUILTIN account */
+                                                if (PolicyAccountDomainInfo == NULL)
+                                                {
+                                                    AceListItem->SidNameUse = SidTypeUser;
+                                                }
+                                            }
+                                            break;
+                                        }
+                                        
+                                        case SidTypeWellKnownGroup:
+                                        {
+                                            /* make the user believe this is a group */
+                                            AceListItem->SidNameUse = SidTypeGroup;
+                                            break;
+                                        }
+                                        
+                                        default:
+                                        {
+                                            DPRINT("Unhandled SID type: 0x%x\n", Names->Use);
+                                            break;
+                                        }
+                                    }
+                                    
+                                    if (PolicyAccountDomainInfo != NULL)
+                                    {
+                                        LsaFreeMemory(PolicyAccountDomainInfo);
+                                    }
+                                    
+                                    LsaFreeMemory(ReferencedDomain);
+                                    LsaFreeMemory(Names);
+                                }
+                                LsaClose(LsaHandle);
+                            }
+                        }
+
+                        /* append item to the cached ACL */
+                        *NextAcePtr = AceListItem;
+                        NextAcePtr = &AceListItem->Next;
+                    }
+                }
+            }
+        }
+        LocalFree((HLOCAL)SecurityDescriptor);
+    }
 }
 
+static INT
+AddAceListEntry(IN PSECURITY_PAGE sp,
+                IN PACE_LISTITEM AceListItem,
+                IN INT Index,
+                IN BOOL Selected)
+{
+    LVITEM li;
 
-INT_PTR CALLBACK
-SecurityPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+    li.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
+    li.iItem = Index;
+    li.iSubItem = 0;
+    li.state = (Selected ? LVIS_SELECTED : 0);
+    li.stateMask = LVIS_SELECTED;
+    li.pszText = (AceListItem->DisplayString != NULL ? AceListItem->DisplayString : AceListItem->AccountName);
+    switch (AceListItem->SidNameUse)
+    {
+        case SidTypeUser:
+            li.iImage = 0;
+            break;
+        case SidTypeGroup:
+            li.iImage = 1;
+            break;
+        default:
+            li.iImage = -1;
+            break;
+    }
+    li.lParam = (LPARAM)AceListItem;
+
+    return ListView_InsertItem(sp->hWndAceList,
+                               &li);
+}
+
+static VOID
+FillUsersGroupsList(IN PSECURITY_PAGE sp)
 {
-  PSECURITY_PAGE sp;
-  
-  switch(uMsg)
-  {
-    case WM_INITDIALOG:
+    LPARAM SelLParam;
+    PACE_LISTITEM CurItem;
+    RECT rcLvClient;
+
+    SelLParam = ListViewGetSelectedItemData(sp->hWndAceList);
+
+    DisableRedrawWindow(sp->hWndAceList);
+
+    ListView_DeleteAllItems(sp->hWndAceList);
+
+    ReloadUsersGroupsList(sp);
+
+    for (CurItem = sp->AceListHead;
+         CurItem != NULL;
+         CurItem = CurItem->Next)
     {
-      sp = (PSECURITY_PAGE)lParam;
-      if(sp != NULL)
-      {
-        LV_COLUMN lvc;
-        RECT rcLvClient;
+        AddAceListEntry(sp,
+                        CurItem,
+                        -1,
+                        (SelLParam == (LPARAM)CurItem));
+    }
+    
+    EnableRedrawWindow(sp->hWndAceList);
+    
+    GetClientRect(sp->hWndAceList, &rcLvClient);
+    
+    ListView_SetColumnWidth(sp->hWndAceList,
+                            0,
+                            rcLvClient.right);
+}
+
+static VOID
+UpdateControlStates(IN PSECURITY_PAGE sp)
+{
+    PACE_LISTITEM Selected = (PACE_LISTITEM)ListViewGetSelectedItemData(sp->hWndAceList);
+
+    EnableWindow(sp->hBtnRemove, Selected != NULL);
+    EnableWindow(sp->hAceCheckList, Selected != NULL);
+    
+    if (Selected != NULL)
+    {
+        LPWSTR szLabel;
+
+        if (LoadAndFormatString(hDllInstance,
+                                IDS_PERMISSIONS_FOR,
+                                &szLabel,
+                                Selected->AccountName))
+        {
+            SetWindowText(sp->hPermissionsForLabel,
+                          szLabel);
+
+            LocalFree((HLOCAL)szLabel);
+        }
         
-        sp->hWnd = hwndDlg;
-        sp->hWndUsrList = GetDlgItem(hwndDlg, IDC_ACELIST);
-        sp->hiUsrs = ImageList_LoadBitmap(hDllInstance, MAKEINTRESOURCE(IDB_USRGRPIMAGES), 16, 3, 0);
+        /* FIXME - update the checkboxes */
+    }
+    else
+    {
+        WCHAR szPermissions[255];
         
-        /* save the pointer to the structure */
-        SetWindowLongPtr(hwndDlg, DWL_USER, (DWORD_PTR)sp);
+        if (LoadString(hDllInstance,
+                       IDS_PERMISSIONS,
+                       szPermissions,
+                       sizeof(szPermissions) / sizeof(szPermissions[0])))
+        {
+            SetWindowText(sp->hPermissionsForLabel,
+                          szPermissions);
+        }
+
+        SendMessage(sp->hAceCheckList,
+                    CLM_CLEARCHECKBOXES,
+                    0,
+                    0);
+    }
+}
+
+static UINT CALLBACK
+SecurityPageCallback(IN HWND hwnd,
+                     IN UINT uMsg,
+                     IN LPPROPSHEETPAGE ppsp)
+{
+    PSECURITY_PAGE sp = (PSECURITY_PAGE)ppsp->lParam;
+    
+    switch(uMsg)
+    {
+        case PSPCB_CREATE:
+        {
+            return TRUE;
+        }
+        case PSPCB_RELEASE:
+        {
+            DestroySecurityPage(sp);
+            UnregisterCheckListControl();
+            return FALSE;
+        }
+    }
+
+    return FALSE;
+}
+
+static VOID
+SetAceCheckListColumns(IN HWND hAceCheckList,
+                       IN UINT Button,
+                       IN HWND hLabel)
+{
+    POINT pt;
+    RECT rcLabel;
+
+    GetWindowRect(hLabel,
+                  &rcLabel);
+    pt.y = 0;
+    pt.x = (rcLabel.right - rcLabel.left) / 2;
+    MapWindowPoints(hLabel,
+                    hAceCheckList,
+                    &pt,
+                    1);
+
+    SendMessage(hAceCheckList,
+                CLM_SETCHECKBOXCOLUMN,
+                Button,
+                pt.x);
+}
+
+static VOID
+LoadPermissionsList(IN PSECURITY_PAGE sp,
+                    IN GUID *GuidObjectType,
+                    IN DWORD dwFlags,
+                    OUT SI_ACCESS *DefaultAccess)
+{
+    HRESULT hRet;
+    PSI_ACCESS AccessList;
+    ULONG nAccessList, DefaultAccessIndex;
+    
+    /* clear the permissions list */
+    
+    SendMessage(sp->hAceCheckList,
+                CLM_CLEAR,
+                0,
+                0);
+    
+    /* query the access rights from the server */
+    hRet = sp->psi->lpVtbl->GetAccessRights(sp->psi,
+                                            GuidObjectType,
+                                            dwFlags,
+                                            &AccessList,
+                                            &nAccessList,
+                                            &DefaultAccessIndex);
+    if (SUCCEEDED(hRet) && nAccessList != 0)
+    {
+        LPCWSTR NameStr;
+        PSI_ACCESS CurAccess, LastAccess;
+        WCHAR NameBuffer[MAX_PATH];
         
-        GetClientRect(sp->hWndUsrList, &rcLvClient);
+        /* save the default access rights to be used when adding ACEs later */
+        if (DefaultAccess != NULL)
+        {
+            *DefaultAccess = AccessList[DefaultAccessIndex];
+        }
         
-        /* setup the listview control */
-        ListView_SetExtendedListViewStyleEx(sp->hWndUsrList, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
-        ListView_SetImageList(sp->hWndUsrList, sp->hiUsrs, LVSIL_SMALL);
+        LastAccess = AccessList + nAccessList;
+        for (CurAccess = &AccessList[0];
+             CurAccess != LastAccess;
+             CurAccess++)
+        {
+            if (CurAccess->dwFlags & dwFlags)
+            {
+                /* get the permission name, load it from a string table if necessary */
+                if (IS_INTRESOURCE(CurAccess->pszName))
+                {
+                    if (!LoadString(sp->ObjectInfo.hInstance,
+                                    (UINT)((ULONG_PTR)CurAccess->pszName),
+                                    NameBuffer,
+                                    sizeof(NameBuffer) / sizeof(NameBuffer[0])))
+                    {
+                        LoadString(hDllInstance,
+                                   IDS_UNKNOWN,
+                                   NameBuffer,
+                                   sizeof(NameBuffer) / sizeof(NameBuffer[0]));
+                    }
+                    NameStr = NameBuffer;
+                }
+                else
+                {
+                    NameStr = CurAccess->pszName;
+                }
 
-        /* add a column to the list view */
-        lvc.mask = LVCF_FMT | LVCF_WIDTH;
-        lvc.fmt = LVCFMT_LEFT;
-        lvc.cx = rcLvClient.right;
-        ListView_InsertColumn(sp->hWndUsrList, 0, &lvc);
+                SendMessage(sp->hAceCheckList,
+                            CLM_ADDITEM,
+                            CIS_NONE,
+                            (LPARAM)NameStr);
+            }
+        }
+    }
+}
+
+static INT_PTR CALLBACK
+SecurityPageProc(IN HWND hwndDlg,
+                 IN UINT uMsg,
+                 IN WPARAM wParam,
+                 IN LPARAM lParam)
+{
+    PSECURITY_PAGE sp;
+
+    switch(uMsg)
+    {
+        case WM_NOTIFY:
+        {
+            NMHDR *pnmh = (NMHDR*)lParam;
+            sp = (PSECURITY_PAGE)GetWindowLongPtr(hwndDlg,
+                                                  DWL_USER);
+            if (sp != NULL)
+            {
+                if (pnmh->hwndFrom == sp->hWndAceList)
+                {
+                    switch(pnmh->code)
+                    {
+                        case LVN_ITEMCHANGED:
+                        {
+                            LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
+                            
+                            if ((pnmv->uChanged & LVIF_STATE) &&
+                                ((pnmv->uOldState & (LVIS_FOCUSED | LVIS_SELECTED)) ||
+                                 (pnmv->uNewState & (LVIS_FOCUSED | LVIS_SELECTED))))
+                            {
+                                UpdateControlStates(sp);
+                            }
+                            break;
+                        }
+                    }
+                }
+                else if (pnmh->hwndFrom == sp->hAceCheckList)
+                {
+                    switch(pnmh->code)
+                    {
+                        case CLN_CHANGINGITEMCHECKBOX:
+                        {
+                            PNMCHANGEITEMCHECKBOX pcicb = (PNMCHANGEITEMCHECKBOX)lParam;
+                            
+                            /* make sure only one of both checkboxes is only checked
+                               at the same time */
+                            if (pcicb->Checked)
+                            {
+                                pcicb->NewState &= ~((pcicb->CheckBox != CLB_DENY) ? CIS_DENY : CIS_ALLOW);
+                            }
+                            break;
+                        }
+                    }
+                }
+            }
+            break;
+        }
         
-        /* FIXME - hide controls in case the flags aren't present */
-      }
-      break;
+        case WM_INITDIALOG:
+        {
+            sp = (PSECURITY_PAGE)((LPPROPSHEETPAGE)lParam)->lParam;
+            if(sp != NULL)
+            {
+                LV_COLUMN lvc;
+                RECT rcLvClient;
+                
+                sp->hWnd = hwndDlg;
+                sp->hWndAceList = GetDlgItem(hwndDlg, IDC_ACELIST);
+                sp->hBtnRemove = GetDlgItem(hwndDlg, IDC_ACELIST_REMOVE);
+                sp->hBtnAdvanced = GetDlgItem(hwndDlg, IDC_ADVANCED);
+                sp->hAceCheckList = GetDlgItem(hwndDlg, IDC_ACE_CHECKLIST);
+                sp->hPermissionsForLabel = GetDlgItem(hwndDlg, IDC_LABEL_PERMISSIONS_FOR);
+                
+                sp->SpecialPermCheckIndex = -1;
+                
+                if ((sp->ObjectInfo.dwFlags & SI_SERVER_IS_DC) &&
+                    sp->ObjectInfo.pszServerName != NULL &&
+                    sp->ObjectInfo.pszServerName[0] != L'\0')
+                {
+                    sp->ServerName = sp->ObjectInfo.pszServerName;
+                }
+
+                /* save the pointer to the structure */
+                SetWindowLongPtr(hwndDlg,
+                                 DWL_USER,
+                                 (DWORD_PTR)sp);
+
+                sp->hiUsrs = ImageList_LoadBitmap(hDllInstance,
+                                                  MAKEINTRESOURCE(IDB_USRGRPIMAGES),
+                                                  16,
+                                                  3,
+                                                  0);
+
+                /* setup the listview control */
+                ListView_SetExtendedListViewStyleEx(sp->hWndAceList,
+                                                    LVS_EX_FULLROWSELECT,
+                                                    LVS_EX_FULLROWSELECT);
+                ListView_SetImageList(sp->hWndAceList,
+                                      sp->hiUsrs,
+                                      LVSIL_SMALL);
+
+                GetClientRect(sp->hWndAceList, &rcLvClient);
+                
+                /* add a column to the list view */
+                lvc.mask = LVCF_FMT | LVCF_WIDTH;
+                lvc.fmt = LVCFMT_LEFT;
+                lvc.cx = rcLvClient.right;
+                ListView_InsertColumn(sp->hWndAceList, 0, &lvc);
+
+                FillUsersGroupsList(sp);
+                
+                ListViewSelectItem(sp->hWndAceList,
+                                   0);
+
+                /* calculate the columns of the allow/deny checkboxes */
+                SetAceCheckListColumns(sp->hAceCheckList,
+                                       CLB_ALLOW,
+                                       GetDlgItem(hwndDlg, IDC_LABEL_ALLOW));
+                SetAceCheckListColumns(sp->hAceCheckList,
+                                       CLB_DENY,
+                                       GetDlgItem(hwndDlg, IDC_LABEL_DENY));
+
+                LoadPermissionsList(sp,
+                                    NULL,
+                                    SI_ACCESS_GENERAL |
+                                    ((sp->ObjectInfo.dwFlags & SI_CONTAINER) ? SI_ACCESS_CONTAINER : 0),
+                                    &sp->DefaultAccess);
+
+                /* hide controls in case the flags aren't present */
+                if (sp->ObjectInfo.dwFlags & SI_ADVANCED)
+                {
+                    WCHAR szSpecialPermissions[255];
+                    
+                    /* editing the permissions is least the user can do when
+                       the advanced button is showed */
+                    sp->ObjectInfo.dwFlags |= SI_EDIT_PERMS;
+                    
+                    if (LoadString(hDllInstance,
+                                   IDS_SPECIAL_PERMISSIONS,
+                                   szSpecialPermissions,
+                                   sizeof(szSpecialPermissions) / sizeof(szSpecialPermissions[0])))
+                    {
+                        /* add the special permissions check item */
+                        sp->SpecialPermCheckIndex = (INT)SendMessage(sp->hAceCheckList,
+                                                                     CLM_ADDITEM,
+                                                                     CIS_ALLOWDISABLED | CIS_DENYDISABLED | CIS_NONE,
+                                                                     (LPARAM)szSpecialPermissions);
+                    }
+                }
+                else
+                {
+                    ShowWindow(sp->hBtnAdvanced,
+                               SW_HIDE);
+                    ShowWindow(GetDlgItem(hwndDlg, IDC_LABEL_ADVANCED),
+                               SW_HIDE);
+                }
+                
+                /* enable quicksearch for the permissions checklist control */
+                SendMessage(sp->hAceCheckList,
+                            CLM_ENABLEQUICKSEARCH,
+                            TRUE,
+                            0);
+            }
+            break;
+        }
     }
-  }
-  return 0;
+    return 0;
 }
 
 
@@ -125,48 +744,82 @@
  */
 HPROPSHEETPAGE
 WINAPI
-CreateSecurityPage(LPSECURITYINFO psi)
+CreateSecurityPage(IN LPSECURITYINFO psi)
 {
-  PROPSHEETPAGE psp;
-  SI_OBJECT_INFO ObjectInfo;
-  HRESULT hRet;
+    PROPSHEETPAGE psp;
+    PSECURITY_PAGE sPage;
+    SI_OBJECT_INFO ObjectInfo;
+    HRESULT hRet;
 
-  if(psi == NULL)
-  {
-    SetLastError(ERROR_INVALID_PARAMETER);
+    if(psi == NULL)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
 
-    DPRINT("No ISecurityInformation class passed!\n");
-    return NULL;
-  }
+        DPRINT("No ISecurityInformation class passed!\n");
+        return NULL;
+    }
 
-  /* get the object information from the server interface */
-  hRet = psi->lpVtbl->GetObjectInformation(psi, &ObjectInfo);
+    /* get the object information from the server. Zero the structure before
+       because some applications seem to return SUCCESS but only seem to set the
+       fields they care about. */
+    ZeroMemory(&ObjectInfo, sizeof(ObjectInfo));
+    hRet = psi->lpVtbl->GetObjectInformation(psi, &ObjectInfo);
 
-  if(FAILED(hRet))
-  {
-    SetLastError(hRet);
+    if(FAILED(hRet))
+    {
+        SetLastError(hRet);
 
-    DPRINT("CreateSecurityPage() failed!\n");
-    return NULL;
-  }
+        DPRINT("CreateSecurityPage() failed! Failed to query the object information!\n");
+        return NULL;
+    }
+    
+    if (!RegisterCheckListControl(hDllInstance))
+    {
+        DPRINT("Registering the CHECKLIST_ACLUI class failed!\n");
+        return NULL;
+    }
+    
+    sPage = HeapAlloc(GetProcessHeap(),
+                      HEAP_ZERO_MEMORY,
+                      sizeof(SECURITY_PAGE));
+    if (sPage == NULL)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        
+        DPRINT("Not enough memory to allocate a SECURITY_PAGE!\n");
+        return NULL;
+    }
+    sPage->psi = psi;
+    sPage->ObjectInfo = ObjectInfo;
 
-  psp.dwSize = sizeof(PROPSHEETPAGE);
-  psp.dwFlags = PSP_DEFAULT | PSP_USECALLBACK;
-  psp.hInstance = hDllInstance;
-  psp.pszTemplate = MAKEINTRESOURCE(IDD_SECPAGE);
-  psp.pfnDlgProc = SecurityPageProc;
-  psp.lParam = (LPARAM)psi;
-  psp.pfnCallback = SecurityPageCallback;
+    ZeroMemory(&psp, sizeof(psp));
 
-  if((ObjectInfo.dwFlags & SI_PAGE_TITLE) != 0 &&
-     ObjectInfo.pszPageTitle != NULL && ObjectInfo.pszPageTitle[0] != L'\0')
-  {
-    /* Set the page title if the flag is present and the string isn't empty */
-    psp.pszTitle = ObjectInfo.pszPageTitle;
-    psp.dwFlags |= PSP_USETITLE;
-  }
+    psp.dwSize = sizeof(PROPSHEETPAGE);
+    psp.dwFlags = PSP_USECALLBACK;
+    psp.hInstance = hDllInstance;
+    psp.pszTemplate = MAKEINTRESOURCE(IDD_SECPAGE);
+    psp.pfnDlgProc = SecurityPageProc;
+    psp.lParam = (LPARAM)sPage;
+    psp.pfnCallback = SecurityPageCallback;
 
-  return CreatePropertySheetPage(&psp);
+    if(ObjectInfo.dwFlags & SI_PAGE_TITLE)
+    {
+        psp.pszTitle = ObjectInfo.pszPageTitle;
+
+        if (psp.pszTitle != NULL)
+        {
+            psp.dwFlags |= PSP_USETITLE;
+        }
+    }
+    else
+    {
+        psp.pszTitle = NULL;
+    }
+    
+    /* NOTE: the SECURITY_PAGE structure will be freed by the property page
+             callback! */
+
+    return CreatePropertySheetPage(&psp);
 }
 
 
@@ -177,99 +830,89 @@
  */
 BOOL
 WINAPI
-EditSecurity(HWND hwndOwner, LPSECURITYINFO psi)
+EditSecurity(IN HWND hwndOwner,
+             IN LPSECURITYINFO psi)
 {
-  HRESULT hRet;
-  SI_OBJECT_INFO ObjectInfo;
-  PROPSHEETHEADER psh;
-  HPROPSHEETPAGE hPages[1];
-  LPVOID lpCaption;
-  BOOL Ret;
-  
-  if(psi == NULL)
-  {
-    SetLastError(ERROR_INVALID_PARAMETER);
-    
-    DPRINT("No ISecurityInformation class passed!\n");
-    return FALSE;
-  }
-  
-  /* get the object information from the server interface */
-  hRet = psi->lpVtbl->GetObjectInformation(psi, &ObjectInfo);
-  
-  if(FAILED(hRet))
-  {
-    SetLastError(hRet);
-    
-    DPRINT("GetObjectInformation() failed!\n");
-    return FALSE;
-  }
+    HRESULT hRet;
+    SI_OBJECT_INFO ObjectInfo;
+    PROPSHEETHEADER psh;
+    HPROPSHEETPAGE hPages[1];
+    LPWSTR lpCaption;
+    BOOL Ret;
 
-  /* create the page */
-  hPages[0] = CreateSecurityPage(psi);
-  if(hPages[0] == NULL)
-  {
-    DPRINT("CreateSecurityPage(), couldn't create property sheet!\n");
-    return FALSE;
-  }
-  
-  psh.dwSize = sizeof(PROPSHEETHEADER);
-  psh.dwFlags = PSH_DEFAULT;
-  psh.hwndParent = hwndOwner;
-  psh.hInstance = hDllInstance;
-  if((ObjectInfo.dwFlags & SI_PAGE_TITLE) != 0 &&
-     ObjectInfo.pszPageTitle != NULL && ObjectInfo.pszPageTitle[0] != L'\0')
-  {
-    /* Set the page title if the flag is present and the string isn't empty */
-    psh.pszCaption = ObjectInfo.pszPageTitle;
-    lpCaption = NULL;
-  }
-  else
-  {
+    if(psi == NULL)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+
+        DPRINT("No ISecurityInformation class passed!\n");
+        return FALSE;
+    }
+
+    /* get the object information from the server. Zero the structure before
+       because some applications seem to return SUCCESS but only seem to set the
+       fields they care about. */
[truncated at 1000 lines; 288 more skipped]