advapi32: Properly skip not supported parts of the object ACE.
[wine.git] / dlls / advapi32 / security.c
blob4bea26d15570d028cb176d735b323cd5aad8154d
1 /*
2 * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
3 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
4 * Copyright 2006 Robert Reif
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
22 #include "config.h"
24 #include <stdarg.h>
25 #include <string.h>
27 #include "ntstatus.h"
28 #define WIN32_NO_STATUS
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "winreg.h"
33 #include "winsafer.h"
34 #include "winternl.h"
35 #include "winioctl.h"
36 #include "accctrl.h"
37 #include "sddl.h"
38 #include "winsvc.h"
39 #include "aclapi.h"
40 #include "objbase.h"
41 #include "iads.h"
42 #include "advapi32_misc.h"
43 #include "lmcons.h"
45 #include "wine/debug.h"
46 #include "wine/unicode.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
50 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes);
51 static DWORD trustee_to_sid(DWORD nDestinationSidLength, PSID pDestinationSid, PTRUSTEEW pTrustee);
53 typedef struct _ACEFLAG
55 LPCWSTR wstr;
56 DWORD value;
57 } ACEFLAG, *LPACEFLAG;
59 typedef struct _MAX_SID
61 /* same fields as struct _SID */
62 BYTE Revision;
63 BYTE SubAuthorityCount;
64 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
65 DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
66 } MAX_SID;
68 typedef struct WELLKNOWNSID
70 WCHAR wstr[2];
71 WELL_KNOWN_SID_TYPE Type;
72 MAX_SID Sid;
73 } WELLKNOWNSID;
75 static const WELLKNOWNSID WellKnownSids[] =
77 { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
78 { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
79 { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
80 { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
81 { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
82 { {'O','W'}, WinCreatorOwnerRightsSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RIGHTS_RID } } },
83 { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
84 { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
85 { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
86 { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
87 { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
88 { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
89 { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
90 { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
91 { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
92 { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
93 { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
94 { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
95 { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
96 { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
97 { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
98 { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
99 { {0,0}, WinLogonIdsSid, { SID_REVISION, SECURITY_LOGON_IDS_RID_COUNT, { SECURITY_NT_AUTHORITY }, { SECURITY_LOGON_IDS_RID } } },
100 { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
101 { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
102 { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
103 { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
104 { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
105 { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
106 { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
107 { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
108 { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
109 { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
110 { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
111 { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
112 { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
113 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
114 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
115 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
116 { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
117 { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
118 { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
119 { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
120 { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
121 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS } } },
122 { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
123 { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
124 { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
125 { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
126 { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
127 { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } },
128 { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } },
129 { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } },
130 { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } },
131 { {'A','C'}, WinBuiltinAnyPackageSid, { SID_REVISION, 2, { SECURITY_APP_PACKAGE_AUTHORITY }, { SECURITY_APP_PACKAGE_BASE_RID, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE } } },
134 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */
135 typedef struct WELLKNOWNRID
137 WCHAR wstr[2];
138 WELL_KNOWN_SID_TYPE Type;
139 DWORD Rid;
140 } WELLKNOWNRID;
142 static const WELLKNOWNRID WellKnownRids[] = {
143 { {'L','A'}, WinAccountAdministratorSid, DOMAIN_USER_RID_ADMIN },
144 { {'L','G'}, WinAccountGuestSid, DOMAIN_USER_RID_GUEST },
145 { {0,0}, WinAccountKrbtgtSid, DOMAIN_USER_RID_KRBTGT },
146 { {'D','A'}, WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS },
147 { {'D','U'}, WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS },
148 { {'D','G'}, WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS },
149 { {'D','C'}, WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS },
150 { {'D','D'}, WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS },
151 { {'C','A'}, WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS },
152 { {'S','A'}, WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS },
153 { {'E','A'}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
154 { {'P','A'}, WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS },
155 { {'R','S'}, WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
159 typedef struct _AccountSid {
160 WELL_KNOWN_SID_TYPE type;
161 LPCWSTR account;
162 LPCWSTR domain;
163 SID_NAME_USE name_use;
164 LPCWSTR alias;
165 } AccountSid;
167 static const WCHAR Account_Operators[] = { 'A','c','c','o','u','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
168 static const WCHAR Administrator[] = {'A','d','m','i','n','i','s','t','r','a','t','o','r',0 };
169 static const WCHAR Administrators[] = { 'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0 };
170 static const WCHAR ALL_APPLICATION_PACKAGES[] = { 'A','L','L',' ','A','P','P','L','I','C','A','T','I','O','N',' ','P','A','C','K','A','G','E','S',0 };
171 static const WCHAR ANONYMOUS_LOGON[] = { 'A','N','O','N','Y','M','O','U','S',' ','L','O','G','O','N',0 };
172 static const WCHAR APPLICATION_PACKAGE_AUTHORITY[] = { 'A','P','P','L','I','C','A','T','I','O','N',' ','P','A','C','K','A','G','E',' ','A','U','T','H','O','R','I','T','Y',0 };
173 static const WCHAR Authenticated_Users[] = { 'A','u','t','h','e','n','t','i','c','a','t','e','d',' ','U','s','e','r','s',0 };
174 static const WCHAR Backup_Operators[] = { 'B','a','c','k','u','p',' ','O','p','e','r','a','t','o','r','s',0 };
175 static const WCHAR BATCH[] = { 'B','A','T','C','H',0 };
176 static const WCHAR Blank[] = { 0 };
177 static const WCHAR BUILTIN[] = { 'B','U','I','L','T','I','N',0 };
178 static const WCHAR Cert_Publishers[] = { 'C','e','r','t',' ','P','u','b','l','i','s','h','e','r','s',0 };
179 static const WCHAR CREATOR_GROUP[] = { 'C','R','E','A','T','O','R',' ','G','R','O','U','P',0 };
180 static const WCHAR CREATOR_GROUP_SERVER[] = { 'C','R','E','A','T','O','R',' ','G','R','O','U','P',' ','S','E','R','V','E','R',0 };
181 static const WCHAR CREATOR_OWNER[] = { 'C','R','E','A','T','O','R',' ','O','W','N','E','R',0 };
182 static const WCHAR CREATOR_OWNER_SERVER[] = { 'C','R','E','A','T','O','R',' ','O','W','N','E','R',' ','S','E','R','V','E','R',0 };
183 static const WCHAR CURRENT_USER[] = { 'C','U','R','R','E','N','T','_','U','S','E','R',0 };
184 static const WCHAR DIALUP[] = { 'D','I','A','L','U','P',0 };
185 static const WCHAR Digest_Authentication[] = { 'D','i','g','e','s','t',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
186 static const WCHAR Domain_Admins[] = { 'D','o','m','a','i','n',' ','A','d','m','i','n','s',0 };
187 static const WCHAR Domain_Computers[] = { 'D','o','m','a','i','n',' ','C','o','m','p','u','t','e','r','s',0 };
188 static const WCHAR Domain_Controllers[] = { 'D','o','m','a','i','n',' ','C','o','n','t','r','o','l','l','e','r','s',0 };
189 static const WCHAR Domain_Guests[] = { 'D','o','m','a','i','n',' ','G','u','e','s','t','s',0 };
190 static const WCHAR None[] = { 'N','o','n','e',0 };
191 static const WCHAR Enterprise_Admins[] = { 'E','n','t','e','r','p','r','i','s','e',' ','A','d','m','i','n','s',0 };
192 static const WCHAR ENTERPRISE_DOMAIN_CONTROLLERS[] = { 'E','N','T','E','R','P','R','I','S','E',' ','D','O','M','A','I','N',' ','C','O','N','T','R','O','L','L','E','R','S',0 };
193 static const WCHAR Everyone[] = { 'E','v','e','r','y','o','n','e',0 };
194 static const WCHAR Group_Policy_Creator_Owners[] = { 'G','r','o','u','p',' ','P','o','l','i','c','y',' ','C','r','e','a','t','o','r',' ','O','w','n','e','r','s',0 };
195 static const WCHAR Guest[] = { 'G','u','e','s','t',0 };
196 static const WCHAR Guests[] = { 'G','u','e','s','t','s',0 };
197 static const WCHAR INTERACTIVE[] = { 'I','N','T','E','R','A','C','T','I','V','E',0 };
198 static const WCHAR LOCAL[] = { 'L','O','C','A','L',0 };
199 static const WCHAR LOCAL_SERVICE[] = { 'L','O','C','A','L',' ','S','E','R','V','I','C','E',0 };
200 static const WCHAR LOCAL_SERVICE2[] = { 'L','O','C','A','L','S','E','R','V','I','C','E',0 };
201 static const WCHAR NETWORK[] = { 'N','E','T','W','O','R','K',0 };
202 static const WCHAR Network_Configuration_Operators[] = { 'N','e','t','w','o','r','k',' ','C','o','n','f','i','g','u','r','a','t','i','o','n',' ','O','p','e','r','a','t','o','r','s',0 };
203 static const WCHAR NETWORK_SERVICE[] = { 'N','E','T','W','O','R','K',' ','S','E','R','V','I','C','E',0 };
204 static const WCHAR NETWORK_SERVICE2[] = { 'N','E','T','W','O','R','K','S','E','R','V','I','C','E',0 };
205 static const WCHAR NT_AUTHORITY[] = { 'N','T',' ','A','U','T','H','O','R','I','T','Y',0 };
206 static const WCHAR NT_Pseudo_Domain[] = { 'N','T',' ','P','s','e','u','d','o',' ','D','o','m','a','i','n',0 };
207 static const WCHAR NTML_Authentication[] = { 'N','T','M','L',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
208 static const WCHAR NULL_SID[] = { 'N','U','L','L',' ','S','I','D',0 };
209 static const WCHAR Other_Organization[] = { 'O','t','h','e','r',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
210 static const WCHAR Performance_Log_Users[] = { 'P','e','r','f','o','r','m','a','n','c','e',' ','L','o','g',' ','U','s','e','r','s',0 };
211 static const WCHAR Performance_Monitor_Users[] = { 'P','e','r','f','o','r','m','a','n','c','e',' ','M','o','n','i','t','o','r',' ','U','s','e','r','s',0 };
212 static const WCHAR Power_Users[] = { 'P','o','w','e','r',' ','U','s','e','r','s',0 };
213 static const WCHAR Pre_Windows_2000_Compatible_Access[] = { 'P','r','e','-','W','i','n','d','o','w','s',' ','2','0','0','0',' ','C','o','m','p','a','t','i','b','l','e',' ','A','c','c','e','s','s',0 };
214 static const WCHAR Print_Operators[] = { 'P','r','i','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
215 static const WCHAR PROXY[] = { 'P','R','O','X','Y',0 };
216 static const WCHAR RAS_and_IAS_Servers[] = { 'R','A','S',' ','a','n','d',' ','I','A','S',' ','S','e','r','v','e','r','s',0 };
217 static const WCHAR Remote_Desktop_Users[] = { 'R','e','m','o','t','e',' ','D','e','s','k','t','o','p',' ','U','s','e','r','s',0 };
218 static const WCHAR REMOTE_INTERACTIVE_LOGON[] = { 'R','E','M','O','T','E',' ','I','N','T','E','R','A','C','T','I','V','E',' ','L','O','G','O','N',0 };
219 static const WCHAR Replicators[] = { 'R','e','p','l','i','c','a','t','o','r','s',0 };
220 static const WCHAR RESTRICTED[] = { 'R','E','S','T','R','I','C','T','E','D',0 };
221 static const WCHAR SChannel_Authentication[] = { 'S','C','h','a','n','n','e','l',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
222 static const WCHAR Schema_Admins[] = { 'S','c','h','e','m','a',' ','A','d','m','i','n','s',0 };
223 static const WCHAR SELF[] = { 'S','E','L','F',0 };
224 static const WCHAR Server_Operators[] = { 'S','e','r','v','e','r',' ','O','p','e','r','a','t','o','r','s',0 };
225 static const WCHAR SERVICE[] = { 'S','E','R','V','I','C','E',0 };
226 static const WCHAR SYSTEM[] = { 'S','Y','S','T','E','M',0 };
227 static const WCHAR TERMINAL_SERVER_USER[] = { 'T','E','R','M','I','N','A','L',' ','S','E','R','V','E','R',' ','U','S','E','R',0 };
228 static const WCHAR This_Organization[] = { 'T','h','i','s',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
229 static const WCHAR Users[] = { 'U','s','e','r','s',0 };
231 static const AccountSid ACCOUNT_SIDS[] = {
232 { WinNullSid, NULL_SID, Blank, SidTypeWellKnownGroup },
233 { WinWorldSid, Everyone, Blank, SidTypeWellKnownGroup },
234 { WinLocalSid, LOCAL, Blank, SidTypeWellKnownGroup },
235 { WinCreatorOwnerSid, CREATOR_OWNER, Blank, SidTypeWellKnownGroup },
236 { WinCreatorGroupSid, CREATOR_GROUP, Blank, SidTypeWellKnownGroup },
237 { WinCreatorOwnerServerSid, CREATOR_OWNER_SERVER, Blank, SidTypeWellKnownGroup },
238 { WinCreatorGroupServerSid, CREATOR_GROUP_SERVER, Blank, SidTypeWellKnownGroup },
239 { WinNtAuthoritySid, NT_Pseudo_Domain, NT_Pseudo_Domain, SidTypeDomain },
240 { WinDialupSid, DIALUP, NT_AUTHORITY, SidTypeWellKnownGroup },
241 { WinNetworkSid, NETWORK, NT_AUTHORITY, SidTypeWellKnownGroup },
242 { WinBatchSid, BATCH, NT_AUTHORITY, SidTypeWellKnownGroup },
243 { WinInteractiveSid, INTERACTIVE, NT_AUTHORITY, SidTypeWellKnownGroup },
244 { WinServiceSid, SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup },
245 { WinAnonymousSid, ANONYMOUS_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
246 { WinProxySid, PROXY, NT_AUTHORITY, SidTypeWellKnownGroup },
247 { WinEnterpriseControllersSid, ENTERPRISE_DOMAIN_CONTROLLERS, NT_AUTHORITY, SidTypeWellKnownGroup },
248 { WinSelfSid, SELF, NT_AUTHORITY, SidTypeWellKnownGroup },
249 { WinAuthenticatedUserSid, Authenticated_Users, NT_AUTHORITY, SidTypeWellKnownGroup },
250 { WinRestrictedCodeSid, RESTRICTED, NT_AUTHORITY, SidTypeWellKnownGroup },
251 { WinTerminalServerSid, TERMINAL_SERVER_USER, NT_AUTHORITY, SidTypeWellKnownGroup },
252 { WinRemoteLogonIdSid, REMOTE_INTERACTIVE_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
253 { WinLocalSystemSid, SYSTEM, NT_AUTHORITY, SidTypeWellKnownGroup },
254 { WinLocalServiceSid, LOCAL_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup, LOCAL_SERVICE2 },
255 { WinNetworkServiceSid, NETWORK_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup , NETWORK_SERVICE2},
256 { WinBuiltinDomainSid, BUILTIN, BUILTIN, SidTypeDomain },
257 { WinBuiltinAdministratorsSid, Administrators, BUILTIN, SidTypeAlias },
258 { WinBuiltinUsersSid, Users, BUILTIN, SidTypeAlias },
259 { WinBuiltinGuestsSid, Guests, BUILTIN, SidTypeAlias },
260 { WinBuiltinPowerUsersSid, Power_Users, BUILTIN, SidTypeAlias },
261 { WinBuiltinAccountOperatorsSid, Account_Operators, BUILTIN, SidTypeAlias },
262 { WinBuiltinSystemOperatorsSid, Server_Operators, BUILTIN, SidTypeAlias },
263 { WinBuiltinPrintOperatorsSid, Print_Operators, BUILTIN, SidTypeAlias },
264 { WinBuiltinBackupOperatorsSid, Backup_Operators, BUILTIN, SidTypeAlias },
265 { WinBuiltinReplicatorSid, Replicators, BUILTIN, SidTypeAlias },
266 { WinBuiltinPreWindows2000CompatibleAccessSid, Pre_Windows_2000_Compatible_Access, BUILTIN, SidTypeAlias },
267 { WinBuiltinRemoteDesktopUsersSid, Remote_Desktop_Users, BUILTIN, SidTypeAlias },
268 { WinBuiltinNetworkConfigurationOperatorsSid, Network_Configuration_Operators, BUILTIN, SidTypeAlias },
269 { WinNTLMAuthenticationSid, NTML_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
270 { WinDigestAuthenticationSid, Digest_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
271 { WinSChannelAuthenticationSid, SChannel_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
272 { WinThisOrganizationSid, This_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
273 { WinOtherOrganizationSid, Other_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
274 { WinBuiltinPerfMonitoringUsersSid, Performance_Monitor_Users, BUILTIN, SidTypeAlias },
275 { WinBuiltinPerfLoggingUsersSid, Performance_Log_Users, BUILTIN, SidTypeAlias },
276 { WinBuiltinAnyPackageSid, ALL_APPLICATION_PACKAGES, APPLICATION_PACKAGE_AUTHORITY, SidTypeWellKnownGroup },
279 * ACE access rights
281 static const WCHAR SDDL_READ_CONTROL[] = {'R','C',0};
282 static const WCHAR SDDL_WRITE_DAC[] = {'W','D',0};
283 static const WCHAR SDDL_WRITE_OWNER[] = {'W','O',0};
284 static const WCHAR SDDL_STANDARD_DELETE[] = {'S','D',0};
286 static const WCHAR SDDL_READ_PROPERTY[] = {'R','P',0};
287 static const WCHAR SDDL_WRITE_PROPERTY[] = {'W','P',0};
288 static const WCHAR SDDL_CREATE_CHILD[] = {'C','C',0};
289 static const WCHAR SDDL_DELETE_CHILD[] = {'D','C',0};
290 static const WCHAR SDDL_LIST_CHILDREN[] = {'L','C',0};
291 static const WCHAR SDDL_SELF_WRITE[] = {'S','W',0};
292 static const WCHAR SDDL_LIST_OBJECT[] = {'L','O',0};
293 static const WCHAR SDDL_DELETE_TREE[] = {'D','T',0};
294 static const WCHAR SDDL_CONTROL_ACCESS[] = {'C','R',0};
296 static const WCHAR SDDL_FILE_ALL[] = {'F','A',0};
297 static const WCHAR SDDL_FILE_READ[] = {'F','R',0};
298 static const WCHAR SDDL_FILE_WRITE[] = {'F','W',0};
299 static const WCHAR SDDL_FILE_EXECUTE[] = {'F','X',0};
301 static const WCHAR SDDL_KEY_ALL[] = {'K','A',0};
302 static const WCHAR SDDL_KEY_READ[] = {'K','R',0};
303 static const WCHAR SDDL_KEY_WRITE[] = {'K','W',0};
304 static const WCHAR SDDL_KEY_EXECUTE[] = {'K','X',0};
306 static const WCHAR SDDL_GENERIC_ALL[] = {'G','A',0};
307 static const WCHAR SDDL_GENERIC_READ[] = {'G','R',0};
308 static const WCHAR SDDL_GENERIC_WRITE[] = {'G','W',0};
309 static const WCHAR SDDL_GENERIC_EXECUTE[] = {'G','X',0};
311 static const WCHAR SDDL_NO_READ_UP[] = {'N','R',0};
312 static const WCHAR SDDL_NO_WRITE_UP[] = {'N','W',0};
313 static const WCHAR SDDL_NO_EXECUTE_UP[] = {'N','X',0};
316 * ACL flags
318 static const WCHAR SDDL_PROTECTED[] = {'P',0};
319 static const WCHAR SDDL_AUTO_INHERIT_REQ[] = {'A','R',0};
320 static const WCHAR SDDL_AUTO_INHERITED[] = {'A','I',0};
323 * ACE types
325 static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0};
326 static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0};
327 static const WCHAR SDDL_AUDIT[] = {'A','U',0};
328 static const WCHAR SDDL_ALARM[] = {'A','L',0};
329 static const WCHAR SDDL_MANDATORY_LABEL[] = {'M','L',0};
332 * ACE flags
334 static const WCHAR SDDL_CONTAINER_INHERIT[] = {'C','I',0};
335 static const WCHAR SDDL_OBJECT_INHERIT[] = {'O','I',0};
336 static const WCHAR SDDL_NO_PROPAGATE[] = {'N','P',0};
337 static const WCHAR SDDL_INHERIT_ONLY[] = {'I','O',0};
338 static const WCHAR SDDL_INHERITED[] = {'I','D',0};
339 static const WCHAR SDDL_AUDIT_SUCCESS[] = {'S','A',0};
340 static const WCHAR SDDL_AUDIT_FAILURE[] = {'F','A',0};
342 const char * debugstr_sid(PSID sid)
344 int auth = 0;
345 SID * psid = sid;
347 if (psid == NULL)
348 return "(null)";
350 auth = psid->IdentifierAuthority.Value[5] +
351 (psid->IdentifierAuthority.Value[4] << 8) +
352 (psid->IdentifierAuthority.Value[3] << 16) +
353 (psid->IdentifierAuthority.Value[2] << 24);
355 switch (psid->SubAuthorityCount) {
356 case 0:
357 return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
358 case 1:
359 return wine_dbg_sprintf("S-%d-%d-%u", psid->Revision, auth,
360 psid->SubAuthority[0]);
361 case 2:
362 return wine_dbg_sprintf("S-%d-%d-%u-%u", psid->Revision, auth,
363 psid->SubAuthority[0], psid->SubAuthority[1]);
364 case 3:
365 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u", psid->Revision, auth,
366 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
367 case 4:
368 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u", psid->Revision, auth,
369 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
370 psid->SubAuthority[3]);
371 case 5:
372 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u", psid->Revision, auth,
373 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
374 psid->SubAuthority[3], psid->SubAuthority[4]);
375 case 6:
376 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
377 psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
378 psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
379 case 7:
380 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
381 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
382 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
383 psid->SubAuthority[6]);
384 case 8:
385 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
386 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
387 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
388 psid->SubAuthority[6], psid->SubAuthority[7]);
390 return "(too-big)";
393 /* helper function for SE_FILE_OBJECT objects in [Get|Set]NamedSecurityInfo */
394 static inline DWORD get_security_file( LPCWSTR full_file_name, DWORD access, HANDLE *file )
396 UNICODE_STRING file_nameW;
397 OBJECT_ATTRIBUTES attr;
398 IO_STATUS_BLOCK io;
399 NTSTATUS status;
401 if (!RtlDosPathNameToNtPathName_U( full_file_name, &file_nameW, NULL, NULL ))
402 return ERROR_PATH_NOT_FOUND;
403 attr.Length = sizeof(attr);
404 attr.RootDirectory = 0;
405 attr.Attributes = OBJ_CASE_INSENSITIVE;
406 attr.ObjectName = &file_nameW;
407 attr.SecurityDescriptor = NULL;
408 status = NtCreateFile( file, access|SYNCHRONIZE, &attr, &io, NULL, FILE_FLAG_BACKUP_SEMANTICS,
409 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
410 FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 );
411 RtlFreeUnicodeString( &file_nameW );
412 return RtlNtStatusToDosError( status );
415 /* helper function for SE_SERVICE objects in [Get|Set]NamedSecurityInfo */
416 static inline DWORD get_security_service( LPWSTR full_service_name, DWORD access, HANDLE *service )
418 SC_HANDLE manager = 0;
419 DWORD err;
421 err = SERV_OpenSCManagerW( NULL, NULL, access, (SC_HANDLE *)&manager );
422 if (err == ERROR_SUCCESS)
424 err = SERV_OpenServiceW( manager, full_service_name, access, (SC_HANDLE *)service );
425 CloseServiceHandle( manager );
427 return err;
430 /* helper function for SE_REGISTRY_KEY objects in [Get|Set]NamedSecurityInfo */
431 static inline DWORD get_security_regkey( LPWSTR full_key_name, DWORD access, HANDLE *key )
433 static const WCHAR classes_rootW[] = {'C','L','A','S','S','E','S','_','R','O','O','T',0};
434 static const WCHAR current_userW[] = {'C','U','R','R','E','N','T','_','U','S','E','R',0};
435 static const WCHAR machineW[] = {'M','A','C','H','I','N','E',0};
436 static const WCHAR usersW[] = {'U','S','E','R','S',0};
437 LPWSTR p = strchrW(full_key_name, '\\');
438 int len = p-full_key_name;
439 HKEY hParent;
441 if (!p) return ERROR_INVALID_PARAMETER;
442 if (strncmpW( full_key_name, classes_rootW, len ) == 0)
443 hParent = HKEY_CLASSES_ROOT;
444 else if (strncmpW( full_key_name, current_userW, len ) == 0)
445 hParent = HKEY_CURRENT_USER;
446 else if (strncmpW( full_key_name, machineW, len ) == 0)
447 hParent = HKEY_LOCAL_MACHINE;
448 else if (strncmpW( full_key_name, usersW, len ) == 0)
449 hParent = HKEY_USERS;
450 else
451 return ERROR_INVALID_PARAMETER;
452 return RegOpenKeyExW( hParent, p+1, 0, access, (HKEY *)key );
456 /************************************************************
457 * ADVAPI_IsLocalComputer
459 * Checks whether the server name indicates local machine.
461 BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName)
463 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
464 BOOL Result;
465 LPWSTR buf;
467 if (!ServerName || !ServerName[0])
468 return TRUE;
470 buf = heap_alloc(dwSize * sizeof(WCHAR));
471 Result = GetComputerNameW(buf, &dwSize);
472 if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
473 ServerName += 2;
474 Result = Result && !lstrcmpW(ServerName, buf);
475 heap_free(buf);
477 return Result;
480 /************************************************************
481 * ADVAPI_GetComputerSid
483 BOOL ADVAPI_GetComputerSid(PSID sid)
485 static const struct /* same fields as struct SID */
487 BYTE Revision;
488 BYTE SubAuthorityCount;
489 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
490 DWORD SubAuthority[4];
491 } computer_sid =
492 { SID_REVISION, 4, { SECURITY_NT_AUTHORITY }, { SECURITY_NT_NON_UNIQUE, 0, 0, 0 } };
494 memcpy( sid, &computer_sid, sizeof(computer_sid) );
495 return TRUE;
498 DWORD WINAPI
499 GetEffectiveRightsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pAccessRights )
501 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
503 *pAccessRights = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
504 return 0;
507 DWORD WINAPI
508 GetEffectiveRightsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pAccessRights )
510 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
512 return 1;
515 /* ##############################################
516 ###### SECURITY DESCRIPTOR FUNCTIONS ######
517 ##############################################
520 /******************************************************************************
521 * BuildSecurityDescriptorA [ADVAPI32.@]
523 * Builds a SD from
525 * PARAMS
526 * pOwner [I]
527 * pGroup [I]
528 * cCountOfAccessEntries [I]
529 * pListOfAccessEntries [I]
530 * cCountOfAuditEntries [I]
531 * pListofAuditEntries [I]
532 * pOldSD [I]
533 * lpdwBufferLength [I/O]
534 * pNewSD [O]
536 * RETURNS
537 * Success: ERROR_SUCCESS
538 * Failure: nonzero error code from Winerror.h
540 DWORD WINAPI BuildSecurityDescriptorA(
541 IN PTRUSTEEA pOwner,
542 IN PTRUSTEEA pGroup,
543 IN ULONG cCountOfAccessEntries,
544 IN PEXPLICIT_ACCESSA pListOfAccessEntries,
545 IN ULONG cCountOfAuditEntries,
546 IN PEXPLICIT_ACCESSA pListofAuditEntries,
547 IN PSECURITY_DESCRIPTOR pOldSD,
548 IN OUT PULONG lpdwBufferLength,
549 OUT PSECURITY_DESCRIPTOR* pNewSD)
551 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
552 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
553 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
555 return ERROR_CALL_NOT_IMPLEMENTED;
558 /******************************************************************************
559 * BuildSecurityDescriptorW [ADVAPI32.@]
561 * See BuildSecurityDescriptorA.
563 DWORD WINAPI BuildSecurityDescriptorW(
564 IN PTRUSTEEW pOwner,
565 IN PTRUSTEEW pGroup,
566 IN ULONG cCountOfAccessEntries,
567 IN PEXPLICIT_ACCESSW pListOfAccessEntries,
568 IN ULONG cCountOfAuditEntries,
569 IN PEXPLICIT_ACCESSW pListOfAuditEntries,
570 IN PSECURITY_DESCRIPTOR pOldSD,
571 IN OUT PULONG lpdwBufferLength,
572 OUT PSECURITY_DESCRIPTOR* pNewSD)
574 SECURITY_DESCRIPTOR desc;
575 NTSTATUS status;
576 DWORD ret = ERROR_SUCCESS;
578 TRACE("(%p,%p,%d,%p,%d,%p,%p,%p,%p)\n", pOwner, pGroup,
579 cCountOfAccessEntries, pListOfAccessEntries, cCountOfAuditEntries,
580 pListOfAuditEntries, pOldSD, lpdwBufferLength, pNewSD);
582 if (pOldSD)
584 SECURITY_DESCRIPTOR_CONTROL control;
585 DWORD desc_size, dacl_size = 0, sacl_size = 0, owner_size = 0, group_size = 0;
586 PACL dacl = NULL, sacl = NULL;
587 PSID owner = NULL, group = NULL;
588 DWORD revision;
590 if ((status = RtlGetControlSecurityDescriptor( pOldSD, &control, &revision )) != STATUS_SUCCESS)
591 return RtlNtStatusToDosError( status );
592 if (!(control & SE_SELF_RELATIVE))
593 return ERROR_INVALID_SECURITY_DESCR;
595 desc_size = sizeof(desc);
596 status = RtlSelfRelativeToAbsoluteSD( pOldSD, &desc, &desc_size, dacl, &dacl_size, sacl, &sacl_size,
597 owner, &owner_size, group, &group_size );
598 if (status == STATUS_BUFFER_TOO_SMALL)
600 if (dacl_size)
601 dacl = LocalAlloc( LMEM_FIXED, dacl_size );
602 if (sacl_size)
603 sacl = LocalAlloc( LMEM_FIXED, sacl_size );
604 if (owner_size)
605 owner = LocalAlloc( LMEM_FIXED, owner_size );
606 if (group_size)
607 group = LocalAlloc( LMEM_FIXED, group_size );
609 desc_size = sizeof(desc);
610 status = RtlSelfRelativeToAbsoluteSD( pOldSD, &desc, &desc_size, dacl, &dacl_size, sacl, &sacl_size,
611 owner, &owner_size, group, &group_size );
613 if (status != STATUS_SUCCESS)
615 LocalFree( dacl );
616 LocalFree( sacl );
617 LocalFree( owner );
618 LocalFree( group );
619 return RtlNtStatusToDosError( status );
622 else
624 if ((status = RtlCreateSecurityDescriptor( &desc, SECURITY_DESCRIPTOR_REVISION )) != STATUS_SUCCESS)
625 return RtlNtStatusToDosError( status );
628 if (pOwner)
630 LocalFree( desc.Owner );
631 desc.Owner = LocalAlloc( LMEM_FIXED, sizeof(MAX_SID) );
632 if ((ret = trustee_to_sid( sizeof(MAX_SID), desc.Owner, pOwner )))
633 goto done;
636 if (pGroup)
638 LocalFree( desc.Group );
639 desc.Group = LocalAlloc( LMEM_FIXED, sizeof(MAX_SID) );
640 if ((ret = trustee_to_sid( sizeof(MAX_SID), desc.Group, pGroup )))
641 goto done;
644 if (pListOfAccessEntries)
646 PACL new_dacl;
648 if ((ret = SetEntriesInAclW( cCountOfAccessEntries, pListOfAccessEntries, desc.Dacl, &new_dacl )))
649 goto done;
651 LocalFree( desc.Dacl );
652 desc.Dacl = new_dacl;
653 desc.Control |= SE_DACL_PRESENT;
656 if (pListOfAuditEntries)
658 PACL new_sacl;
660 if ((ret = SetEntriesInAclW( cCountOfAuditEntries, pListOfAuditEntries, desc.Sacl, &new_sacl )))
661 goto done;
663 LocalFree( desc.Sacl );
664 desc.Sacl = new_sacl;
665 desc.Control |= SE_SACL_PRESENT;
668 *lpdwBufferLength = RtlLengthSecurityDescriptor( &desc );
669 *pNewSD = LocalAlloc( LMEM_FIXED, *lpdwBufferLength );
671 if ((status = RtlMakeSelfRelativeSD( &desc, *pNewSD, lpdwBufferLength )) != STATUS_SUCCESS)
673 ret = RtlNtStatusToDosError( status );
674 LocalFree( *pNewSD );
675 *pNewSD = NULL;
678 done:
679 /* free absolute descriptor */
680 LocalFree( desc.Owner );
681 LocalFree( desc.Group );
682 LocalFree( desc.Sacl );
683 LocalFree( desc.Dacl );
684 return ret;
688 static const WCHAR SE_CREATE_TOKEN_NAME_W[] =
689 { 'S','e','C','r','e','a','t','e','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 };
690 static const WCHAR SE_ASSIGNPRIMARYTOKEN_NAME_W[] =
691 { 'S','e','A','s','s','i','g','n','P','r','i','m','a','r','y','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 };
692 static const WCHAR SE_LOCK_MEMORY_NAME_W[] =
693 { 'S','e','L','o','c','k','M','e','m','o','r','y','P','r','i','v','i','l','e','g','e',0 };
694 static const WCHAR SE_INCREASE_QUOTA_NAME_W[] =
695 { 'S','e','I','n','c','r','e','a','s','e','Q','u','o','t','a','P','r','i','v','i','l','e','g','e',0 };
696 static const WCHAR SE_MACHINE_ACCOUNT_NAME_W[] =
697 { 'S','e','M','a','c','h','i','n','e','A','c','c','o','u','n','t','P','r','i','v','i','l','e','g','e',0 };
698 static const WCHAR SE_TCB_NAME_W[] =
699 { 'S','e','T','c','b','P','r','i','v','i','l','e','g','e',0 };
700 static const WCHAR SE_SECURITY_NAME_W[] =
701 { 'S','e','S','e','c','u','r','i','t','y','P','r','i','v','i','l','e','g','e',0 };
702 static const WCHAR SE_TAKE_OWNERSHIP_NAME_W[] =
703 { 'S','e','T','a','k','e','O','w','n','e','r','s','h','i','p','P','r','i','v','i','l','e','g','e',0 };
704 static const WCHAR SE_LOAD_DRIVER_NAME_W[] =
705 { 'S','e','L','o','a','d','D','r','i','v','e','r','P','r','i','v','i','l','e','g','e',0 };
706 static const WCHAR SE_SYSTEM_PROFILE_NAME_W[] =
707 { 'S','e','S','y','s','t','e','m','P','r','o','f','i','l','e','P','r','i','v','i','l','e','g','e',0 };
708 static const WCHAR SE_SYSTEMTIME_NAME_W[] =
709 { 'S','e','S','y','s','t','e','m','t','i','m','e','P','r','i','v','i','l','e','g','e',0 };
710 static const WCHAR SE_PROF_SINGLE_PROCESS_NAME_W[] =
711 { 'S','e','P','r','o','f','i','l','e','S','i','n','g','l','e','P','r','o','c','e','s','s','P','r','i','v','i','l','e','g','e',0 };
712 static const WCHAR SE_INC_BASE_PRIORITY_NAME_W[] =
713 { 'S','e','I','n','c','r','e','a','s','e','B','a','s','e','P','r','i','o','r','i','t','y','P','r','i','v','i','l','e','g','e',0 };
714 static const WCHAR SE_CREATE_PAGEFILE_NAME_W[] =
715 { 'S','e','C','r','e','a','t','e','P','a','g','e','f','i','l','e','P','r','i','v','i','l','e','g','e',0 };
716 static const WCHAR SE_CREATE_PERMANENT_NAME_W[] =
717 { 'S','e','C','r','e','a','t','e','P','e','r','m','a','n','e','n','t','P','r','i','v','i','l','e','g','e',0 };
718 static const WCHAR SE_BACKUP_NAME_W[] =
719 { 'S','e','B','a','c','k','u','p','P','r','i','v','i','l','e','g','e',0 };
720 static const WCHAR SE_RESTORE_NAME_W[] =
721 { 'S','e','R','e','s','t','o','r','e','P','r','i','v','i','l','e','g','e',0 };
722 static const WCHAR SE_SHUTDOWN_NAME_W[] =
723 { 'S','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 };
724 static const WCHAR SE_DEBUG_NAME_W[] =
725 { 'S','e','D','e','b','u','g','P','r','i','v','i','l','e','g','e',0 };
726 static const WCHAR SE_AUDIT_NAME_W[] =
727 { 'S','e','A','u','d','i','t','P','r','i','v','i','l','e','g','e',0 };
728 static const WCHAR SE_SYSTEM_ENVIRONMENT_NAME_W[] =
729 { 'S','e','S','y','s','t','e','m','E','n','v','i','r','o','n','m','e','n','t','P','r','i','v','i','l','e','g','e',0 };
730 static const WCHAR SE_CHANGE_NOTIFY_NAME_W[] =
731 { 'S','e','C','h','a','n','g','e','N','o','t','i','f','y','P','r','i','v','i','l','e','g','e',0 };
732 static const WCHAR SE_REMOTE_SHUTDOWN_NAME_W[] =
733 { 'S','e','R','e','m','o','t','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 };
734 static const WCHAR SE_UNDOCK_NAME_W[] =
735 { 'S','e','U','n','d','o','c','k','P','r','i','v','i','l','e','g','e',0 };
736 static const WCHAR SE_SYNC_AGENT_NAME_W[] =
737 { 'S','e','S','y','n','c','A','g','e','n','t','P','r','i','v','i','l','e','g','e',0 };
738 static const WCHAR SE_ENABLE_DELEGATION_NAME_W[] =
739 { 'S','e','E','n','a','b','l','e','D','e','l','e','g','a','t','i','o','n','P','r','i','v','i','l','e','g','e',0 };
740 static const WCHAR SE_MANAGE_VOLUME_NAME_W[] =
741 { 'S','e','M','a','n','a','g','e','V','o','l','u','m','e','P','r','i','v','i','l','e','g','e',0 };
742 static const WCHAR SE_IMPERSONATE_NAME_W[] =
743 { 'S','e','I','m','p','e','r','s','o','n','a','t','e','P','r','i','v','i','l','e','g','e',0 };
744 static const WCHAR SE_CREATE_GLOBAL_NAME_W[] =
745 { 'S','e','C','r','e','a','t','e','G','l','o','b','a','l','P','r','i','v','i','l','e','g','e',0 };
747 static const WCHAR * const WellKnownPrivNames[SE_MAX_WELL_KNOWN_PRIVILEGE + 1] =
749 NULL,
750 NULL,
751 SE_CREATE_TOKEN_NAME_W,
752 SE_ASSIGNPRIMARYTOKEN_NAME_W,
753 SE_LOCK_MEMORY_NAME_W,
754 SE_INCREASE_QUOTA_NAME_W,
755 SE_MACHINE_ACCOUNT_NAME_W,
756 SE_TCB_NAME_W,
757 SE_SECURITY_NAME_W,
758 SE_TAKE_OWNERSHIP_NAME_W,
759 SE_LOAD_DRIVER_NAME_W,
760 SE_SYSTEM_PROFILE_NAME_W,
761 SE_SYSTEMTIME_NAME_W,
762 SE_PROF_SINGLE_PROCESS_NAME_W,
763 SE_INC_BASE_PRIORITY_NAME_W,
764 SE_CREATE_PAGEFILE_NAME_W,
765 SE_CREATE_PERMANENT_NAME_W,
766 SE_BACKUP_NAME_W,
767 SE_RESTORE_NAME_W,
768 SE_SHUTDOWN_NAME_W,
769 SE_DEBUG_NAME_W,
770 SE_AUDIT_NAME_W,
771 SE_SYSTEM_ENVIRONMENT_NAME_W,
772 SE_CHANGE_NOTIFY_NAME_W,
773 SE_REMOTE_SHUTDOWN_NAME_W,
774 SE_UNDOCK_NAME_W,
775 SE_SYNC_AGENT_NAME_W,
776 SE_ENABLE_DELEGATION_NAME_W,
777 SE_MANAGE_VOLUME_NAME_W,
778 SE_IMPERSONATE_NAME_W,
779 SE_CREATE_GLOBAL_NAME_W,
782 const WCHAR *get_wellknown_privilege_name(const LUID *luid)
784 if (luid->HighPart || luid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
785 luid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE || !WellKnownPrivNames[luid->LowPart])
786 return NULL;
788 return WellKnownPrivNames[luid->LowPart];
791 /******************************************************************************
792 * LookupPrivilegeValueW [ADVAPI32.@]
794 * See LookupPrivilegeValueA.
796 BOOL WINAPI
797 LookupPrivilegeValueW( LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid )
799 UINT i;
801 TRACE("%s,%s,%p\n",debugstr_w(lpSystemName), debugstr_w(lpName), lpLuid);
803 if (!ADVAPI_IsLocalComputer(lpSystemName))
805 SetLastError(RPC_S_SERVER_UNAVAILABLE);
806 return FALSE;
808 if (!lpName)
810 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
811 return FALSE;
813 for( i=SE_MIN_WELL_KNOWN_PRIVILEGE; i<=SE_MAX_WELL_KNOWN_PRIVILEGE; i++ )
815 if( !WellKnownPrivNames[i] )
816 continue;
817 if( strcmpiW( WellKnownPrivNames[i], lpName) )
818 continue;
819 lpLuid->LowPart = i;
820 lpLuid->HighPart = 0;
821 TRACE( "%s -> %08x-%08x\n",debugstr_w( lpSystemName ),
822 lpLuid->HighPart, lpLuid->LowPart );
823 return TRUE;
825 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
826 return FALSE;
829 /******************************************************************************
830 * LookupPrivilegeValueA [ADVAPI32.@]
832 * Retrieves LUID used on a system to represent the privilege name.
834 * PARAMS
835 * lpSystemName [I] Name of the system
836 * lpName [I] Name of the privilege
837 * lpLuid [O] Destination for the resulting LUID
839 * RETURNS
840 * Success: TRUE. lpLuid contains the requested LUID.
841 * Failure: FALSE.
843 BOOL WINAPI
844 LookupPrivilegeValueA( LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid )
846 UNICODE_STRING lpSystemNameW;
847 UNICODE_STRING lpNameW;
848 BOOL ret;
850 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
851 RtlCreateUnicodeStringFromAsciiz(&lpNameW,lpName);
852 ret = LookupPrivilegeValueW(lpSystemNameW.Buffer, lpNameW.Buffer, lpLuid);
853 RtlFreeUnicodeString(&lpNameW);
854 RtlFreeUnicodeString(&lpSystemNameW);
855 return ret;
858 BOOL WINAPI LookupPrivilegeDisplayNameA( LPCSTR lpSystemName, LPCSTR lpName, LPSTR lpDisplayName,
859 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
861 FIXME("%s %s %s %p %p - stub\n", debugstr_a(lpSystemName), debugstr_a(lpName),
862 debugstr_a(lpDisplayName), cchDisplayName, lpLanguageId);
864 return FALSE;
867 BOOL WINAPI LookupPrivilegeDisplayNameW( LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName,
868 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
870 FIXME("%s %s %s %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpName),
871 debugstr_w(lpDisplayName), cchDisplayName, lpLanguageId);
873 return FALSE;
876 /******************************************************************************
877 * LookupPrivilegeNameA [ADVAPI32.@]
879 * See LookupPrivilegeNameW.
881 BOOL WINAPI
882 LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName,
883 LPDWORD cchName)
885 UNICODE_STRING lpSystemNameW;
886 BOOL ret;
887 DWORD wLen = 0;
889 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
891 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
892 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
893 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
895 LPWSTR lpNameW = heap_alloc(wLen * sizeof(WCHAR));
897 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
898 &wLen);
899 if (ret)
901 /* Windows crashes if cchName is NULL, so will I */
902 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
903 *cchName, NULL, NULL);
905 if (len == 0)
907 /* WideCharToMultiByte failed */
908 ret = FALSE;
910 else if (len > *cchName)
912 *cchName = len;
913 SetLastError(ERROR_INSUFFICIENT_BUFFER);
914 ret = FALSE;
916 else
918 /* WideCharToMultiByte succeeded, output length needs to be
919 * length not including NULL terminator
921 *cchName = len - 1;
924 heap_free(lpNameW);
926 RtlFreeUnicodeString(&lpSystemNameW);
927 return ret;
930 /******************************************************************************
931 * LookupPrivilegeNameW [ADVAPI32.@]
933 * Retrieves the privilege name referred to by the LUID lpLuid.
935 * PARAMS
936 * lpSystemName [I] Name of the system
937 * lpLuid [I] Privilege value
938 * lpName [O] Name of the privilege
939 * cchName [I/O] Number of characters in lpName.
941 * RETURNS
942 * Success: TRUE. lpName contains the name of the privilege whose value is
943 * *lpLuid.
944 * Failure: FALSE.
946 * REMARKS
947 * Only well-known privilege names (those defined in winnt.h) can be retrieved
948 * using this function.
949 * If the length of lpName is too small, on return *cchName will contain the
950 * number of WCHARs needed to contain the privilege, including the NULL
951 * terminator, and GetLastError will return ERROR_INSUFFICIENT_BUFFER.
952 * On success, *cchName will contain the number of characters stored in
953 * lpName, NOT including the NULL terminator.
955 BOOL WINAPI
956 LookupPrivilegeNameW( LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName,
957 LPDWORD cchName)
959 size_t privNameLen;
961 TRACE("%s,%p,%p,%p\n",debugstr_w(lpSystemName), lpLuid, lpName, cchName);
963 if (!ADVAPI_IsLocalComputer(lpSystemName))
965 SetLastError(RPC_S_SERVER_UNAVAILABLE);
966 return FALSE;
968 if (lpLuid->HighPart || (lpLuid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
969 lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
971 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
972 return FALSE;
974 privNameLen = strlenW(WellKnownPrivNames[lpLuid->LowPart]);
975 /* Windows crashes if cchName is NULL, so will I */
976 if (*cchName <= privNameLen)
978 *cchName = privNameLen + 1;
979 SetLastError(ERROR_INSUFFICIENT_BUFFER);
980 return FALSE;
982 else
984 strcpyW(lpName, WellKnownPrivNames[lpLuid->LowPart]);
985 *cchName = privNameLen;
986 return TRUE;
990 /******************************************************************************
991 * GetFileSecurityA [ADVAPI32.@]
993 * Obtains Specified information about the security of a file or directory.
995 * PARAMS
996 * lpFileName [I] Name of the file to get info for
997 * RequestedInformation [I] SE_ flags from "winnt.h"
998 * pSecurityDescriptor [O] Destination for security information
999 * nLength [I] Length of pSecurityDescriptor
1000 * lpnLengthNeeded [O] Destination for length of returned security information
1002 * RETURNS
1003 * Success: TRUE. pSecurityDescriptor contains the requested information.
1004 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
1006 * NOTES
1007 * The information returned is constrained by the callers access rights and
1008 * privileges.
1010 BOOL WINAPI
1011 GetFileSecurityA( LPCSTR lpFileName,
1012 SECURITY_INFORMATION RequestedInformation,
1013 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1014 DWORD nLength, LPDWORD lpnLengthNeeded )
1016 BOOL r;
1017 LPWSTR name;
1019 name = SERV_dup(lpFileName);
1020 r = GetFileSecurityW( name, RequestedInformation, pSecurityDescriptor,
1021 nLength, lpnLengthNeeded );
1022 heap_free( name );
1024 return r;
1027 /******************************************************************************
1028 * LookupAccountSidA [ADVAPI32.@]
1030 BOOL WINAPI
1031 LookupAccountSidA(
1032 IN LPCSTR system,
1033 IN PSID sid,
1034 OUT LPSTR account,
1035 IN OUT LPDWORD accountSize,
1036 OUT LPSTR domain,
1037 IN OUT LPDWORD domainSize,
1038 OUT PSID_NAME_USE name_use )
1040 DWORD len;
1041 BOOL r;
1042 LPWSTR systemW;
1043 LPWSTR accountW = NULL;
1044 LPWSTR domainW = NULL;
1045 DWORD accountSizeW = *accountSize;
1046 DWORD domainSizeW = *domainSize;
1048 systemW = SERV_dup(system);
1049 if (account)
1050 accountW = heap_alloc( accountSizeW * sizeof(WCHAR) );
1051 if (domain)
1052 domainW = heap_alloc( domainSizeW * sizeof(WCHAR) );
1054 r = LookupAccountSidW( systemW, sid, accountW, &accountSizeW, domainW, &domainSizeW, name_use );
1056 if (r) {
1057 if (accountW && *accountSize) {
1058 len = WideCharToMultiByte( CP_ACP, 0, accountW, -1, NULL, 0, NULL, NULL );
1059 WideCharToMultiByte( CP_ACP, 0, accountW, -1, account, len, NULL, NULL );
1060 *accountSize = len;
1061 } else
1062 *accountSize = accountSizeW + 1;
1064 if (domainW && *domainSize) {
1065 len = WideCharToMultiByte( CP_ACP, 0, domainW, -1, NULL, 0, NULL, NULL );
1066 WideCharToMultiByte( CP_ACP, 0, domainW, -1, domain, len, NULL, NULL );
1067 *domainSize = len;
1068 } else
1069 *domainSize = domainSizeW + 1;
1071 else
1073 *accountSize = accountSizeW + 1;
1074 *domainSize = domainSizeW + 1;
1077 heap_free( systemW );
1078 heap_free( accountW );
1079 heap_free( domainW );
1081 return r;
1084 /******************************************************************************
1085 * LookupAccountSidLocalA [ADVAPI32.@]
1087 BOOL WINAPI
1088 LookupAccountSidLocalA(
1089 PSID sid,
1090 LPSTR account,
1091 LPDWORD accountSize,
1092 LPSTR domain,
1093 LPDWORD domainSize,
1094 PSID_NAME_USE name_use )
1096 return LookupAccountSidA(NULL, sid, account, accountSize, domain, domainSize, name_use);
1099 /******************************************************************************
1100 * LookupAccountSidW [ADVAPI32.@]
1102 * PARAMS
1103 * system []
1104 * sid []
1105 * account []
1106 * accountSize []
1107 * domain []
1108 * domainSize []
1109 * name_use []
1112 BOOL WINAPI
1113 LookupAccountSidW(
1114 IN LPCWSTR system,
1115 IN PSID sid,
1116 OUT LPWSTR account,
1117 IN OUT LPDWORD accountSize,
1118 OUT LPWSTR domain,
1119 IN OUT LPDWORD domainSize,
1120 OUT PSID_NAME_USE name_use )
1122 unsigned int i, j;
1123 const WCHAR * ac = NULL;
1124 const WCHAR * dm = NULL;
1125 SID_NAME_USE use = 0;
1126 LPWSTR computer_name = NULL;
1127 LPWSTR account_name = NULL;
1129 TRACE("(%s,sid=%s,%p,%p(%u),%p,%p(%u),%p)\n",
1130 debugstr_w(system),debugstr_sid(sid),
1131 account,accountSize,accountSize?*accountSize:0,
1132 domain,domainSize,domainSize?*domainSize:0,
1133 name_use);
1135 if (!ADVAPI_IsLocalComputer(system)) {
1136 FIXME("Only local computer supported!\n");
1137 SetLastError(RPC_S_SERVER_UNAVAILABLE);
1138 return FALSE;
1141 /* check the well known SIDs first */
1142 for (i = 0; i <= WinAccountProtectedUsersSid; i++) {
1143 if (IsWellKnownSid(sid, i)) {
1144 for (j = 0; j < ARRAY_SIZE(ACCOUNT_SIDS); j++) {
1145 if (ACCOUNT_SIDS[j].type == i) {
1146 ac = ACCOUNT_SIDS[j].account;
1147 dm = ACCOUNT_SIDS[j].domain;
1148 use = ACCOUNT_SIDS[j].name_use;
1151 break;
1155 if (dm == NULL) {
1156 MAX_SID local;
1158 /* check for the local computer next */
1159 if (ADVAPI_GetComputerSid(&local)) {
1160 DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
1161 BOOL result;
1163 computer_name = heap_alloc(size * sizeof(WCHAR));
1164 result = GetComputerNameW(computer_name, &size);
1166 if (result) {
1167 if (EqualSid(sid, &local)) {
1168 dm = computer_name;
1169 ac = Blank;
1170 use = 3;
1171 } else {
1172 local.SubAuthorityCount++;
1174 if (EqualPrefixSid(sid, &local)) {
1175 dm = computer_name;
1176 use = 1;
1177 switch (((MAX_SID *)sid)->SubAuthority[4]) {
1178 case DOMAIN_USER_RID_ADMIN:
1179 ac = Administrator;
1180 break;
1181 case DOMAIN_USER_RID_GUEST:
1182 ac = Guest;
1183 break;
1184 case DOMAIN_GROUP_RID_ADMINS:
1185 ac = Domain_Admins;
1186 break;
1187 case DOMAIN_GROUP_RID_USERS:
1188 ac = None;
1189 use = SidTypeGroup;
1190 break;
1191 case DOMAIN_GROUP_RID_GUESTS:
1192 ac = Domain_Guests;
1193 break;
1194 case DOMAIN_GROUP_RID_COMPUTERS:
1195 ac = Domain_Computers;
1196 break;
1197 case DOMAIN_GROUP_RID_CONTROLLERS:
1198 ac = Domain_Controllers;
1199 break;
1200 case DOMAIN_GROUP_RID_CERT_ADMINS:
1201 ac = Cert_Publishers;
1202 break;
1203 case DOMAIN_GROUP_RID_SCHEMA_ADMINS:
1204 ac = Schema_Admins;
1205 break;
1206 case DOMAIN_GROUP_RID_ENTERPRISE_ADMINS:
1207 ac = Enterprise_Admins;
1208 break;
1209 case DOMAIN_GROUP_RID_POLICY_ADMINS:
1210 ac = Group_Policy_Creator_Owners;
1211 break;
1212 case DOMAIN_ALIAS_RID_RAS_SERVERS:
1213 ac = RAS_and_IAS_Servers;
1214 break;
1215 case 1000: /* first user account */
1216 size = UNLEN + 1;
1217 account_name = heap_alloc(size * sizeof(WCHAR));
1218 if (GetUserNameW(account_name, &size))
1219 ac = account_name;
1220 else
1221 dm = NULL;
1223 break;
1224 default:
1225 dm = NULL;
1226 break;
1234 if (dm) {
1235 DWORD ac_len = lstrlenW(ac);
1236 DWORD dm_len = lstrlenW(dm);
1237 BOOL status = TRUE;
1239 if (*accountSize > ac_len) {
1240 if (account)
1241 lstrcpyW(account, ac);
1243 if (*domainSize > dm_len) {
1244 if (domain)
1245 lstrcpyW(domain, dm);
1247 if ((*accountSize && *accountSize < ac_len) ||
1248 (!account && !*accountSize && ac_len) ||
1249 (*domainSize && *domainSize < dm_len) ||
1250 (!domain && !*domainSize && dm_len))
1252 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1253 status = FALSE;
1255 if (*domainSize)
1256 *domainSize = dm_len;
1257 else
1258 *domainSize = dm_len + 1;
1259 if (*accountSize)
1260 *accountSize = ac_len;
1261 else
1262 *accountSize = ac_len + 1;
1264 heap_free(account_name);
1265 heap_free(computer_name);
1266 if (status) *name_use = use;
1267 return status;
1270 heap_free(account_name);
1271 heap_free(computer_name);
1272 SetLastError(ERROR_NONE_MAPPED);
1273 return FALSE;
1276 /******************************************************************************
1277 * LookupAccountSidLocalW [ADVAPI32.@]
1279 BOOL WINAPI
1280 LookupAccountSidLocalW(
1281 PSID sid,
1282 LPWSTR account,
1283 LPDWORD accountSize,
1284 LPWSTR domain,
1285 LPDWORD domainSize,
1286 PSID_NAME_USE name_use )
1288 return LookupAccountSidW(NULL, sid, account, accountSize, domain, domainSize, name_use);
1291 /******************************************************************************
1292 * SetFileSecurityA [ADVAPI32.@]
1294 * See SetFileSecurityW.
1296 BOOL WINAPI SetFileSecurityA( LPCSTR lpFileName,
1297 SECURITY_INFORMATION RequestedInformation,
1298 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1300 BOOL r;
1301 LPWSTR name;
1303 name = SERV_dup(lpFileName);
1304 r = SetFileSecurityW( name, RequestedInformation, pSecurityDescriptor );
1305 heap_free( name );
1307 return r;
1310 /******************************************************************************
1311 * QueryWindows31FilesMigration [ADVAPI32.@]
1313 * PARAMS
1314 * x1 []
1316 BOOL WINAPI
1317 QueryWindows31FilesMigration( DWORD x1 )
1319 FIXME("(%d):stub\n",x1);
1320 return TRUE;
1323 /******************************************************************************
1324 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
1326 * PARAMS
1327 * x1 []
1328 * x2 []
1329 * x3 []
1330 * x4 []
1332 BOOL WINAPI
1333 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
1334 DWORD x4 )
1336 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
1337 return TRUE;
1340 /******************************************************************************
1341 * NotifyBootConfigStatus [ADVAPI32.@]
1343 * PARAMS
1344 * x1 []
1346 BOOL WINAPI
1347 NotifyBootConfigStatus( BOOL x1 )
1349 FIXME("(0x%08d):stub\n",x1);
1350 return TRUE;
1353 /******************************************************************************
1354 * LookupAccountNameA [ADVAPI32.@]
1356 BOOL WINAPI
1357 LookupAccountNameA(
1358 IN LPCSTR system,
1359 IN LPCSTR account,
1360 OUT PSID sid,
1361 OUT LPDWORD cbSid,
1362 LPSTR ReferencedDomainName,
1363 IN OUT LPDWORD cbReferencedDomainName,
1364 OUT PSID_NAME_USE name_use )
1366 BOOL ret;
1367 UNICODE_STRING lpSystemW;
1368 UNICODE_STRING lpAccountW;
1369 LPWSTR lpReferencedDomainNameW = NULL;
1371 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, system);
1372 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, account);
1374 if (ReferencedDomainName)
1375 lpReferencedDomainNameW = heap_alloc(*cbReferencedDomainName * sizeof(WCHAR));
1377 ret = LookupAccountNameW(lpSystemW.Buffer, lpAccountW.Buffer, sid, cbSid, lpReferencedDomainNameW,
1378 cbReferencedDomainName, name_use);
1380 if (ret && lpReferencedDomainNameW)
1382 WideCharToMultiByte(CP_ACP, 0, lpReferencedDomainNameW, -1,
1383 ReferencedDomainName, *cbReferencedDomainName+1, NULL, NULL);
1386 RtlFreeUnicodeString(&lpSystemW);
1387 RtlFreeUnicodeString(&lpAccountW);
1388 heap_free(lpReferencedDomainNameW);
1390 return ret;
1393 /******************************************************************************
1394 * lookup_user_account_name
1396 static BOOL lookup_user_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
1397 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
1399 char buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
1400 DWORD len = sizeof(buffer);
1401 HANDLE token;
1402 BOOL ret;
1403 PSID pSid;
1404 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
1405 DWORD nameLen;
1407 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
1409 if (GetLastError() != ERROR_NO_TOKEN) return FALSE;
1410 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) return FALSE;
1413 ret = GetTokenInformation(token, TokenUser, buffer, len, &len);
1414 CloseHandle( token );
1416 if (!ret) return FALSE;
1418 pSid = ((TOKEN_USER *)buffer)->User.Sid;
1420 if (Sid != NULL && (*cbSid >= GetLengthSid(pSid)))
1421 CopySid(*cbSid, Sid, pSid);
1422 if (*cbSid < GetLengthSid(pSid))
1424 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1425 ret = FALSE;
1427 *cbSid = GetLengthSid(pSid);
1429 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
1430 if (!GetComputerNameW(domainName, &nameLen))
1432 domainName[0] = 0;
1433 nameLen = 0;
1435 if (*cchReferencedDomainName <= nameLen || !ret)
1437 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1438 nameLen += 1;
1439 ret = FALSE;
1441 else if (ReferencedDomainName)
1442 strcpyW(ReferencedDomainName, domainName);
1444 *cchReferencedDomainName = nameLen;
1446 if (ret)
1447 *peUse = SidTypeUser;
1449 return ret;
1452 /******************************************************************************
1453 * lookup_computer_account_name
1455 static BOOL lookup_computer_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
1456 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
1458 MAX_SID local;
1459 BOOL ret;
1460 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
1461 DWORD nameLen;
1463 if ((ret = ADVAPI_GetComputerSid(&local)))
1465 if (Sid != NULL && (*cbSid >= GetLengthSid(&local)))
1466 CopySid(*cbSid, Sid, &local);
1467 if (*cbSid < GetLengthSid(&local))
1469 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1470 ret = FALSE;
1472 *cbSid = GetLengthSid(&local);
1475 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
1476 if (!GetComputerNameW(domainName, &nameLen))
1478 domainName[0] = 0;
1479 nameLen = 0;
1481 if (*cchReferencedDomainName <= nameLen || !ret)
1483 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1484 nameLen += 1;
1485 ret = FALSE;
1487 else if (ReferencedDomainName)
1488 strcpyW(ReferencedDomainName, domainName);
1490 *cchReferencedDomainName = nameLen;
1492 if (ret)
1493 *peUse = SidTypeDomain;
1495 return ret;
1498 static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STRING *account,
1499 LSA_UNICODE_STRING *domain )
1501 WCHAR *p = str->Buffer + str->Length / sizeof(WCHAR) - 1;
1503 while (p > str->Buffer && *p != '\\') p--;
1505 if (*p == '\\')
1507 domain->Buffer = str->Buffer;
1508 domain->Length = (p - str->Buffer) * sizeof(WCHAR);
1510 account->Buffer = p + 1;
1511 account->Length = str->Length - ((p - str->Buffer + 1) * sizeof(WCHAR));
1513 else
1515 domain->Buffer = NULL;
1516 domain->Length = 0;
1518 account->Buffer = str->Buffer;
1519 account->Length = str->Length;
1523 static BOOL match_domain( ULONG idx, const LSA_UNICODE_STRING *domain )
1525 ULONG len = strlenW( ACCOUNT_SIDS[idx].domain );
1527 if (len == domain->Length / sizeof(WCHAR) && !strncmpiW( domain->Buffer, ACCOUNT_SIDS[idx].domain, len ))
1528 return TRUE;
1530 return FALSE;
1533 static BOOL match_account( ULONG idx, const LSA_UNICODE_STRING *account )
1535 ULONG len = strlenW( ACCOUNT_SIDS[idx].account );
1537 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].account, len ))
1538 return TRUE;
1540 if (ACCOUNT_SIDS[idx].alias)
1542 len = strlenW( ACCOUNT_SIDS[idx].alias );
1543 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].alias, len ))
1544 return TRUE;
1546 return FALSE;
1550 * Helper function for LookupAccountNameW
1552 BOOL lookup_local_wellknown_name( const LSA_UNICODE_STRING *account_and_domain,
1553 PSID Sid, LPDWORD cbSid,
1554 LPWSTR ReferencedDomainName,
1555 LPDWORD cchReferencedDomainName,
1556 PSID_NAME_USE peUse, BOOL *handled )
1558 PSID pSid;
1559 LSA_UNICODE_STRING account, domain;
1560 BOOL ret = TRUE;
1561 ULONG i;
1563 *handled = FALSE;
1564 split_domain_account( account_and_domain, &account, &domain );
1566 for (i = 0; i < ARRAY_SIZE(ACCOUNT_SIDS); i++)
1568 /* check domain first */
1569 if (domain.Buffer && !match_domain( i, &domain )) continue;
1571 if (match_account( i, &account ))
1573 DWORD len, sidLen = SECURITY_MAX_SID_SIZE;
1575 if (!(pSid = heap_alloc( sidLen ))) return FALSE;
1577 if ((ret = CreateWellKnownSid( ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen )))
1579 if (*cbSid < sidLen)
1581 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1582 ret = FALSE;
1584 else if (Sid)
1586 CopySid(*cbSid, Sid, pSid);
1588 *cbSid = sidLen;
1591 len = strlenW( ACCOUNT_SIDS[i].domain );
1592 if (*cchReferencedDomainName <= len || !ret)
1594 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1595 len++;
1596 ret = FALSE;
1598 else if (ReferencedDomainName)
1600 strcpyW( ReferencedDomainName, ACCOUNT_SIDS[i].domain );
1603 *cchReferencedDomainName = len;
1604 if (ret)
1605 *peUse = ACCOUNT_SIDS[i].name_use;
1607 heap_free(pSid);
1608 *handled = TRUE;
1609 return ret;
1612 return ret;
1615 BOOL lookup_local_user_name( const LSA_UNICODE_STRING *account_and_domain,
1616 PSID Sid, LPDWORD cbSid,
1617 LPWSTR ReferencedDomainName,
1618 LPDWORD cchReferencedDomainName,
1619 PSID_NAME_USE peUse, BOOL *handled )
1621 DWORD nameLen;
1622 LPWSTR userName = NULL;
1623 LSA_UNICODE_STRING account, domain;
1624 BOOL ret = TRUE;
1626 *handled = FALSE;
1627 split_domain_account( account_and_domain, &account, &domain );
1629 /* Let the current Unix user id masquerade as first Windows user account */
1631 nameLen = UNLEN + 1;
1632 if (!(userName = heap_alloc( nameLen * sizeof(WCHAR) ))) return FALSE;
1634 if (domain.Buffer)
1636 /* check to make sure this account is on this computer */
1637 if (GetComputerNameW( userName, &nameLen ) &&
1638 (domain.Length / sizeof(WCHAR) != nameLen || strncmpW( domain.Buffer, userName, nameLen )))
1640 SetLastError(ERROR_NONE_MAPPED);
1641 ret = FALSE;
1643 nameLen = UNLEN + 1;
1646 if (GetUserNameW( userName, &nameLen ) &&
1647 account.Length / sizeof(WCHAR) == nameLen - 1 && !strncmpW( account.Buffer, userName, nameLen - 1 ))
1649 ret = lookup_user_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
1650 *handled = TRUE;
1652 else
1654 nameLen = UNLEN + 1;
1655 if (GetComputerNameW( userName, &nameLen ) &&
1656 account.Length / sizeof(WCHAR) == nameLen && !strncmpW( account.Buffer, userName , nameLen ))
1658 ret = lookup_computer_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
1659 *handled = TRUE;
1663 heap_free(userName);
1664 return ret;
1667 /******************************************************************************
1668 * LookupAccountNameW [ADVAPI32.@]
1670 BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
1671 LPDWORD cbSid, LPWSTR ReferencedDomainName,
1672 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
1674 BOOL ret, handled;
1675 LSA_UNICODE_STRING account;
1677 TRACE("%s %s %p %p %p %p %p\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
1678 Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
1680 if (!ADVAPI_IsLocalComputer( lpSystemName ))
1682 FIXME("remote computer not supported\n");
1683 SetLastError( RPC_S_SERVER_UNAVAILABLE );
1684 return FALSE;
1687 if (!lpAccountName || !strcmpW( lpAccountName, Blank ))
1689 lpAccountName = BUILTIN;
1692 RtlInitUnicodeString( &account, lpAccountName );
1694 /* Check well known SIDs first */
1695 ret = lookup_local_wellknown_name( &account, Sid, cbSid, ReferencedDomainName,
1696 cchReferencedDomainName, peUse, &handled );
1697 if (handled)
1698 return ret;
1700 /* Check user names */
1701 ret = lookup_local_user_name( &account, Sid, cbSid, ReferencedDomainName,
1702 cchReferencedDomainName, peUse, &handled);
1703 if (handled)
1704 return ret;
1706 SetLastError( ERROR_NONE_MAPPED );
1707 return FALSE;
1710 /******************************************************************************
1711 * AccessCheckAndAuditAlarmA [ADVAPI32.@]
1713 BOOL WINAPI AccessCheckAndAuditAlarmA(LPCSTR Subsystem, LPVOID HandleId, LPSTR ObjectTypeName,
1714 LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
1715 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
1716 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
1718 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_a(Subsystem),
1719 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName),
1720 SecurityDescriptor, DesiredAccess, GenericMapping,
1721 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
1722 return TRUE;
1725 BOOL WINAPI ObjectCloseAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
1727 FIXME("stub (%s,%p,%x)\n", debugstr_a(SubsystemName), HandleId, GenerateOnClose);
1729 return TRUE;
1732 BOOL WINAPI ObjectOpenAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName,
1733 LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
1734 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
1735 LPBOOL GenerateOnClose)
1737 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_a(SubsystemName),
1738 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName), pSecurityDescriptor,
1739 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
1740 GenerateOnClose);
1742 return TRUE;
1745 BOOL WINAPI ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
1746 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
1748 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_a(SubsystemName), HandleId, ClientToken,
1749 DesiredAccess, Privileges, AccessGranted);
1751 return TRUE;
1754 BOOL WINAPI PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken,
1755 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
1757 FIXME("stub (%s,%s,%p,%p,%x)\n", debugstr_a(SubsystemName), debugstr_a(ServiceName),
1758 ClientToken, Privileges, AccessGranted);
1760 return TRUE;
1763 /******************************************************************************
1764 * GetSecurityInfo [ADVAPI32.@]
1766 * Retrieves a copy of the security descriptor associated with an object.
1768 * PARAMS
1769 * hObject [I] A handle for the object.
1770 * ObjectType [I] The type of object.
1771 * SecurityInfo [I] A bitmask indicating what info to retrieve.
1772 * ppsidOwner [O] If non-null, receives a pointer to the owner SID.
1773 * ppsidGroup [O] If non-null, receives a pointer to the group SID.
1774 * ppDacl [O] If non-null, receives a pointer to the DACL.
1775 * ppSacl [O] If non-null, receives a pointer to the SACL.
1776 * ppSecurityDescriptor [O] Receives a pointer to the security descriptor,
1777 * which must be freed with LocalFree.
1779 * RETURNS
1780 * ERROR_SUCCESS if all's well, and a WIN32 error code otherwise.
1782 DWORD WINAPI GetSecurityInfo(
1783 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
1784 SECURITY_INFORMATION SecurityInfo, PSID *ppsidOwner,
1785 PSID *ppsidGroup, PACL *ppDacl, PACL *ppSacl,
1786 PSECURITY_DESCRIPTOR *ppSecurityDescriptor
1789 PSECURITY_DESCRIPTOR sd;
1790 NTSTATUS status;
1791 ULONG n1, n2;
1792 BOOL present, defaulted;
1794 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
1795 if (!(ppsidOwner||ppsidGroup||ppDacl||ppSacl||ppSecurityDescriptor)) return ERROR_INVALID_PARAMETER;
1797 /* If no descriptor, we have to check that there's a pointer for the requested information */
1798 if( !ppSecurityDescriptor && (
1799 ((SecurityInfo & OWNER_SECURITY_INFORMATION) && !ppsidOwner)
1800 || ((SecurityInfo & GROUP_SECURITY_INFORMATION) && !ppsidGroup)
1801 || ((SecurityInfo & DACL_SECURITY_INFORMATION) && !ppDacl)
1802 || ((SecurityInfo & SACL_SECURITY_INFORMATION) && !ppSacl) ))
1803 return ERROR_INVALID_PARAMETER;
1805 switch (ObjectType)
1807 case SE_SERVICE:
1808 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, NULL, 0, &n1);
1809 break;
1810 default:
1811 status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1);
1812 break;
1814 if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS)
1815 return RtlNtStatusToDosError(status);
1817 sd = LocalAlloc(0, n1);
1818 if (!sd)
1819 return ERROR_NOT_ENOUGH_MEMORY;
1821 switch (ObjectType)
1823 case SE_SERVICE:
1824 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, sd, n1, &n2);
1825 break;
1826 default:
1827 status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2);
1828 break;
1830 if (status != STATUS_SUCCESS)
1832 LocalFree(sd);
1833 return RtlNtStatusToDosError(status);
1836 if (ppsidOwner)
1838 *ppsidOwner = NULL;
1839 GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted);
1841 if (ppsidGroup)
1843 *ppsidGroup = NULL;
1844 GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted);
1846 if (ppDacl)
1848 *ppDacl = NULL;
1849 GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted);
1851 if (ppSacl)
1853 *ppSacl = NULL;
1854 GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted);
1856 if (ppSecurityDescriptor)
1857 *ppSecurityDescriptor = sd;
1859 /* The security descriptor (sd) cannot be freed if ppSecurityDescriptor is
1860 * NULL, because native happily returns the SIDs and ACLs that are requested
1861 * in this case.
1864 return ERROR_SUCCESS;
1867 /******************************************************************************
1868 * GetSecurityInfoExA [ADVAPI32.@]
1870 DWORD WINAPI GetSecurityInfoExA(
1871 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
1872 SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
1873 LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
1874 PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
1877 FIXME("stub!\n");
1878 return ERROR_BAD_PROVIDER;
1881 /******************************************************************************
1882 * GetSecurityInfoExW [ADVAPI32.@]
1884 DWORD WINAPI GetSecurityInfoExW(
1885 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
1886 SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
1887 LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList,
1888 PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
1891 FIXME("stub!\n");
1892 return ERROR_BAD_PROVIDER;
1895 /******************************************************************************
1896 * BuildExplicitAccessWithNameA [ADVAPI32.@]
1898 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
1899 LPSTR pTrusteeName, DWORD AccessPermissions,
1900 ACCESS_MODE AccessMode, DWORD Inheritance )
1902 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_a(pTrusteeName),
1903 AccessPermissions, AccessMode, Inheritance);
1905 pExplicitAccess->grfAccessPermissions = AccessPermissions;
1906 pExplicitAccess->grfAccessMode = AccessMode;
1907 pExplicitAccess->grfInheritance = Inheritance;
1909 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1910 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1911 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1912 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1913 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1916 /******************************************************************************
1917 * BuildExplicitAccessWithNameW [ADVAPI32.@]
1919 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
1920 LPWSTR pTrusteeName, DWORD AccessPermissions,
1921 ACCESS_MODE AccessMode, DWORD Inheritance )
1923 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_w(pTrusteeName),
1924 AccessPermissions, AccessMode, Inheritance);
1926 pExplicitAccess->grfAccessPermissions = AccessPermissions;
1927 pExplicitAccess->grfAccessMode = AccessMode;
1928 pExplicitAccess->grfInheritance = Inheritance;
1930 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1931 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1932 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1933 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1934 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1937 /******************************************************************************
1938 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
1940 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
1941 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
1942 LPSTR InheritedObjectTypeName, LPSTR Name )
1944 DWORD ObjectsPresent = 0;
1946 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1947 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
1949 /* Fill the OBJECTS_AND_NAME structure */
1950 pObjName->ObjectType = ObjectType;
1951 if (ObjectTypeName != NULL)
1953 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1956 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1957 if (InheritedObjectTypeName != NULL)
1959 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1962 pObjName->ObjectsPresent = ObjectsPresent;
1963 pObjName->ptstrName = Name;
1965 /* Fill the TRUSTEE structure */
1966 pTrustee->pMultipleTrustee = NULL;
1967 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1968 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
1969 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1970 pTrustee->ptstrName = (LPSTR)pObjName;
1973 /******************************************************************************
1974 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
1976 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
1977 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
1978 LPWSTR InheritedObjectTypeName, LPWSTR Name )
1980 DWORD ObjectsPresent = 0;
1982 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1983 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
1985 /* Fill the OBJECTS_AND_NAME structure */
1986 pObjName->ObjectType = ObjectType;
1987 if (ObjectTypeName != NULL)
1989 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1992 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1993 if (InheritedObjectTypeName != NULL)
1995 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1998 pObjName->ObjectsPresent = ObjectsPresent;
1999 pObjName->ptstrName = Name;
2001 /* Fill the TRUSTEE structure */
2002 pTrustee->pMultipleTrustee = NULL;
2003 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2004 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
2005 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2006 pTrustee->ptstrName = (LPWSTR)pObjName;
2009 /******************************************************************************
2010 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
2012 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
2013 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
2015 DWORD ObjectsPresent = 0;
2017 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
2019 /* Fill the OBJECTS_AND_SID structure */
2020 if (pObjectGuid != NULL)
2022 pObjSid->ObjectTypeGuid = *pObjectGuid;
2023 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
2025 else
2027 ZeroMemory(&pObjSid->ObjectTypeGuid,
2028 sizeof(GUID));
2031 if (pInheritedObjectGuid != NULL)
2033 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
2034 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
2036 else
2038 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
2039 sizeof(GUID));
2042 pObjSid->ObjectsPresent = ObjectsPresent;
2043 pObjSid->pSid = pSid;
2045 /* Fill the TRUSTEE structure */
2046 pTrustee->pMultipleTrustee = NULL;
2047 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2048 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
2049 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2050 pTrustee->ptstrName = (LPSTR) pObjSid;
2053 /******************************************************************************
2054 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
2056 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
2057 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
2059 DWORD ObjectsPresent = 0;
2061 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
2063 /* Fill the OBJECTS_AND_SID structure */
2064 if (pObjectGuid != NULL)
2066 pObjSid->ObjectTypeGuid = *pObjectGuid;
2067 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
2069 else
2071 ZeroMemory(&pObjSid->ObjectTypeGuid,
2072 sizeof(GUID));
2075 if (pInheritedObjectGuid != NULL)
2077 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
2078 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
2080 else
2082 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
2083 sizeof(GUID));
2086 pObjSid->ObjectsPresent = ObjectsPresent;
2087 pObjSid->pSid = pSid;
2089 /* Fill the TRUSTEE structure */
2090 pTrustee->pMultipleTrustee = NULL;
2091 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2092 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
2093 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2094 pTrustee->ptstrName = (LPWSTR) pObjSid;
2097 /******************************************************************************
2098 * BuildTrusteeWithSidA [ADVAPI32.@]
2100 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid)
2102 TRACE("%p %p\n", pTrustee, pSid);
2104 pTrustee->pMultipleTrustee = NULL;
2105 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2106 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
2107 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2108 pTrustee->ptstrName = pSid;
2111 /******************************************************************************
2112 * BuildTrusteeWithSidW [ADVAPI32.@]
2114 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
2116 TRACE("%p %p\n", pTrustee, pSid);
2118 pTrustee->pMultipleTrustee = NULL;
2119 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2120 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
2121 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2122 pTrustee->ptstrName = pSid;
2125 /******************************************************************************
2126 * BuildTrusteeWithNameA [ADVAPI32.@]
2128 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
2130 TRACE("%p %s\n", pTrustee, debugstr_a(name) );
2132 pTrustee->pMultipleTrustee = NULL;
2133 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2134 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
2135 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2136 pTrustee->ptstrName = name;
2139 /******************************************************************************
2140 * BuildTrusteeWithNameW [ADVAPI32.@]
2142 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
2144 TRACE("%p %s\n", pTrustee, debugstr_w(name) );
2146 pTrustee->pMultipleTrustee = NULL;
2147 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2148 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
2149 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2150 pTrustee->ptstrName = name;
2153 /******************************************************************************
2154 * GetTrusteeFormA [ADVAPI32.@]
2156 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee)
2158 TRACE("(%p)\n", pTrustee);
2160 if (!pTrustee)
2161 return TRUSTEE_BAD_FORM;
2163 return pTrustee->TrusteeForm;
2166 /******************************************************************************
2167 * GetTrusteeFormW [ADVAPI32.@]
2169 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee)
2171 TRACE("(%p)\n", pTrustee);
2173 if (!pTrustee)
2174 return TRUSTEE_BAD_FORM;
2176 return pTrustee->TrusteeForm;
2179 /******************************************************************************
2180 * GetTrusteeNameA [ADVAPI32.@]
2182 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee)
2184 TRACE("(%p)\n", pTrustee);
2186 if (!pTrustee)
2187 return NULL;
2189 return pTrustee->ptstrName;
2192 /******************************************************************************
2193 * GetTrusteeNameW [ADVAPI32.@]
2195 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee)
2197 TRACE("(%p)\n", pTrustee);
2199 if (!pTrustee)
2200 return NULL;
2202 return pTrustee->ptstrName;
2205 /******************************************************************************
2206 * GetTrusteeTypeA [ADVAPI32.@]
2208 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee)
2210 TRACE("(%p)\n", pTrustee);
2212 if (!pTrustee)
2213 return TRUSTEE_IS_UNKNOWN;
2215 return pTrustee->TrusteeType;
2218 /******************************************************************************
2219 * GetTrusteeTypeW [ADVAPI32.@]
2221 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee)
2223 TRACE("(%p)\n", pTrustee);
2225 if (!pTrustee)
2226 return TRUSTEE_IS_UNKNOWN;
2228 return pTrustee->TrusteeType;
2231 static DWORD trustee_name_A_to_W(TRUSTEE_FORM form, char *trustee_nameA, WCHAR **ptrustee_nameW)
2233 switch (form)
2235 case TRUSTEE_IS_NAME:
2237 *ptrustee_nameW = SERV_dup(trustee_nameA);
2238 return ERROR_SUCCESS;
2240 case TRUSTEE_IS_OBJECTS_AND_NAME:
2242 OBJECTS_AND_NAME_A *objA = (OBJECTS_AND_NAME_A *)trustee_nameA;
2243 OBJECTS_AND_NAME_W *objW = NULL;
2245 if (objA)
2247 if (!(objW = heap_alloc( sizeof(OBJECTS_AND_NAME_W) )))
2248 return ERROR_NOT_ENOUGH_MEMORY;
2250 objW->ObjectsPresent = objA->ObjectsPresent;
2251 objW->ObjectType = objA->ObjectType;
2252 objW->ObjectTypeName = SERV_dup(objA->ObjectTypeName);
2253 objW->InheritedObjectTypeName = SERV_dup(objA->InheritedObjectTypeName);
2254 objW->ptstrName = SERV_dup(objA->ptstrName);
2257 *ptrustee_nameW = (WCHAR *)objW;
2258 return ERROR_SUCCESS;
2260 /* These forms do not require conversion. */
2261 case TRUSTEE_IS_SID:
2262 case TRUSTEE_IS_OBJECTS_AND_SID:
2263 *ptrustee_nameW = (WCHAR *)trustee_nameA;
2264 return ERROR_SUCCESS;
2265 default:
2266 return ERROR_INVALID_PARAMETER;
2270 static void free_trustee_name(TRUSTEE_FORM form, WCHAR *trustee_nameW)
2272 switch (form)
2274 case TRUSTEE_IS_NAME:
2275 heap_free( trustee_nameW );
2276 break;
2277 case TRUSTEE_IS_OBJECTS_AND_NAME:
2279 OBJECTS_AND_NAME_W *objW = (OBJECTS_AND_NAME_W *)trustee_nameW;
2281 if (objW)
2283 heap_free( objW->ptstrName );
2284 heap_free( objW->InheritedObjectTypeName );
2285 heap_free( objW->ObjectTypeName );
2286 heap_free( objW );
2289 break;
2291 /* Other forms did not require allocation, so no freeing is necessary. */
2292 default:
2293 break;
2297 static DWORD trustee_to_sid( DWORD nDestinationSidLength, PSID pDestinationSid, PTRUSTEEW pTrustee )
2299 if (pTrustee->MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
2301 WARN("bad multiple trustee operation %d\n", pTrustee->MultipleTrusteeOperation);
2302 return ERROR_INVALID_PARAMETER;
2305 switch (pTrustee->TrusteeForm)
2307 case TRUSTEE_IS_SID:
2308 if (!CopySid(nDestinationSidLength, pDestinationSid, pTrustee->ptstrName))
2310 WARN("bad sid %p\n", pTrustee->ptstrName);
2311 return ERROR_INVALID_PARAMETER;
2313 break;
2314 case TRUSTEE_IS_NAME:
2316 DWORD sid_size = nDestinationSidLength;
2317 DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
2318 SID_NAME_USE use;
2319 if (!strcmpW( pTrustee->ptstrName, CURRENT_USER ))
2321 if (!lookup_user_account_name( pDestinationSid, &sid_size, NULL, &domain_size, &use ))
2323 return GetLastError();
2326 else if (!LookupAccountNameW(NULL, pTrustee->ptstrName, pDestinationSid, &sid_size, NULL, &domain_size, &use))
2328 WARN("bad user name %s\n", debugstr_w(pTrustee->ptstrName));
2329 return ERROR_INVALID_PARAMETER;
2331 break;
2333 case TRUSTEE_IS_OBJECTS_AND_SID:
2334 FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
2335 break;
2336 case TRUSTEE_IS_OBJECTS_AND_NAME:
2337 FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
2338 break;
2339 default:
2340 WARN("bad trustee form %d\n", pTrustee->TrusteeForm);
2341 return ERROR_INVALID_PARAMETER;
2344 return ERROR_SUCCESS;
2347 /******************************************************************************
2348 * SetEntriesInAclA [ADVAPI32.@]
2350 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
2351 PACL OldAcl, PACL* NewAcl )
2353 DWORD err = ERROR_SUCCESS;
2354 EXPLICIT_ACCESSW *pEntriesW;
2355 UINT alloc_index, free_index;
2357 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
2359 if (NewAcl)
2360 *NewAcl = NULL;
2362 if (!count && !OldAcl)
2363 return ERROR_SUCCESS;
2365 pEntriesW = heap_alloc( count * sizeof(EXPLICIT_ACCESSW) );
2366 if (!pEntriesW)
2367 return ERROR_NOT_ENOUGH_MEMORY;
2369 for (alloc_index = 0; alloc_index < count; ++alloc_index)
2371 pEntriesW[alloc_index].grfAccessPermissions = pEntries[alloc_index].grfAccessPermissions;
2372 pEntriesW[alloc_index].grfAccessMode = pEntries[alloc_index].grfAccessMode;
2373 pEntriesW[alloc_index].grfInheritance = pEntries[alloc_index].grfInheritance;
2374 pEntriesW[alloc_index].Trustee.pMultipleTrustee = NULL; /* currently not supported */
2375 pEntriesW[alloc_index].Trustee.MultipleTrusteeOperation = pEntries[alloc_index].Trustee.MultipleTrusteeOperation;
2376 pEntriesW[alloc_index].Trustee.TrusteeForm = pEntries[alloc_index].Trustee.TrusteeForm;
2377 pEntriesW[alloc_index].Trustee.TrusteeType = pEntries[alloc_index].Trustee.TrusteeType;
2379 err = trustee_name_A_to_W( pEntries[alloc_index].Trustee.TrusteeForm,
2380 pEntries[alloc_index].Trustee.ptstrName,
2381 &pEntriesW[alloc_index].Trustee.ptstrName );
2382 if (err != ERROR_SUCCESS)
2384 if (err == ERROR_INVALID_PARAMETER)
2385 WARN("bad trustee form %d for trustee %d\n",
2386 pEntries[alloc_index].Trustee.TrusteeForm, alloc_index);
2388 goto cleanup;
2392 err = SetEntriesInAclW( count, pEntriesW, OldAcl, NewAcl );
2394 cleanup:
2395 /* Free any previously allocated trustee name buffers, taking into account
2396 * a possible out-of-memory condition while building the EXPLICIT_ACCESSW
2397 * list. */
2398 for (free_index = 0; free_index < alloc_index; ++free_index)
2399 free_trustee_name( pEntriesW[free_index].Trustee.TrusteeForm, pEntriesW[free_index].Trustee.ptstrName );
2401 heap_free( pEntriesW );
2402 return err;
2405 /******************************************************************************
2406 * SetEntriesInAclW [ADVAPI32.@]
2408 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
2409 PACL OldAcl, PACL* NewAcl )
2411 ULONG i;
2412 PSID *ppsid;
2413 DWORD ret = ERROR_SUCCESS;
2414 DWORD acl_size = sizeof(ACL);
2415 NTSTATUS status;
2417 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
2419 if (NewAcl)
2420 *NewAcl = NULL;
2422 if (!count && !OldAcl)
2423 return ERROR_SUCCESS;
2425 /* allocate array of maximum sized sids allowed */
2426 ppsid = heap_alloc(count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
2427 if (!ppsid)
2428 return ERROR_OUTOFMEMORY;
2430 for (i = 0; i < count; i++)
2432 ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
2434 TRACE("[%d]:\n\tgrfAccessPermissions = 0x%x\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%x\n\t"
2435 "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
2436 "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
2437 pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
2438 pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
2439 pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
2440 pEntries[i].Trustee.ptstrName);
2442 ret = trustee_to_sid( FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]), ppsid[i], &pEntries[i].Trustee);
2443 if (ret)
2444 goto exit;
2446 /* Note: we overestimate the ACL size here as a tradeoff between
2447 * instructions (simplicity) and memory */
2448 switch (pEntries[i].grfAccessMode)
2450 case GRANT_ACCESS:
2451 case SET_ACCESS:
2452 acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
2453 break;
2454 case DENY_ACCESS:
2455 acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
2456 break;
2457 case SET_AUDIT_SUCCESS:
2458 case SET_AUDIT_FAILURE:
2459 acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
2460 break;
2461 case REVOKE_ACCESS:
2462 break;
2463 default:
2464 WARN("bad access mode %d for trustee %d\n", pEntries[i].grfAccessMode, i);
2465 ret = ERROR_INVALID_PARAMETER;
2466 goto exit;
2470 if (OldAcl)
2472 ACL_SIZE_INFORMATION size_info;
2474 status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
2475 if (status != STATUS_SUCCESS)
2477 ret = RtlNtStatusToDosError(status);
2478 goto exit;
2480 acl_size += size_info.AclBytesInUse - sizeof(ACL);
2483 *NewAcl = LocalAlloc(0, acl_size);
2484 if (!*NewAcl)
2486 ret = ERROR_OUTOFMEMORY;
2487 goto exit;
2490 status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
2491 if (status != STATUS_SUCCESS)
2493 ret = RtlNtStatusToDosError(status);
2494 goto exit;
2497 for (i = 0; i < count; i++)
2499 switch (pEntries[i].grfAccessMode)
2501 case GRANT_ACCESS:
2502 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
2503 pEntries[i].grfInheritance,
2504 pEntries[i].grfAccessPermissions,
2505 ppsid[i]);
2506 break;
2507 case SET_ACCESS:
2509 ULONG j;
2510 BOOL add = TRUE;
2511 if (OldAcl)
2513 for (j = 0; ; j++)
2515 const ACE_HEADER *existing_ace_header;
2516 status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
2517 if (status != STATUS_SUCCESS)
2518 break;
2519 if (pEntries[i].grfAccessMode == SET_ACCESS &&
2520 existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
2521 EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
2523 add = FALSE;
2524 break;
2528 if (add)
2529 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
2530 pEntries[i].grfInheritance,
2531 pEntries[i].grfAccessPermissions,
2532 ppsid[i]);
2533 break;
2535 case DENY_ACCESS:
2536 status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
2537 pEntries[i].grfInheritance,
2538 pEntries[i].grfAccessPermissions,
2539 ppsid[i]);
2540 break;
2541 case SET_AUDIT_SUCCESS:
2542 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
2543 pEntries[i].grfInheritance,
2544 pEntries[i].grfAccessPermissions,
2545 ppsid[i], TRUE, FALSE);
2546 break;
2547 case SET_AUDIT_FAILURE:
2548 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
2549 pEntries[i].grfInheritance,
2550 pEntries[i].grfAccessPermissions,
2551 ppsid[i], FALSE, TRUE);
2552 break;
2553 default:
2554 FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
2558 if (OldAcl)
2560 for (i = 0; ; i++)
2562 BOOL add = TRUE;
2563 ULONG j;
2564 const ACE_HEADER *old_ace_header;
2565 status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
2566 if (status != STATUS_SUCCESS) break;
2567 for (j = 0; j < count; j++)
2569 if (pEntries[j].grfAccessMode == SET_ACCESS &&
2570 old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
2571 EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
2573 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
2574 add = FALSE;
2575 break;
2577 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
2579 switch (old_ace_header->AceType)
2581 case ACCESS_ALLOWED_ACE_TYPE:
2582 if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
2583 add = FALSE;
2584 break;
2585 case ACCESS_DENIED_ACE_TYPE:
2586 if (EqualSid(ppsid[j], &((ACCESS_DENIED_ACE *)old_ace_header)->SidStart))
2587 add = FALSE;
2588 break;
2589 case SYSTEM_AUDIT_ACE_TYPE:
2590 if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
2591 add = FALSE;
2592 break;
2593 case SYSTEM_ALARM_ACE_TYPE:
2594 if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
2595 add = FALSE;
2596 break;
2597 default:
2598 FIXME("unhandled ace type %d\n", old_ace_header->AceType);
2601 if (!add)
2602 break;
2605 if (add)
2606 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
2607 if (status != STATUS_SUCCESS)
2609 WARN("RtlAddAce failed with error 0x%08x\n", status);
2610 ret = RtlNtStatusToDosError(status);
2611 break;
2616 exit:
2617 heap_free(ppsid);
2618 return ret;
2621 /******************************************************************************
2622 * SetNamedSecurityInfoA [ADVAPI32.@]
2624 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
2625 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
2626 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
2628 LPWSTR wstr;
2629 DWORD r;
2631 TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
2632 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
2634 wstr = SERV_dup(pObjectName);
2635 r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
2636 psidGroup, pDacl, pSacl );
2638 heap_free( wstr );
2640 return r;
2643 /******************************************************************************
2644 * SetNamedSecurityInfoW [ADVAPI32.@]
2646 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
2647 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
2648 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
2650 DWORD access = 0;
2651 HANDLE handle;
2652 DWORD err;
2654 TRACE( "%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
2655 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
2657 if (!pObjectName) return ERROR_INVALID_PARAMETER;
2659 if (SecurityInfo & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION))
2660 access |= WRITE_OWNER;
2661 if (SecurityInfo & DACL_SECURITY_INFORMATION)
2662 access |= WRITE_DAC;
2663 if (SecurityInfo & SACL_SECURITY_INFORMATION)
2664 access |= ACCESS_SYSTEM_SECURITY;
2666 switch (ObjectType)
2668 case SE_SERVICE:
2669 if (!(err = get_security_service( pObjectName, access, &handle )))
2671 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
2672 CloseServiceHandle( handle );
2674 break;
2675 case SE_REGISTRY_KEY:
2676 if (!(err = get_security_regkey( pObjectName, access, &handle )))
2678 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
2679 RegCloseKey( handle );
2681 break;
2682 case SE_FILE_OBJECT:
2683 if (SecurityInfo & DACL_SECURITY_INFORMATION)
2684 access |= READ_CONTROL;
2685 if (!(err = get_security_file( pObjectName, access, &handle )))
2687 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
2688 CloseHandle( handle );
2690 break;
2691 default:
2692 FIXME( "Object type %d is not currently supported.\n", ObjectType );
2693 return ERROR_SUCCESS;
2695 return err;
2698 /******************************************************************************
2699 * GetExplicitEntriesFromAclA [ADVAPI32.@]
2701 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
2702 PEXPLICIT_ACCESSA* pListOfExplicitEntries)
2704 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
2705 return ERROR_CALL_NOT_IMPLEMENTED;
2708 /******************************************************************************
2709 * GetExplicitEntriesFromAclW [ADVAPI32.@]
2711 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG count, PEXPLICIT_ACCESSW *list )
2713 ACL_SIZE_INFORMATION sizeinfo;
2714 EXPLICIT_ACCESSW *entries;
2715 MAX_SID *sid_entries;
2716 ACE_HEADER *ace;
2717 NTSTATUS status;
2718 int i;
2720 TRACE("%p %p %p\n",pacl, count, list);
2722 if (!count || !list)
2723 return ERROR_INVALID_PARAMETER;
2725 status = RtlQueryInformationAcl(pacl, &sizeinfo, sizeof(sizeinfo), AclSizeInformation);
2726 if (status) return RtlNtStatusToDosError(status);
2728 if (!sizeinfo.AceCount)
2730 *count = 0;
2731 *list = NULL;
2732 return ERROR_SUCCESS;
2735 entries = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, (sizeof(EXPLICIT_ACCESSW) + sizeof(MAX_SID)) * sizeinfo.AceCount);
2736 if (!entries) return ERROR_OUTOFMEMORY;
2737 sid_entries = (MAX_SID *)(entries + sizeinfo.AceCount);
2739 for (i = 0; i < sizeinfo.AceCount; i++)
2741 status = RtlGetAce(pacl, i, (void**)&ace);
2742 if (status) goto error;
2744 switch (ace->AceType)
2746 case ACCESS_ALLOWED_ACE_TYPE:
2748 ACCESS_ALLOWED_ACE *allow = (ACCESS_ALLOWED_ACE *)ace;
2749 entries[i].grfAccessMode = GRANT_ACCESS;
2750 entries[i].grfInheritance = ace->AceFlags;
2751 entries[i].grfAccessPermissions = allow->Mask;
2753 CopySid(sizeof(MAX_SID), (PSID)&sid_entries[i], (PSID)&allow->SidStart);
2754 entries[i].Trustee.pMultipleTrustee = NULL;
2755 entries[i].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2756 entries[i].Trustee.TrusteeForm = TRUSTEE_IS_SID;
2757 entries[i].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
2758 entries[i].Trustee.ptstrName = (WCHAR *)&sid_entries[i];
2759 break;
2762 case ACCESS_DENIED_ACE_TYPE:
2764 ACCESS_DENIED_ACE *deny = (ACCESS_DENIED_ACE *)ace;
2765 entries[i].grfAccessMode = DENY_ACCESS;
2766 entries[i].grfInheritance = ace->AceFlags;
2767 entries[i].grfAccessPermissions = deny->Mask;
2769 CopySid(sizeof(MAX_SID), (PSID)&sid_entries[i], (PSID)&deny->SidStart);
2770 entries[i].Trustee.pMultipleTrustee = NULL;
2771 entries[i].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2772 entries[i].Trustee.TrusteeForm = TRUSTEE_IS_SID;
2773 entries[i].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
2774 entries[i].Trustee.ptstrName = (WCHAR *)&sid_entries[i];
2775 break;
2778 default:
2779 FIXME("Unhandled ace type %d\n", ace->AceType);
2780 entries[i].grfAccessMode = NOT_USED_ACCESS;
2781 continue;
2785 *count = sizeinfo.AceCount;
2786 *list = entries;
2787 return ERROR_SUCCESS;
2789 error:
2790 LocalFree(entries);
2791 return RtlNtStatusToDosError(status);
2794 /******************************************************************************
2795 * GetAuditedPermissionsFromAclA [ADVAPI32.@]
2797 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
2798 PACCESS_MASK pFailedAuditRights)
2800 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
2801 return ERROR_CALL_NOT_IMPLEMENTED;
2805 /******************************************************************************
2806 * GetAuditedPermissionsFromAclW [ADVAPI32.@]
2808 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
2809 PACCESS_MASK pFailedAuditRights)
2811 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
2812 return ERROR_CALL_NOT_IMPLEMENTED;
2816 /******************************************************************************
2817 * ParseAclStringFlags
2819 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
2821 DWORD flags = 0;
2822 LPCWSTR szAcl = *StringAcl;
2824 while (*szAcl && *szAcl != '(')
2826 if (*szAcl == 'P')
2828 flags |= SE_DACL_PROTECTED;
2830 else if (*szAcl == 'A')
2832 szAcl++;
2833 if (*szAcl == 'R')
2834 flags |= SE_DACL_AUTO_INHERIT_REQ;
2835 else if (*szAcl == 'I')
2836 flags |= SE_DACL_AUTO_INHERITED;
2838 szAcl++;
2841 *StringAcl = szAcl;
2842 return flags;
2845 /******************************************************************************
2846 * ParseAceStringType
2848 static const ACEFLAG AceType[] =
2850 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
2851 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
2852 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
2853 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
2854 { SDDL_MANDATORY_LABEL,SYSTEM_MANDATORY_LABEL_ACE_TYPE },
2856 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
2857 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
2858 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
2859 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
2861 { NULL, 0 },
2864 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
2866 UINT len = 0;
2867 LPCWSTR szAcl = *StringAcl;
2868 const ACEFLAG *lpaf = AceType;
2870 while (*szAcl == ' ')
2871 szAcl++;
2873 while (lpaf->wstr &&
2874 (len = strlenW(lpaf->wstr)) &&
2875 strncmpW(lpaf->wstr, szAcl, len))
2876 lpaf++;
2878 if (!lpaf->wstr)
2879 return 0;
2881 *StringAcl = szAcl + len;
2882 return lpaf->value;
2886 /******************************************************************************
2887 * ParseAceStringFlags
2889 static const ACEFLAG AceFlags[] =
2891 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
2892 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
2893 { SDDL_INHERITED, INHERITED_ACE },
2894 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
2895 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
2896 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
2897 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
2898 { NULL, 0 },
2901 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
2903 UINT len = 0;
2904 BYTE flags = 0;
2905 LPCWSTR szAcl = *StringAcl;
2907 while (*szAcl == ' ')
2908 szAcl++;
2910 while (*szAcl != ';')
2912 const ACEFLAG *lpaf = AceFlags;
2914 while (lpaf->wstr &&
2915 (len = strlenW(lpaf->wstr)) &&
2916 strncmpW(lpaf->wstr, szAcl, len))
2917 lpaf++;
2919 if (!lpaf->wstr)
2920 return 0;
2922 flags |= lpaf->value;
2923 szAcl += len;
2926 *StringAcl = szAcl;
2927 return flags;
2931 /******************************************************************************
2932 * ParseAceStringRights
2934 static const ACEFLAG AceRights[] =
2936 { SDDL_GENERIC_ALL, GENERIC_ALL },
2937 { SDDL_GENERIC_READ, GENERIC_READ },
2938 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
2939 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
2941 { SDDL_READ_CONTROL, READ_CONTROL },
2942 { SDDL_STANDARD_DELETE, DELETE },
2943 { SDDL_WRITE_DAC, WRITE_DAC },
2944 { SDDL_WRITE_OWNER, WRITE_OWNER },
2946 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
2947 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
2948 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
2949 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
2950 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
2951 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
2952 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
2953 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
2954 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
2956 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
2957 { SDDL_FILE_READ, FILE_GENERIC_READ },
2958 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
2959 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
2961 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
2962 { SDDL_KEY_READ, KEY_READ },
2963 { SDDL_KEY_WRITE, KEY_WRITE },
2964 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
2966 { SDDL_NO_READ_UP, SYSTEM_MANDATORY_LABEL_NO_READ_UP },
2967 { SDDL_NO_WRITE_UP, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP },
2968 { SDDL_NO_EXECUTE_UP, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP },
2969 { NULL, 0 },
2972 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
2974 UINT len = 0;
2975 DWORD rights = 0;
2976 LPCWSTR szAcl = *StringAcl;
2978 while (*szAcl == ' ')
2979 szAcl++;
2981 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
2983 LPCWSTR p = szAcl;
2985 while (*p && *p != ';')
2986 p++;
2988 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
2990 rights = strtoulW(szAcl, NULL, 16);
2991 szAcl = p;
2993 else
2994 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
2996 else
2998 while (*szAcl != ';')
3000 const ACEFLAG *lpaf = AceRights;
3002 while (lpaf->wstr &&
3003 (len = strlenW(lpaf->wstr)) &&
3004 strncmpW(lpaf->wstr, szAcl, len))
3006 lpaf++;
3009 if (!lpaf->wstr)
3010 return 0;
3012 rights |= lpaf->value;
3013 szAcl += len;
3017 *StringAcl = szAcl;
3018 return rights;
3022 /******************************************************************************
3023 * ParseStringAclToAcl
3025 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
3027 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
3028 PACL pAcl, LPDWORD cBytes)
3030 DWORD val;
3031 DWORD sidlen;
3032 DWORD length = sizeof(ACL);
3033 DWORD acesize = 0;
3034 DWORD acecount = 0;
3035 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
3036 DWORD error = ERROR_INVALID_ACL;
3038 TRACE("%s\n", debugstr_w(StringAcl));
3040 if (!StringAcl)
3041 return FALSE;
3043 if (pAcl) /* pAce is only useful if we're setting values */
3044 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
3046 /* Parse ACL flags */
3047 *lpdwFlags = ParseAclStringFlags(&StringAcl);
3049 /* Parse ACE */
3050 while (*StringAcl == '(')
3052 StringAcl++;
3054 /* Parse ACE type */
3055 val = ParseAceStringType(&StringAcl);
3056 if (pAce)
3057 pAce->Header.AceType = (BYTE) val;
3058 if (*StringAcl != ';')
3060 error = RPC_S_INVALID_STRING_UUID;
3061 goto lerr;
3063 StringAcl++;
3065 /* Parse ACE flags */
3066 val = ParseAceStringFlags(&StringAcl);
3067 if (pAce)
3068 pAce->Header.AceFlags = (BYTE) val;
3069 if (*StringAcl != ';')
3070 goto lerr;
3071 StringAcl++;
3073 /* Parse ACE rights */
3074 val = ParseAceStringRights(&StringAcl);
3075 if (pAce)
3076 pAce->Mask = val;
3077 if (*StringAcl != ';')
3078 goto lerr;
3079 StringAcl++;
3081 /* Parse ACE object guid */
3082 while (*StringAcl == ' ')
3083 StringAcl++;
3084 if (*StringAcl != ';')
3086 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
3087 goto lerr;
3089 StringAcl++;
3091 /* Parse ACE inherit object guid */
3092 while (*StringAcl == ' ')
3093 StringAcl++;
3094 if (*StringAcl != ';')
3096 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
3097 goto lerr;
3099 StringAcl++;
3101 /* Parse ACE account sid */
3102 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
3104 while (*StringAcl && *StringAcl != ')')
3105 StringAcl++;
3108 if (*StringAcl != ')')
3109 goto lerr;
3110 StringAcl++;
3112 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
3113 length += acesize;
3114 if (pAce)
3116 pAce->Header.AceSize = acesize;
3117 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
3119 acecount++;
3122 *cBytes = length;
3124 if (length > 0xffff)
3126 ERR("ACL too large\n");
3127 goto lerr;
3130 if (pAcl)
3132 pAcl->AclRevision = ACL_REVISION;
3133 pAcl->Sbz1 = 0;
3134 pAcl->AclSize = length;
3135 pAcl->AceCount = acecount;
3136 pAcl->Sbz2 = 0;
3138 return TRUE;
3140 lerr:
3141 SetLastError(error);
3142 WARN("Invalid ACE string format\n");
3143 return FALSE;
3147 /******************************************************************************
3148 * ParseStringSecurityDescriptorToSecurityDescriptor
3150 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
3151 LPCWSTR StringSecurityDescriptor,
3152 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
3153 LPDWORD cBytes)
3155 BOOL bret = FALSE;
3156 WCHAR toktype;
3157 WCHAR *tok;
3158 LPCWSTR lptoken;
3159 LPBYTE lpNext = NULL;
3160 DWORD len;
3162 *cBytes = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
3164 tok = heap_alloc( (lstrlenW(StringSecurityDescriptor) + 1) * sizeof(WCHAR));
3166 if (SecurityDescriptor)
3167 lpNext = (LPBYTE)(SecurityDescriptor + 1);
3169 while (*StringSecurityDescriptor == ' ')
3170 StringSecurityDescriptor++;
3172 while (*StringSecurityDescriptor)
3174 toktype = *StringSecurityDescriptor;
3176 /* Expect char identifier followed by ':' */
3177 StringSecurityDescriptor++;
3178 if (*StringSecurityDescriptor != ':')
3180 SetLastError(ERROR_INVALID_PARAMETER);
3181 goto lend;
3183 StringSecurityDescriptor++;
3185 /* Extract token */
3186 lptoken = StringSecurityDescriptor;
3187 while (*lptoken && *lptoken != ':')
3188 lptoken++;
3190 if (*lptoken)
3191 lptoken--;
3193 len = lptoken - StringSecurityDescriptor;
3194 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
3195 tok[len] = 0;
3197 switch (toktype)
3199 case 'O':
3201 DWORD bytes;
3203 if (!ParseStringSidToSid(tok, lpNext, &bytes))
3204 goto lend;
3206 if (SecurityDescriptor)
3208 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
3209 lpNext += bytes; /* Advance to next token */
3212 *cBytes += bytes;
3214 break;
3217 case 'G':
3219 DWORD bytes;
3221 if (!ParseStringSidToSid(tok, lpNext, &bytes))
3222 goto lend;
3224 if (SecurityDescriptor)
3226 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
3227 lpNext += bytes; /* Advance to next token */
3230 *cBytes += bytes;
3232 break;
3235 case 'D':
3237 DWORD flags;
3238 DWORD bytes;
3240 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
3241 goto lend;
3243 if (SecurityDescriptor)
3245 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
3246 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
3247 lpNext += bytes; /* Advance to next token */
3250 *cBytes += bytes;
3252 break;
3255 case 'S':
3257 DWORD flags;
3258 DWORD bytes;
3260 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
3261 goto lend;
3263 if (SecurityDescriptor)
3265 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
3266 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
3267 lpNext += bytes; /* Advance to next token */
3270 *cBytes += bytes;
3272 break;
3275 default:
3276 FIXME("Unknown token\n");
3277 SetLastError(ERROR_INVALID_PARAMETER);
3278 goto lend;
3281 StringSecurityDescriptor = lptoken;
3284 bret = TRUE;
3286 lend:
3287 heap_free(tok);
3288 return bret;
3291 /******************************************************************************
3292 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
3294 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
3295 LPCSTR StringSecurityDescriptor,
3296 DWORD StringSDRevision,
3297 PSECURITY_DESCRIPTOR* SecurityDescriptor,
3298 PULONG SecurityDescriptorSize)
3300 BOOL ret;
3301 LPWSTR StringSecurityDescriptorW;
3303 TRACE("%s, %u, %p, %p\n", debugstr_a(StringSecurityDescriptor), StringSDRevision,
3304 SecurityDescriptor, SecurityDescriptorSize);
3306 if(!StringSecurityDescriptor)
3307 return FALSE;
3309 StringSecurityDescriptorW = SERV_dup(StringSecurityDescriptor);
3310 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
3311 StringSDRevision, SecurityDescriptor,
3312 SecurityDescriptorSize);
3313 heap_free(StringSecurityDescriptorW);
3315 return ret;
3318 /******************************************************************************
3319 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
3321 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
3322 LPCWSTR StringSecurityDescriptor,
3323 DWORD StringSDRevision,
3324 PSECURITY_DESCRIPTOR* SecurityDescriptor,
3325 PULONG SecurityDescriptorSize)
3327 DWORD cBytes;
3328 SECURITY_DESCRIPTOR* psd;
3329 BOOL bret = FALSE;
3331 TRACE("%s, %u, %p, %p\n", debugstr_w(StringSecurityDescriptor), StringSDRevision,
3332 SecurityDescriptor, SecurityDescriptorSize);
3334 if (GetVersion() & 0x80000000)
3336 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3337 goto lend;
3339 else if (!StringSecurityDescriptor || !SecurityDescriptor)
3341 SetLastError(ERROR_INVALID_PARAMETER);
3342 goto lend;
3344 else if (StringSDRevision != SID_REVISION)
3346 SetLastError(ERROR_UNKNOWN_REVISION);
3347 goto lend;
3350 /* Compute security descriptor length */
3351 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
3352 NULL, &cBytes))
3353 goto lend;
3355 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
3356 if (!psd) goto lend;
3358 psd->Revision = SID_REVISION;
3359 psd->Control |= SE_SELF_RELATIVE;
3361 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
3362 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
3364 LocalFree(psd);
3365 goto lend;
3368 if (SecurityDescriptorSize)
3369 *SecurityDescriptorSize = cBytes;
3371 bret = TRUE;
3373 lend:
3374 TRACE(" ret=%d\n", bret);
3375 return bret;
3378 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
3380 if (cch == -1)
3381 cch = strlenW(string);
3383 if (plen)
3384 *plen += cch;
3386 if (pwptr)
3388 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
3389 *pwptr += cch;
3393 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
3395 static const WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
3396 static const WCHAR subauthfmt[] = { '-','%','u',0 };
3397 DWORD i;
3398 WCHAR buf[26];
3399 SID *pisid = psid;
3401 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
3403 SetLastError(ERROR_INVALID_SID);
3404 return FALSE;
3407 if (pisid->IdentifierAuthority.Value[0] ||
3408 pisid->IdentifierAuthority.Value[1])
3410 FIXME("not matching MS' bugs\n");
3411 SetLastError(ERROR_INVALID_SID);
3412 return FALSE;
3415 sprintfW( buf, fmt, pisid->Revision,
3416 MAKELONG(
3417 MAKEWORD( pisid->IdentifierAuthority.Value[5],
3418 pisid->IdentifierAuthority.Value[4] ),
3419 MAKEWORD( pisid->IdentifierAuthority.Value[3],
3420 pisid->IdentifierAuthority.Value[2] )
3421 ) );
3422 DumpString(buf, -1, pwptr, plen);
3424 for( i=0; i<pisid->SubAuthorityCount; i++ )
3426 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
3427 DumpString(buf, -1, pwptr, plen);
3429 return TRUE;
3432 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
3434 size_t i;
3435 for (i = 0; i < ARRAY_SIZE(WellKnownSids); i++)
3437 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
3439 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
3440 return TRUE;
3444 return DumpSidNumeric(psid, pwptr, plen);
3447 static const LPCWSTR AceRightBitNames[32] = {
3448 SDDL_CREATE_CHILD, /* 0 */
3449 SDDL_DELETE_CHILD,
3450 SDDL_LIST_CHILDREN,
3451 SDDL_SELF_WRITE,
3452 SDDL_READ_PROPERTY, /* 4 */
3453 SDDL_WRITE_PROPERTY,
3454 SDDL_DELETE_TREE,
3455 SDDL_LIST_OBJECT,
3456 SDDL_CONTROL_ACCESS, /* 8 */
3457 NULL,
3458 NULL,
3459 NULL,
3460 NULL, /* 12 */
3461 NULL,
3462 NULL,
3463 NULL,
3464 SDDL_STANDARD_DELETE, /* 16 */
3465 SDDL_READ_CONTROL,
3466 SDDL_WRITE_DAC,
3467 SDDL_WRITE_OWNER,
3468 NULL, /* 20 */
3469 NULL,
3470 NULL,
3471 NULL,
3472 NULL, /* 24 */
3473 NULL,
3474 NULL,
3475 NULL,
3476 SDDL_GENERIC_ALL, /* 28 */
3477 SDDL_GENERIC_EXECUTE,
3478 SDDL_GENERIC_WRITE,
3479 SDDL_GENERIC_READ
3482 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
3484 static const WCHAR fmtW[] = {'0','x','%','x',0};
3485 WCHAR buf[15];
3486 size_t i;
3488 if (mask == 0)
3489 return;
3491 /* first check if the right have name */
3492 for (i = 0; i < ARRAY_SIZE(AceRights); i++)
3494 if (AceRights[i].wstr == NULL)
3495 break;
3496 if (mask == AceRights[i].value)
3498 DumpString(AceRights[i].wstr, -1, pwptr, plen);
3499 return;
3503 /* then check if it can be built from bit names */
3504 for (i = 0; i < 32; i++)
3506 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
3508 /* can't be built from bit names */
3509 sprintfW(buf, fmtW, mask);
3510 DumpString(buf, -1, pwptr, plen);
3511 return;
3515 /* build from bit names */
3516 for (i = 0; i < 32; i++)
3517 if (mask & (1 << i))
3518 DumpString(AceRightBitNames[i], -1, pwptr, plen);
3521 static inline BOOL is_object_ace(BYTE AceType)
3523 switch (AceType)
3525 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
3526 case ACCESS_DENIED_OBJECT_ACE_TYPE:
3527 case ACCESS_AUDIT_OBJECT_ACE_TYPE:
3528 case ACCESS_ALARM_OBJECT_ACE_TYPE:
3529 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
3530 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
3531 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
3532 case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE:
3533 return TRUE;
3535 default: return FALSE;
3539 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
3541 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
3542 static const WCHAR openbr = '(';
3543 static const WCHAR closebr = ')';
3544 static const WCHAR semicolon = ';';
3545 DWORD *SidStart;
3547 piace = pace;
3549 if (piace->Header.AceType > ACCESS_MAX_MS_V5_ACE_TYPE || piace->Header.AceSize < sizeof(ACCESS_ALLOWED_ACE))
3551 SetLastError(ERROR_INVALID_ACL);
3552 return FALSE;
3555 DumpString(&openbr, 1, pwptr, plen);
3556 switch (piace->Header.AceType)
3558 case ACCESS_ALLOWED_ACE_TYPE:
3559 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
3560 break;
3561 case ACCESS_DENIED_ACE_TYPE:
3562 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
3563 break;
3564 case SYSTEM_AUDIT_ACE_TYPE:
3565 DumpString(SDDL_AUDIT, -1, pwptr, plen);
3566 break;
3567 case SYSTEM_ALARM_ACE_TYPE:
3568 DumpString(SDDL_ALARM, -1, pwptr, plen);
3569 break;
3571 DumpString(&semicolon, 1, pwptr, plen);
3573 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
3574 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
3575 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
3576 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
3577 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
3578 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
3579 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
3580 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
3581 if (piace->Header.AceFlags & INHERITED_ACE)
3582 DumpString(SDDL_INHERITED, -1, pwptr, plen);
3583 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
3584 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
3585 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
3586 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
3587 DumpString(&semicolon, 1, pwptr, plen);
3588 DumpRights(piace->Mask, pwptr, plen);
3589 DumpString(&semicolon, 1, pwptr, plen);
3590 SidStart = &piace->SidStart;
3591 if (is_object_ace(piace->Header.AceType))
3593 ACCESS_ALLOWED_OBJECT_ACE *objace = pace;
3595 SidStart++; /* Flags */
3596 if (objace->Flags & ACE_OBJECT_TYPE_PRESENT)
3597 SidStart += sizeof(GUID) / sizeof(*SidStart); /* ObjectType */
3598 if (objace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
3599 SidStart += sizeof(GUID) / sizeof(*SidStart); /* InheritedObjectType */
3601 /* objects not supported */
3602 DumpString(&semicolon, 1, pwptr, plen);
3603 /* objects not supported */
3604 DumpString(&semicolon, 1, pwptr, plen);
3605 if (!DumpSid(SidStart, pwptr, plen))
3606 return FALSE;
3607 DumpString(&closebr, 1, pwptr, plen);
3608 return TRUE;
3611 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
3613 WORD count;
3614 UINT i;
3616 if (protected)
3617 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
3618 if (autoInheritReq)
3619 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
3620 if (autoInherited)
3621 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
3623 if (pacl == NULL)
3624 return TRUE;
3626 if (!IsValidAcl(pacl))
3627 return FALSE;
3629 count = pacl->AceCount;
3630 for (i = 0; i < count; i++)
3632 LPVOID ace;
3633 if (!GetAce(pacl, i, &ace))
3634 return FALSE;
3635 if (!DumpAce(ace, pwptr, plen))
3636 return FALSE;
3639 return TRUE;
3642 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3644 static const WCHAR prefix[] = {'O',':',0};
3645 BOOL bDefaulted;
3646 PSID psid;
3648 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
3649 return FALSE;
3651 if (psid == NULL)
3652 return TRUE;
3654 DumpString(prefix, -1, pwptr, plen);
3655 if (!DumpSid(psid, pwptr, plen))
3656 return FALSE;
3657 return TRUE;
3660 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3662 static const WCHAR prefix[] = {'G',':',0};
3663 BOOL bDefaulted;
3664 PSID psid;
3666 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
3667 return FALSE;
3669 if (psid == NULL)
3670 return TRUE;
3672 DumpString(prefix, -1, pwptr, plen);
3673 if (!DumpSid(psid, pwptr, plen))
3674 return FALSE;
3675 return TRUE;
3678 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3680 static const WCHAR dacl[] = {'D',':',0};
3681 SECURITY_DESCRIPTOR_CONTROL control;
3682 BOOL present, defaulted;
3683 DWORD revision;
3684 PACL pacl;
3686 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
3687 return FALSE;
3689 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
3690 return FALSE;
3692 if (!present)
3693 return TRUE;
3695 DumpString(dacl, 2, pwptr, plen);
3696 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
3697 return FALSE;
3698 return TRUE;
3701 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3703 static const WCHAR sacl[] = {'S',':',0};
3704 SECURITY_DESCRIPTOR_CONTROL control;
3705 BOOL present, defaulted;
3706 DWORD revision;
3707 PACL pacl;
3709 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
3710 return FALSE;
3712 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
3713 return FALSE;
3715 if (!present)
3716 return TRUE;
3718 DumpString(sacl, 2, pwptr, plen);
3719 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
3720 return FALSE;
3721 return TRUE;
3724 /******************************************************************************
3725 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
3727 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
3729 ULONG len;
3730 WCHAR *wptr, *wstr;
3732 if (SDRevision != SDDL_REVISION_1)
3734 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
3735 SetLastError(ERROR_UNKNOWN_REVISION);
3736 return FALSE;
3739 len = 0;
3740 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
3741 if (!DumpOwner(SecurityDescriptor, NULL, &len))
3742 return FALSE;
3743 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
3744 if (!DumpGroup(SecurityDescriptor, NULL, &len))
3745 return FALSE;
3746 if (RequestedInformation & DACL_SECURITY_INFORMATION)
3747 if (!DumpDacl(SecurityDescriptor, NULL, &len))
3748 return FALSE;
3749 if (RequestedInformation & SACL_SECURITY_INFORMATION)
3750 if (!DumpSacl(SecurityDescriptor, NULL, &len))
3751 return FALSE;
3753 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
3754 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
3755 if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) {
3756 LocalFree (wstr);
3757 return FALSE;
3759 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
3760 if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) {
3761 LocalFree (wstr);
3762 return FALSE;
3764 if (RequestedInformation & DACL_SECURITY_INFORMATION)
3765 if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) {
3766 LocalFree (wstr);
3767 return FALSE;
3769 if (RequestedInformation & SACL_SECURITY_INFORMATION)
3770 if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) {
3771 LocalFree (wstr);
3772 return FALSE;
3774 *wptr = 0;
3776 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
3777 *OutputString = wstr;
3778 if (OutputLen)
3779 *OutputLen = strlenW(*OutputString)+1;
3780 return TRUE;
3783 /******************************************************************************
3784 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
3786 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
3788 LPWSTR wstr;
3789 ULONG len;
3790 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
3792 int lenA;
3794 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
3795 *OutputString = heap_alloc(lenA);
3796 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
3797 LocalFree(wstr);
3799 if (OutputLen != NULL)
3800 *OutputLen = lenA;
3801 return TRUE;
3803 else
3805 *OutputString = NULL;
3806 if (OutputLen)
3807 *OutputLen = 0;
3808 return FALSE;
3812 /******************************************************************************
3813 * ConvertStringSidToSidW [ADVAPI32.@]
3815 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
3817 BOOL bret = FALSE;
3818 DWORD cBytes;
3820 TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
3821 if (GetVersion() & 0x80000000)
3822 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3823 else if (!StringSid || !Sid)
3824 SetLastError(ERROR_INVALID_PARAMETER);
3825 else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
3827 PSID pSid = *Sid = LocalAlloc(0, cBytes);
3829 bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
3830 if (!bret)
3831 LocalFree(*Sid);
3833 return bret;
3836 /******************************************************************************
3837 * ConvertStringSidToSidA [ADVAPI32.@]
3839 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
3841 BOOL bret = FALSE;
3843 TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
3844 if (GetVersion() & 0x80000000)
3845 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3846 else if (!StringSid || !Sid)
3847 SetLastError(ERROR_INVALID_PARAMETER);
3848 else
3850 WCHAR *wStringSid = SERV_dup(StringSid);
3851 bret = ConvertStringSidToSidW(wStringSid, Sid);
3852 heap_free(wStringSid);
3854 return bret;
3857 /******************************************************************************
3858 * ConvertSidToStringSidW [ADVAPI32.@]
3860 * format of SID string is:
3861 * S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
3862 * where
3863 * <rev> is the revision of the SID encoded as decimal
3864 * <auth> is the identifier authority encoded as hex
3865 * <subauthN> is the subauthority id encoded as decimal
3867 BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
3869 DWORD len = 0;
3870 LPWSTR wstr, wptr;
3872 TRACE("%p %p\n", pSid, pstr );
3874 len = 0;
3875 if (!DumpSidNumeric(pSid, NULL, &len))
3876 return FALSE;
3877 wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
3878 DumpSidNumeric(pSid, &wptr, NULL);
3879 *wptr = 0;
3881 *pstr = wstr;
3882 return TRUE;
3885 /******************************************************************************
3886 * ConvertSidToStringSidA [ADVAPI32.@]
3888 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
3890 LPWSTR wstr = NULL;
3891 LPSTR str;
3892 UINT len;
3894 TRACE("%p %p\n", pSid, pstr );
3896 if( !ConvertSidToStringSidW( pSid, &wstr ) )
3897 return FALSE;
3899 len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
3900 str = LocalAlloc( 0, len );
3901 WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
3902 LocalFree( wstr );
3904 *pstr = str;
3906 return TRUE;
3909 /******************************************************************************
3910 * CreateProcessWithLogonW
3912 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
3913 LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
3914 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
3916 FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
3917 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
3918 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
3919 lpStartupInfo, lpProcessInformation);
3921 return FALSE;
3924 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line,
3925 DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info,
3926 PROCESS_INFORMATION *process_information )
3928 FIXME("%p 0x%08x %s %s 0x%08x %p %s %p %p - semi-stub\n", token,
3929 logon_flags, debugstr_w(application_name), debugstr_w(command_line),
3930 creation_flags, environment, debugstr_w(current_directory),
3931 startup_info, process_information);
3933 /* FIXME: check if handles should be inherited */
3934 return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment,
3935 current_directory, startup_info, process_information );
3938 /******************************************************************************
3939 * ComputeStringSidSize
3941 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
3943 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
3945 int ctok = 0;
3946 while (*StringSid)
3948 if (*StringSid == '-')
3949 ctok++;
3950 StringSid++;
3953 if (ctok >= 3)
3954 return GetSidLengthRequired(ctok - 2);
3956 else /* String constant format - Only available in winxp and above */
3958 unsigned int i;
3960 for (i = 0; i < ARRAY_SIZE(WellKnownSids); i++)
3961 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
3962 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
3964 for (i = 0; i < ARRAY_SIZE(WellKnownRids); i++)
3965 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
3967 MAX_SID local;
3968 ADVAPI_GetComputerSid(&local);
3969 return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1);
3974 return GetSidLengthRequired(0);
3977 /******************************************************************************
3978 * ParseStringSidToSid
3980 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
3982 BOOL bret = FALSE;
3983 SID* pisid=pSid;
3985 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
3986 if (!StringSid)
3988 SetLastError(ERROR_INVALID_PARAMETER);
3989 TRACE("StringSid is NULL, returning FALSE\n");
3990 return FALSE;
3993 while (*StringSid == ' ')
3994 StringSid++;
3996 *cBytes = ComputeStringSidSize(StringSid);
3997 if (!pisid) /* Simply compute the size */
3999 TRACE("only size requested, returning TRUE with %d\n", *cBytes);
4000 return TRUE;
4003 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
4005 DWORD i = 0, identAuth;
4006 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
4008 StringSid += 2; /* Advance to Revision */
4009 pisid->Revision = atoiW(StringSid);
4011 if (pisid->Revision != SDDL_REVISION)
4013 TRACE("Revision %d is unknown\n", pisid->Revision);
4014 goto lend; /* ERROR_INVALID_SID */
4016 if (csubauth == 0)
4018 TRACE("SubAuthorityCount is 0\n");
4019 goto lend; /* ERROR_INVALID_SID */
4022 pisid->SubAuthorityCount = csubauth;
4024 /* Advance to identifier authority */
4025 while (*StringSid && *StringSid != '-')
4026 StringSid++;
4027 if (*StringSid == '-')
4028 StringSid++;
4030 /* MS' implementation can't handle values greater than 2^32 - 1, so
4031 * we don't either; assume most significant bytes are always 0
4033 pisid->IdentifierAuthority.Value[0] = 0;
4034 pisid->IdentifierAuthority.Value[1] = 0;
4035 identAuth = atoiW(StringSid);
4036 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
4037 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
4038 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
4039 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
4041 /* Advance to first sub authority */
4042 while (*StringSid && *StringSid != '-')
4043 StringSid++;
4044 if (*StringSid == '-')
4045 StringSid++;
4047 while (*StringSid)
4049 pisid->SubAuthority[i++] = atoiW(StringSid);
4051 while (*StringSid && *StringSid != '-')
4052 StringSid++;
4053 if (*StringSid == '-')
4054 StringSid++;
4057 if (i != pisid->SubAuthorityCount)
4058 goto lend; /* ERROR_INVALID_SID */
4060 bret = TRUE;
4062 else /* String constant format - Only available in winxp and above */
4064 unsigned int i;
4065 pisid->Revision = SDDL_REVISION;
4067 for (i = 0; i < ARRAY_SIZE(WellKnownSids); i++)
4068 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
4070 DWORD j;
4071 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
4072 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
4073 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
4074 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
4075 bret = TRUE;
4078 for (i = 0; i < ARRAY_SIZE(WellKnownRids); i++)
4079 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
4081 ADVAPI_GetComputerSid(pisid);
4082 pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid;
4083 pisid->SubAuthorityCount++;
4084 bret = TRUE;
4087 if (!bret)
4088 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
4091 lend:
4092 if (!bret)
4093 SetLastError(ERROR_INVALID_SID);
4095 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
4096 return bret;
4099 /******************************************************************************
4100 * GetNamedSecurityInfoA [ADVAPI32.@]
4102 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
4103 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
4104 PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
4105 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
4107 LPWSTR wstr;
4108 DWORD r;
4110 TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
4111 ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
4113 wstr = SERV_dup(pObjectName);
4114 r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
4115 ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
4117 heap_free( wstr );
4119 return r;
4122 /******************************************************************************
4123 * GetNamedSecurityInfoW [ADVAPI32.@]
4125 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
4126 SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
4127 PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
4129 DWORD access = 0;
4130 HANDLE handle;
4131 DWORD err;
4133 TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
4134 group, dacl, sacl, descriptor );
4136 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
4137 if (!name || !(owner||group||dacl||sacl||descriptor) ) return ERROR_INVALID_PARAMETER;
4139 /* If no descriptor, we have to check that there's a pointer for the requested information */
4140 if( !descriptor && (
4141 ((info & OWNER_SECURITY_INFORMATION) && !owner)
4142 || ((info & GROUP_SECURITY_INFORMATION) && !group)
4143 || ((info & DACL_SECURITY_INFORMATION) && !dacl)
4144 || ((info & SACL_SECURITY_INFORMATION) && !sacl) ))
4145 return ERROR_INVALID_PARAMETER;
4147 if (info & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION))
4148 access |= READ_CONTROL;
4149 if (info & SACL_SECURITY_INFORMATION)
4150 access |= ACCESS_SYSTEM_SECURITY;
4152 switch (type)
4154 case SE_SERVICE:
4155 if (!(err = get_security_service( name, access, &handle )))
4157 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
4158 CloseServiceHandle( handle );
4160 break;
4161 case SE_REGISTRY_KEY:
4162 if (!(err = get_security_regkey( name, access, &handle )))
4164 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
4165 RegCloseKey( handle );
4167 break;
4168 case SE_FILE_OBJECT:
4169 if (!(err = get_security_file( name, access, &handle )))
4171 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
4172 CloseHandle( handle );
4174 break;
4175 default:
4176 FIXME( "Object type %d is not currently supported.\n", type );
4177 if (owner) *owner = NULL;
4178 if (group) *group = NULL;
4179 if (dacl) *dacl = NULL;
4180 if (sacl) *sacl = NULL;
4181 if (descriptor) *descriptor = NULL;
4182 return ERROR_SUCCESS;
4184 return err;
4187 /******************************************************************************
4188 * GetNamedSecurityInfoExW [ADVAPI32.@]
4190 DWORD WINAPI GetNamedSecurityInfoExW( LPCWSTR object, SE_OBJECT_TYPE type,
4191 SECURITY_INFORMATION info, LPCWSTR provider, LPCWSTR property,
4192 PACTRL_ACCESSW* access_list, PACTRL_AUDITW* audit_list, LPWSTR* owner, LPWSTR* group )
4194 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_w(object), type, info,
4195 debugstr_w(provider), debugstr_w(property), access_list, audit_list, owner, group);
4196 return ERROR_CALL_NOT_IMPLEMENTED;
4199 /******************************************************************************
4200 * GetNamedSecurityInfoExA [ADVAPI32.@]
4202 DWORD WINAPI GetNamedSecurityInfoExA( LPCSTR object, SE_OBJECT_TYPE type,
4203 SECURITY_INFORMATION info, LPCSTR provider, LPCSTR property,
4204 PACTRL_ACCESSA* access_list, PACTRL_AUDITA* audit_list, LPSTR* owner, LPSTR* group )
4206 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_a(object), type, info,
4207 debugstr_a(provider), debugstr_a(property), access_list, audit_list, owner, group);
4208 return ERROR_CALL_NOT_IMPLEMENTED;
4211 /******************************************************************************
4212 * DecryptFileW [ADVAPI32.@]
4214 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
4216 FIXME("(%s, %08x): stub\n", debugstr_w(lpFileName), dwReserved);
4217 return TRUE;
4220 /******************************************************************************
4221 * DecryptFileA [ADVAPI32.@]
4223 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
4225 FIXME("(%s, %08x): stub\n", debugstr_a(lpFileName), dwReserved);
4226 return TRUE;
4229 /******************************************************************************
4230 * EncryptFileW [ADVAPI32.@]
4232 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
4234 FIXME("(%s): stub\n", debugstr_w(lpFileName));
4235 return TRUE;
4238 /******************************************************************************
4239 * EncryptFileA [ADVAPI32.@]
4241 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
4243 FIXME("(%s): stub\n", debugstr_a(lpFileName));
4244 return TRUE;
4247 /******************************************************************************
4248 * FileEncryptionStatusW [ADVAPI32.@]
4250 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
4252 FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
4253 if (!lpStatus)
4254 return FALSE;
4255 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
4256 return TRUE;
4259 /******************************************************************************
4260 * FileEncryptionStatusA [ADVAPI32.@]
4262 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
4264 FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
4265 if (!lpStatus)
4266 return FALSE;
4267 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
4268 return TRUE;
4271 static NTSTATUS combine_dacls(ACL *parent, ACL *child, ACL **result)
4273 NTSTATUS status;
4274 ACL *combined;
4275 int i;
4277 /* initialize a combined DACL containing both inherited and new ACEs */
4278 combined = heap_alloc_zero(child->AclSize+parent->AclSize);
4279 if (!combined)
4280 return STATUS_NO_MEMORY;
4282 status = RtlCreateAcl(combined, parent->AclSize+child->AclSize, ACL_REVISION);
4283 if (status != STATUS_SUCCESS)
4285 heap_free(combined);
4286 return status;
4289 /* copy the new ACEs */
4290 for (i=0; i<child->AceCount; i++)
4292 ACE_HEADER *ace;
4294 if (!GetAce(child, i, (void*)&ace))
4295 continue;
4296 if (!AddAce(combined, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
4297 WARN("error adding new ACE\n");
4300 /* copy the inherited ACEs */
4301 for (i=0; i<parent->AceCount; i++)
4303 ACE_HEADER *ace;
4305 if (!GetAce(parent, i, (void*)&ace))
4306 continue;
4307 if (!(ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)))
4308 continue;
4309 if ((ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) !=
4310 (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE))
4312 FIXME("unsupported flags: %x\n", ace->AceFlags);
4313 continue;
4316 if (ace->AceFlags & NO_PROPAGATE_INHERIT_ACE)
4317 ace->AceFlags &= ~(OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE|NO_PROPAGATE_INHERIT_ACE);
4318 ace->AceFlags &= ~INHERIT_ONLY_ACE;
4319 ace->AceFlags |= INHERITED_ACE;
4321 if (!AddAce(combined, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
4322 WARN("error adding inherited ACE\n");
4325 *result = combined;
4326 return STATUS_SUCCESS;
4329 /******************************************************************************
4330 * SetSecurityInfo [ADVAPI32.@]
4332 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType,
4333 SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
4334 PSID psidGroup, PACL pDacl, PACL pSacl)
4336 SECURITY_DESCRIPTOR sd;
4337 PACL dacl = pDacl;
4338 NTSTATUS status;
4340 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
4341 return ERROR_INVALID_SECURITY_DESCR;
4343 if (SecurityInfo & OWNER_SECURITY_INFORMATION)
4344 SetSecurityDescriptorOwner(&sd, psidOwner, FALSE);
4345 if (SecurityInfo & GROUP_SECURITY_INFORMATION)
4346 SetSecurityDescriptorGroup(&sd, psidGroup, FALSE);
4347 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4349 if (ObjectType == SE_FILE_OBJECT && pDacl)
4351 SECURITY_DESCRIPTOR_CONTROL control;
4352 PSECURITY_DESCRIPTOR psd;
4353 OBJECT_NAME_INFORMATION *name_info;
4354 DWORD size, rev;
4356 status = NtQuerySecurityObject(handle, SecurityInfo, NULL, 0, &size);
4357 if (status != STATUS_BUFFER_TOO_SMALL)
4358 return RtlNtStatusToDosError(status);
4360 psd = heap_alloc(size);
4361 if (!psd)
4362 return ERROR_NOT_ENOUGH_MEMORY;
4364 status = NtQuerySecurityObject(handle, SecurityInfo, psd, size, &size);
4365 if (status)
4367 heap_free(psd);
4368 return RtlNtStatusToDosError(status);
4371 status = RtlGetControlSecurityDescriptor(psd, &control, &rev);
4372 heap_free(psd);
4373 if (status)
4374 return RtlNtStatusToDosError(status);
4375 /* TODO: copy some control flags to new sd */
4377 /* inherit parent directory DACL */
4378 if (!(control & SE_DACL_PROTECTED))
4380 status = NtQueryObject(handle, ObjectNameInformation, NULL, 0, &size);
4381 if (status != STATUS_INFO_LENGTH_MISMATCH)
4382 return RtlNtStatusToDosError(status);
4384 name_info = heap_alloc(size);
4385 if (!name_info)
4386 return ERROR_NOT_ENOUGH_MEMORY;
4388 status = NtQueryObject(handle, ObjectNameInformation, name_info, size, NULL);
4389 if (status)
4391 heap_free(name_info);
4392 return RtlNtStatusToDosError(status);
4395 for (name_info->Name.Length-=2; name_info->Name.Length>0; name_info->Name.Length-=2)
4396 if (name_info->Name.Buffer[name_info->Name.Length/2-1]=='\\' ||
4397 name_info->Name.Buffer[name_info->Name.Length/2-1]=='/')
4398 break;
4399 if (name_info->Name.Length)
4401 OBJECT_ATTRIBUTES attr;
4402 IO_STATUS_BLOCK io;
4403 HANDLE parent;
4404 PSECURITY_DESCRIPTOR parent_sd;
4405 ACL *parent_dacl;
4406 DWORD err = ERROR_ACCESS_DENIED;
4408 name_info->Name.Buffer[name_info->Name.Length/2] = 0;
4410 attr.Length = sizeof(attr);
4411 attr.RootDirectory = 0;
4412 attr.Attributes = 0;
4413 attr.ObjectName = &name_info->Name;
4414 attr.SecurityDescriptor = NULL;
4415 status = NtOpenFile(&parent, READ_CONTROL|SYNCHRONIZE, &attr, &io,
4416 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4417 FILE_OPEN_FOR_BACKUP_INTENT);
4418 heap_free(name_info);
4419 if (!status)
4421 err = GetSecurityInfo(parent, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4422 NULL, NULL, &parent_dacl, NULL, &parent_sd);
4423 CloseHandle(parent);
4426 if (!err)
4428 status = combine_dacls(parent_dacl, pDacl, &dacl);
4429 LocalFree(parent_sd);
4430 if (status != STATUS_SUCCESS)
4431 return RtlNtStatusToDosError(status);
4434 else
4435 heap_free(name_info);
4439 SetSecurityDescriptorDacl(&sd, TRUE, dacl, FALSE);
4441 if (SecurityInfo & SACL_SECURITY_INFORMATION)
4442 SetSecurityDescriptorSacl(&sd, TRUE, pSacl, FALSE);
4444 switch (ObjectType)
4446 case SE_SERVICE:
4447 FIXME("stub: Service objects are not supported at this time.\n");
4448 status = STATUS_SUCCESS; /* Implement SetServiceObjectSecurity */
4449 break;
4450 default:
4451 status = NtSetSecurityObject(handle, SecurityInfo, &sd);
4452 break;
4454 if (dacl != pDacl)
4455 heap_free(dacl);
4456 return RtlNtStatusToDosError(status);
4459 /******************************************************************************
4460 * SaferCreateLevel [ADVAPI32.@]
4462 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
4463 SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
4465 FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
4467 *LevelHandle = (SAFER_LEVEL_HANDLE)0xdeadbeef;
4468 return TRUE;
4471 /******************************************************************************
4472 * SaferComputeTokenFromLevel [ADVAPI32.@]
4474 BOOL WINAPI SaferComputeTokenFromLevel(SAFER_LEVEL_HANDLE handle, HANDLE token, PHANDLE access_token,
4475 DWORD flags, LPVOID reserved)
4477 FIXME("(%p, %p, %p, %x, %p) stub\n", handle, token, access_token, flags, reserved);
4479 *access_token = (flags & SAFER_TOKEN_NULL_IF_EQUAL) ? NULL : (HANDLE)0xdeadbeef;
4480 return TRUE;
4483 /******************************************************************************
4484 * SaferCloseLevel [ADVAPI32.@]
4486 BOOL WINAPI SaferCloseLevel(SAFER_LEVEL_HANDLE handle)
4488 FIXME("(%p) stub\n", handle);
4489 return TRUE;
4492 /******************************************************************************
4493 * TreeResetNamedSecurityInfoW [ADVAPI32.@]
4495 DWORD WINAPI TreeResetNamedSecurityInfoW( LPWSTR pObjectName,
4496 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
4497 PSID pOwner, PSID pGroup, PACL pDacl, PACL pSacl,
4498 BOOL KeepExplicit, FN_PROGRESS fnProgress,
4499 PROG_INVOKE_SETTING ProgressInvokeSetting, PVOID Args)
4501 FIXME("(%s, %i, %i, %p, %p, %p, %p, %i, %p, %i, %p) stub\n",
4502 debugstr_w(pObjectName), ObjectType, SecurityInfo, pOwner, pGroup,
4503 pDacl, pSacl, KeepExplicit, fnProgress, ProgressInvokeSetting, Args);
4505 return ERROR_SUCCESS;
4508 /******************************************************************************
4509 * SaferGetPolicyInformation [ADVAPI32.@]
4511 BOOL WINAPI SaferGetPolicyInformation(DWORD scope, SAFER_POLICY_INFO_CLASS class, DWORD size,
4512 PVOID buffer, PDWORD required, LPVOID lpReserved)
4514 FIXME("(%u %u %u %p %p %p) stub\n", scope, class, size, buffer, required, lpReserved);
4515 return FALSE;
4518 /******************************************************************************
4519 * SaferIdentifyLevel [ADVAPI32.@]
4521 BOOL WINAPI SaferIdentifyLevel(DWORD count, SAFER_CODE_PROPERTIES *properties, SAFER_LEVEL_HANDLE *handle,
4522 void *reserved)
4524 FIXME("(%u %p %p %p) stub\n", count, properties, handle, reserved);
4525 *handle = (SAFER_LEVEL_HANDLE)0xdeadbeef;
4526 return TRUE;
4529 /******************************************************************************
4530 * SaferSetLevelInformation [ADVAPI32.@]
4532 BOOL WINAPI SaferSetLevelInformation(SAFER_LEVEL_HANDLE handle, SAFER_OBJECT_INFO_CLASS infotype,
4533 LPVOID buffer, DWORD size)
4535 FIXME("(%p %u %p %u) stub\n", handle, infotype, buffer, size);
4536 return FALSE;
4539 /******************************************************************************
4540 * LookupSecurityDescriptorPartsA [ADVAPI32.@]
4542 DWORD WINAPI LookupSecurityDescriptorPartsA(TRUSTEEA *owner, TRUSTEEA *group, ULONG *access_count,
4543 EXPLICIT_ACCESSA *access_list, ULONG *audit_count,
4544 EXPLICIT_ACCESSA *audit_list, SECURITY_DESCRIPTOR *descriptor)
4546 FIXME("(%p %p %p %p %p %p %p) stub\n", owner, group, access_count,
4547 access_list, audit_count, audit_list, descriptor);
4548 return ERROR_CALL_NOT_IMPLEMENTED;
4551 /******************************************************************************
4552 * LookupSecurityDescriptorPartsW [ADVAPI32.@]
4554 DWORD WINAPI LookupSecurityDescriptorPartsW(TRUSTEEW *owner, TRUSTEEW *group, ULONG *access_count,
4555 EXPLICIT_ACCESSW *access_list, ULONG *audit_count,
4556 EXPLICIT_ACCESSW *audit_list, SECURITY_DESCRIPTOR *descriptor)
4558 FIXME("(%p %p %p %p %p %p %p) stub\n", owner, group, access_count,
4559 access_list, audit_count, audit_list, descriptor);
4560 return ERROR_CALL_NOT_IMPLEMENTED;