2 * Implementation of the AclUI
4 * Copyright (C) 2009 Nikolay Sivov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(aclui
);
35 /* the aclui.h files does not contain the necessary COBJMACROS */
36 #define ISecurityInformation_AddRef(This) (This)->lpVtbl->AddRef(This)
37 #define ISecurityInformation_Release(This) (This)->lpVtbl->Release(This)
38 #define ISecurityInformation_GetObjectInformation(This, obj) (This)->lpVtbl->GetObjectInformation(This, obj)
39 #define ISecurityInformation_GetSecurity(This, info, sd, def) (This)->lpVtbl->GetSecurity(This, info, sd, def)
40 #define ISecurityInformation_GetAccessRights(This, type, flags, access, count, def) (This)->lpVtbl->GetAccessRights(This, type, flags, access, count, def)
50 ISecurityInformation
*security
;
52 PSECURITY_DESCRIPTOR sd
;
55 unsigned int user_count
;
60 static HINSTANCE aclui_instance
;
62 static WCHAR
*get_sid_name(PSID sid
, SID_NAME_USE
*sid_type
)
69 LookupAccountSidW(NULL
, sid
, NULL
, &name_len
, NULL
, &domain_len
, sid_type
);
70 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
72 if (!(name
= malloc(name_len
* sizeof(WCHAR
))))
74 if (!(domain
= malloc(domain_len
* sizeof(WCHAR
))))
80 ret
= LookupAccountSidW(NULL
, sid
, name
, &name_len
, domain
, &domain_len
, sid_type
);
87 static void add_user(struct security_page
*page
, PSID sid
)
89 struct user
*new_array
, *user
;
90 SID_NAME_USE sid_type
;
95 /* check if we already processed this user or group */
96 for (i
= 0; i
< page
->user_count
; ++i
)
98 if (EqualSid(sid
, page
->users
[i
].sid
))
102 if (!(name
= get_sid_name(sid
, &sid_type
)))
105 if (!(new_array
= realloc(page
->users
, (page
->user_count
+ 1) * sizeof(*page
->users
))))
107 page
->users
= new_array
;
108 user
= &page
->users
[page
->user_count
++];
113 item
.mask
= LVIF_PARAM
| LVIF_TEXT
;
117 item
.lParam
= (LPARAM
)user
;
119 SendMessageW(GetDlgItem(page
->dialog
, IDC_USERS
), LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
122 static PSID
get_sid_from_ace(ACE_HEADER
*ace
)
124 switch (ace
->AceType
)
126 case ACCESS_ALLOWED_ACE_TYPE
:
127 return &((ACCESS_ALLOWED_ACE
*)ace
)->SidStart
;
128 case ACCESS_DENIED_ACE_TYPE
:
129 return &((ACCESS_DENIED_ACE
*)ace
)->SidStart
;
131 FIXME("Unhandled ACE type %#x.\n", ace
->AceType
);
136 static void init_users(struct security_page
*page
)
138 BOOL defaulted
, present
;
144 if (!GetSecurityDescriptorDacl(page
->sd
, &present
, &dacl
, &defaulted
))
146 ERR("Failed to query descriptor information, error %u.\n", GetLastError());
153 for (index
= 0; index
< dacl
->AceCount
; index
++)
155 if (!GetAce(dacl
, index
, (void **)&ace
))
157 if (!(sid
= get_sid_from_ace(ace
)))
163 static void security_page_free(struct security_page
*page
)
167 for (i
= 0; i
< page
->user_count
; ++i
)
168 free(page
->users
[i
].name
);
173 ISecurityInformation_Release(page
->security
);
177 static void security_page_init_dlg(HWND hwnd
, struct security_page
*page
)
186 if (FAILED(hr
= ISecurityInformation_GetSecurity(page
->security
,
187 DACL_SECURITY_INFORMATION
, &page
->sd
, FALSE
)))
189 ERR("Failed to get security descriptor, hr %#x.\n", hr
);
193 control
= GetDlgItem(hwnd
, IDC_USERS
);
194 SendMessageW(control
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_FULLROWSELECT
, LVS_EX_FULLROWSELECT
);
196 GetClientRect(control
, &rect
);
197 column
.mask
= LVCF_FMT
| LVCF_WIDTH
;
198 column
.fmt
= LVCFMT_LEFT
;
199 column
.cx
= rect
.right
- rect
.left
;
200 SendMessageW(control
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
204 if (page
->user_count
)
207 item
.mask
= LVIF_STATE
;
210 item
.state
= LVIS_FOCUSED
| LVIS_SELECTED
;
211 item
.stateMask
= item
.state
;
212 SendMessageW(control
, LVM_SETITEMW
, 0, (LPARAM
)&item
);
216 static INT_PTR CALLBACK
security_page_proc(HWND dialog
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
222 PROPSHEETPAGEW
*propsheet
= (PROPSHEETPAGEW
*)lparam
;
223 security_page_init_dlg(dialog
, (struct security_page
*)propsheet
->lParam
);
230 static UINT CALLBACK
security_page_callback(HWND hwnd
, UINT msg
, PROPSHEETPAGEW
*ppsp
)
232 struct security_page
*page
= (struct security_page
*)ppsp
->lParam
;
234 if (msg
== PSPCB_RELEASE
)
235 security_page_free(page
);
240 HPROPSHEETPAGE WINAPI
CreateSecurityPage(ISecurityInformation
*security
)
242 struct security_page
*page
;
243 PROPSHEETPAGEW propsheet
;
246 TRACE("%p\n", security
);
248 InitCommonControls();
250 if (!(page
= calloc(1, sizeof(*page
))))
253 if (FAILED(ISecurityInformation_GetObjectInformation(security
, &page
->info
)))
259 page
->security
= security
;
260 ISecurityInformation_AddRef(security
);
262 memset(&propsheet
, 0, sizeof(propsheet
));
263 propsheet
.dwSize
= sizeof(propsheet
);
264 propsheet
.dwFlags
= PSP_DEFAULT
| PSP_USECALLBACK
;
265 propsheet
.hInstance
= aclui_instance
;
266 propsheet
.pszTemplate
= (WCHAR
*)MAKEINTRESOURCE(IDD_SECURITY_PROPERTIES
);
267 propsheet
.pfnDlgProc
= security_page_proc
;
268 propsheet
.pfnCallback
= security_page_callback
;
269 propsheet
.lParam
= (LPARAM
)page
;
271 if (page
->info
.dwFlags
& SI_PAGE_TITLE
)
273 propsheet
.pszTitle
= page
->info
.pszPageTitle
;
274 propsheet
.dwFlags
|= PSP_USETITLE
;
277 if (!(ret
= CreatePropertySheetPageW(&propsheet
)))
279 ERR("Failed to create property sheet page.\n");
280 ISecurityInformation_Release(security
);
287 BOOL WINAPI
EditSecurity(HWND owner
, LPSECURITYINFO psi
)
289 FIXME("(%p, %p): stub\n", owner
, psi
);
293 BOOL WINAPI
DllMain(HINSTANCE instance
, DWORD reason
, void *reserved
)
295 if (reason
== DLL_PROCESS_ATTACH
)
297 aclui_instance
= instance
;
298 DisableThreadLibraryCalls(instance
);