vcomp/tests: Add tests for atomic double functions.
[wine.git] / dlls / advapi32 / security.c
blobb632577f51333bb9f773252f437337fa9e0bd48a
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 <stdarg.h>
23 #include <string.h>
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "winreg.h"
31 #include "winsafer.h"
32 #include "winternl.h"
33 #include "winioctl.h"
34 #include "accctrl.h"
35 #include "sddl.h"
36 #include "winsvc.h"
37 #include "aclapi.h"
38 #include "objbase.h"
39 #include "iads.h"
40 #include "advapi32_misc.h"
41 #include "lmcons.h"
43 #include "wine/debug.h"
44 #include "wine/unicode.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
48 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes);
49 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
50 PACL pAcl, LPDWORD cBytes);
51 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl);
52 static BYTE ParseAceStringType(LPCWSTR* StringAcl);
53 static DWORD ParseAceStringRights(LPCWSTR* StringAcl);
54 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
55 LPCWSTR StringSecurityDescriptor,
56 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
57 LPDWORD cBytes);
58 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl);
60 typedef struct _ACEFLAG
62 LPCWSTR wstr;
63 DWORD value;
64 } ACEFLAG, *LPACEFLAG;
66 typedef struct _MAX_SID
68 /* same fields as struct _SID */
69 BYTE Revision;
70 BYTE SubAuthorityCount;
71 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
72 DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
73 } MAX_SID;
75 typedef struct WELLKNOWNSID
77 WCHAR wstr[2];
78 WELL_KNOWN_SID_TYPE Type;
79 MAX_SID Sid;
80 } WELLKNOWNSID;
82 static const WELLKNOWNSID WellKnownSids[] =
84 { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
85 { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
86 { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
87 { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
88 { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
89 { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
90 { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
91 { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
92 { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
93 { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
94 { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
95 { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
96 { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
97 { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
98 { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
99 { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
100 { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
101 { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
102 { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
103 { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
104 { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
105 { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
106 { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
107 { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
108 { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
109 { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
110 { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
111 { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
112 { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
113 { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
114 { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
115 { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
116 { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
117 { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
118 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
119 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
120 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
121 { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
122 { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
123 { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
124 { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
125 { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
126 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS } } },
127 { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
128 { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
129 { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
130 { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
131 { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
132 { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } },
133 { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } },
134 { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } },
135 { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } },
138 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */
139 typedef struct WELLKNOWNRID
141 WCHAR wstr[2];
142 WELL_KNOWN_SID_TYPE Type;
143 DWORD Rid;
144 } WELLKNOWNRID;
146 static const WELLKNOWNRID WellKnownRids[] = {
147 { {'L','A'}, WinAccountAdministratorSid, DOMAIN_USER_RID_ADMIN },
148 { {'L','G'}, WinAccountGuestSid, DOMAIN_USER_RID_GUEST },
149 { {0,0}, WinAccountKrbtgtSid, DOMAIN_USER_RID_KRBTGT },
150 { {0,0}, WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS },
151 { {0,0}, WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS },
152 { {0,0}, WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS },
153 { {0,0}, WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS },
154 { {0,0}, WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS },
155 { {0,0}, WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS },
156 { {0,0}, WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS },
157 { {0,0}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
158 { {0,0}, WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS },
159 { {0,0}, WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
163 static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
165 typedef struct _AccountSid {
166 WELL_KNOWN_SID_TYPE type;
167 LPCWSTR account;
168 LPCWSTR domain;
169 SID_NAME_USE name_use;
170 LPCWSTR alias;
171 } AccountSid;
173 static const WCHAR Account_Operators[] = { 'A','c','c','o','u','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
174 static const WCHAR Administrator[] = {'A','d','m','i','n','i','s','t','r','a','t','o','r',0 };
175 static const WCHAR Administrators[] = { 'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0 };
176 static const WCHAR ANONYMOUS_LOGON[] = { 'A','N','O','N','Y','M','O','U','S',' ','L','O','G','O','N',0 };
177 static const WCHAR Authenticated_Users[] = { 'A','u','t','h','e','n','t','i','c','a','t','e','d',' ','U','s','e','r','s',0 };
178 static const WCHAR Backup_Operators[] = { 'B','a','c','k','u','p',' ','O','p','e','r','a','t','o','r','s',0 };
179 static const WCHAR BATCH[] = { 'B','A','T','C','H',0 };
180 static const WCHAR Blank[] = { 0 };
181 static const WCHAR BUILTIN[] = { 'B','U','I','L','T','I','N',0 };
182 static const WCHAR Cert_Publishers[] = { 'C','e','r','t',' ','P','u','b','l','i','s','h','e','r','s',0 };
183 static const WCHAR CREATOR_GROUP[] = { 'C','R','E','A','T','O','R',' ','G','R','O','U','P',0 };
184 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 };
185 static const WCHAR CREATOR_OWNER[] = { 'C','R','E','A','T','O','R',' ','O','W','N','E','R',0 };
186 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 };
187 static const WCHAR CURRENT_USER[] = { 'C','U','R','R','E','N','T','_','U','S','E','R',0 };
188 static const WCHAR DIALUP[] = { 'D','I','A','L','U','P',0 };
189 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 };
190 static const WCHAR Domain_Admins[] = { 'D','o','m','a','i','n',' ','A','d','m','i','n','s',0 };
191 static const WCHAR Domain_Computers[] = { 'D','o','m','a','i','n',' ','C','o','m','p','u','t','e','r','s',0 };
192 static const WCHAR Domain_Controllers[] = { 'D','o','m','a','i','n',' ','C','o','n','t','r','o','l','l','e','r','s',0 };
193 static const WCHAR Domain_Guests[] = { 'D','o','m','a','i','n',' ','G','u','e','s','t','s',0 };
194 static const WCHAR Domain_Users[] = { 'D','o','m','a','i','n',' ','U','s','e','r','s',0 };
195 static const WCHAR Enterprise_Admins[] = { 'E','n','t','e','r','p','r','i','s','e',' ','A','d','m','i','n','s',0 };
196 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 };
197 static const WCHAR Everyone[] = { 'E','v','e','r','y','o','n','e',0 };
198 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 };
199 static const WCHAR Guest[] = { 'G','u','e','s','t',0 };
200 static const WCHAR Guests[] = { 'G','u','e','s','t','s',0 };
201 static const WCHAR INTERACTIVE[] = { 'I','N','T','E','R','A','C','T','I','V','E',0 };
202 static const WCHAR LOCAL[] = { 'L','O','C','A','L',0 };
203 static const WCHAR LOCAL_SERVICE[] = { 'L','O','C','A','L',' ','S','E','R','V','I','C','E',0 };
204 static const WCHAR LOCAL_SERVICE2[] = { 'L','O','C','A','L','S','E','R','V','I','C','E',0 };
205 static const WCHAR NETWORK[] = { 'N','E','T','W','O','R','K',0 };
206 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 };
207 static const WCHAR NETWORK_SERVICE[] = { 'N','E','T','W','O','R','K',' ','S','E','R','V','I','C','E',0 };
208 static const WCHAR NETWORK_SERVICE2[] = { 'N','E','T','W','O','R','K','S','E','R','V','I','C','E',0 };
209 static const WCHAR NT_AUTHORITY[] = { 'N','T',' ','A','U','T','H','O','R','I','T','Y',0 };
210 static const WCHAR NT_Pseudo_Domain[] = { 'N','T',' ','P','s','e','u','d','o',' ','D','o','m','a','i','n',0 };
211 static const WCHAR NTML_Authentication[] = { 'N','T','M','L',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
212 static const WCHAR NULL_SID[] = { 'N','U','L','L',' ','S','I','D',0 };
213 static const WCHAR Other_Organization[] = { 'O','t','h','e','r',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
214 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 };
215 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 };
216 static const WCHAR Power_Users[] = { 'P','o','w','e','r',' ','U','s','e','r','s',0 };
217 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 };
218 static const WCHAR Print_Operators[] = { 'P','r','i','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
219 static const WCHAR PROXY[] = { 'P','R','O','X','Y',0 };
220 static const WCHAR RAS_and_IAS_Servers[] = { 'R','A','S',' ','a','n','d',' ','I','A','S',' ','S','e','r','v','e','r','s',0 };
221 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 };
222 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 };
223 static const WCHAR Replicators[] = { 'R','e','p','l','i','c','a','t','o','r','s',0 };
224 static const WCHAR RESTRICTED[] = { 'R','E','S','T','R','I','C','T','E','D',0 };
225 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 };
226 static const WCHAR Schema_Admins[] = { 'S','c','h','e','m','a',' ','A','d','m','i','n','s',0 };
227 static const WCHAR SELF[] = { 'S','E','L','F',0 };
228 static const WCHAR Server_Operators[] = { 'S','e','r','v','e','r',' ','O','p','e','r','a','t','o','r','s',0 };
229 static const WCHAR SERVICE[] = { 'S','E','R','V','I','C','E',0 };
230 static const WCHAR SYSTEM[] = { 'S','Y','S','T','E','M',0 };
231 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 };
232 static const WCHAR This_Organization[] = { 'T','h','i','s',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
233 static const WCHAR Users[] = { 'U','s','e','r','s',0 };
235 static const AccountSid ACCOUNT_SIDS[] = {
236 { WinNullSid, NULL_SID, Blank, SidTypeWellKnownGroup },
237 { WinWorldSid, Everyone, Blank, SidTypeWellKnownGroup },
238 { WinLocalSid, LOCAL, Blank, SidTypeWellKnownGroup },
239 { WinCreatorOwnerSid, CREATOR_OWNER, Blank, SidTypeWellKnownGroup },
240 { WinCreatorGroupSid, CREATOR_GROUP, Blank, SidTypeWellKnownGroup },
241 { WinCreatorOwnerServerSid, CREATOR_OWNER_SERVER, Blank, SidTypeWellKnownGroup },
242 { WinCreatorGroupServerSid, CREATOR_GROUP_SERVER, Blank, SidTypeWellKnownGroup },
243 { WinNtAuthoritySid, NT_Pseudo_Domain, NT_Pseudo_Domain, SidTypeDomain },
244 { WinDialupSid, DIALUP, NT_AUTHORITY, SidTypeWellKnownGroup },
245 { WinNetworkSid, NETWORK, NT_AUTHORITY, SidTypeWellKnownGroup },
246 { WinBatchSid, BATCH, NT_AUTHORITY, SidTypeWellKnownGroup },
247 { WinInteractiveSid, INTERACTIVE, NT_AUTHORITY, SidTypeWellKnownGroup },
248 { WinServiceSid, SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup },
249 { WinAnonymousSid, ANONYMOUS_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
250 { WinProxySid, PROXY, NT_AUTHORITY, SidTypeWellKnownGroup },
251 { WinEnterpriseControllersSid, ENTERPRISE_DOMAIN_CONTROLLERS, NT_AUTHORITY, SidTypeWellKnownGroup },
252 { WinSelfSid, SELF, NT_AUTHORITY, SidTypeWellKnownGroup },
253 { WinAuthenticatedUserSid, Authenticated_Users, NT_AUTHORITY, SidTypeWellKnownGroup },
254 { WinRestrictedCodeSid, RESTRICTED, NT_AUTHORITY, SidTypeWellKnownGroup },
255 { WinTerminalServerSid, TERMINAL_SERVER_USER, NT_AUTHORITY, SidTypeWellKnownGroup },
256 { WinRemoteLogonIdSid, REMOTE_INTERACTIVE_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
257 { WinLocalSystemSid, SYSTEM, NT_AUTHORITY, SidTypeWellKnownGroup },
258 { WinLocalServiceSid, LOCAL_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup, LOCAL_SERVICE2 },
259 { WinNetworkServiceSid, NETWORK_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup , NETWORK_SERVICE2},
260 { WinBuiltinDomainSid, BUILTIN, BUILTIN, SidTypeDomain },
261 { WinBuiltinAdministratorsSid, Administrators, BUILTIN, SidTypeAlias },
262 { WinBuiltinUsersSid, Users, BUILTIN, SidTypeAlias },
263 { WinBuiltinGuestsSid, Guests, BUILTIN, SidTypeAlias },
264 { WinBuiltinPowerUsersSid, Power_Users, BUILTIN, SidTypeAlias },
265 { WinBuiltinAccountOperatorsSid, Account_Operators, BUILTIN, SidTypeAlias },
266 { WinBuiltinSystemOperatorsSid, Server_Operators, BUILTIN, SidTypeAlias },
267 { WinBuiltinPrintOperatorsSid, Print_Operators, BUILTIN, SidTypeAlias },
268 { WinBuiltinBackupOperatorsSid, Backup_Operators, BUILTIN, SidTypeAlias },
269 { WinBuiltinReplicatorSid, Replicators, BUILTIN, SidTypeAlias },
270 { WinBuiltinPreWindows2000CompatibleAccessSid, Pre_Windows_2000_Compatible_Access, BUILTIN, SidTypeAlias },
271 { WinBuiltinRemoteDesktopUsersSid, Remote_Desktop_Users, BUILTIN, SidTypeAlias },
272 { WinBuiltinNetworkConfigurationOperatorsSid, Network_Configuration_Operators, BUILTIN, SidTypeAlias },
273 { WinNTLMAuthenticationSid, NTML_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
274 { WinDigestAuthenticationSid, Digest_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
275 { WinSChannelAuthenticationSid, SChannel_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
276 { WinThisOrganizationSid, This_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
277 { WinOtherOrganizationSid, Other_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
278 { WinBuiltinPerfMonitoringUsersSid, Performance_Monitor_Users, BUILTIN, SidTypeAlias },
279 { WinBuiltinPerfLoggingUsersSid, Performance_Log_Users, BUILTIN, SidTypeAlias },
282 * ACE access rights
284 static const WCHAR SDDL_READ_CONTROL[] = {'R','C',0};
285 static const WCHAR SDDL_WRITE_DAC[] = {'W','D',0};
286 static const WCHAR SDDL_WRITE_OWNER[] = {'W','O',0};
287 static const WCHAR SDDL_STANDARD_DELETE[] = {'S','D',0};
289 static const WCHAR SDDL_READ_PROPERTY[] = {'R','P',0};
290 static const WCHAR SDDL_WRITE_PROPERTY[] = {'W','P',0};
291 static const WCHAR SDDL_CREATE_CHILD[] = {'C','C',0};
292 static const WCHAR SDDL_DELETE_CHILD[] = {'D','C',0};
293 static const WCHAR SDDL_LIST_CHILDREN[] = {'L','C',0};
294 static const WCHAR SDDL_SELF_WRITE[] = {'S','W',0};
295 static const WCHAR SDDL_LIST_OBJECT[] = {'L','O',0};
296 static const WCHAR SDDL_DELETE_TREE[] = {'D','T',0};
297 static const WCHAR SDDL_CONTROL_ACCESS[] = {'C','R',0};
299 static const WCHAR SDDL_FILE_ALL[] = {'F','A',0};
300 static const WCHAR SDDL_FILE_READ[] = {'F','R',0};
301 static const WCHAR SDDL_FILE_WRITE[] = {'F','W',0};
302 static const WCHAR SDDL_FILE_EXECUTE[] = {'F','X',0};
304 static const WCHAR SDDL_KEY_ALL[] = {'K','A',0};
305 static const WCHAR SDDL_KEY_READ[] = {'K','R',0};
306 static const WCHAR SDDL_KEY_WRITE[] = {'K','W',0};
307 static const WCHAR SDDL_KEY_EXECUTE[] = {'K','X',0};
309 static const WCHAR SDDL_GENERIC_ALL[] = {'G','A',0};
310 static const WCHAR SDDL_GENERIC_READ[] = {'G','R',0};
311 static const WCHAR SDDL_GENERIC_WRITE[] = {'G','W',0};
312 static const WCHAR SDDL_GENERIC_EXECUTE[] = {'G','X',0};
314 static const WCHAR SDDL_NO_READ_UP[] = {'N','R',0};
315 static const WCHAR SDDL_NO_WRITE_UP[] = {'N','W',0};
316 static const WCHAR SDDL_NO_EXECUTE_UP[] = {'N','X',0};
319 * ACL flags
321 static const WCHAR SDDL_PROTECTED[] = {'P',0};
322 static const WCHAR SDDL_AUTO_INHERIT_REQ[] = {'A','R',0};
323 static const WCHAR SDDL_AUTO_INHERITED[] = {'A','I',0};
326 * ACE types
328 static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0};
329 static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0};
330 static const WCHAR SDDL_AUDIT[] = {'A','U',0};
331 static const WCHAR SDDL_ALARM[] = {'A','L',0};
332 static const WCHAR SDDL_MANDATORY_LABEL[] = {'M','L',0};
335 * ACE flags
337 static const WCHAR SDDL_CONTAINER_INHERIT[] = {'C','I',0};
338 static const WCHAR SDDL_OBJECT_INHERIT[] = {'O','I',0};
339 static const WCHAR SDDL_NO_PROPAGATE[] = {'N','P',0};
340 static const WCHAR SDDL_INHERIT_ONLY[] = {'I','O',0};
341 static const WCHAR SDDL_INHERITED[] = {'I','D',0};
342 static const WCHAR SDDL_AUDIT_SUCCESS[] = {'S','A',0};
343 static const WCHAR SDDL_AUDIT_FAILURE[] = {'F','A',0};
345 const char * debugstr_sid(PSID sid)
347 int auth = 0;
348 SID * psid = sid;
350 if (psid == NULL)
351 return "(null)";
353 auth = psid->IdentifierAuthority.Value[5] +
354 (psid->IdentifierAuthority.Value[4] << 8) +
355 (psid->IdentifierAuthority.Value[3] << 16) +
356 (psid->IdentifierAuthority.Value[2] << 24);
358 switch (psid->SubAuthorityCount) {
359 case 0:
360 return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
361 case 1:
362 return wine_dbg_sprintf("S-%d-%d-%u", psid->Revision, auth,
363 psid->SubAuthority[0]);
364 case 2:
365 return wine_dbg_sprintf("S-%d-%d-%u-%u", psid->Revision, auth,
366 psid->SubAuthority[0], psid->SubAuthority[1]);
367 case 3:
368 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u", psid->Revision, auth,
369 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
370 case 4:
371 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u", psid->Revision, auth,
372 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
373 psid->SubAuthority[3]);
374 case 5:
375 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u", psid->Revision, auth,
376 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
377 psid->SubAuthority[3], psid->SubAuthority[4]);
378 case 6:
379 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
380 psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
381 psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
382 case 7:
383 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
384 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
385 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
386 psid->SubAuthority[6]);
387 case 8:
388 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
389 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
390 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
391 psid->SubAuthority[6], psid->SubAuthority[7]);
393 return "(too-big)";
396 /* set last error code from NT status and get the proper boolean return value */
397 /* used for functions that are a simple wrapper around the corresponding ntdll API */
398 static inline BOOL set_ntstatus( NTSTATUS status )
400 if (status) SetLastError( RtlNtStatusToDosError( status ));
401 return !status;
404 /* helper function for SE_FILE_OBJECT objects in [Get|Set]NamedSecurityInfo */
405 static inline DWORD get_security_file( LPCWSTR full_file_name, DWORD access, HANDLE *file )
407 UNICODE_STRING file_nameW;
408 OBJECT_ATTRIBUTES attr;
409 IO_STATUS_BLOCK io;
410 NTSTATUS status;
412 if (!RtlDosPathNameToNtPathName_U( full_file_name, &file_nameW, NULL, NULL ))
413 return ERROR_PATH_NOT_FOUND;
414 attr.Length = sizeof(attr);
415 attr.RootDirectory = 0;
416 attr.Attributes = OBJ_CASE_INSENSITIVE;
417 attr.ObjectName = &file_nameW;
418 attr.SecurityDescriptor = NULL;
419 status = NtCreateFile( file, access, &attr, &io, NULL, FILE_FLAG_BACKUP_SEMANTICS,
420 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
421 FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 );
422 RtlFreeUnicodeString( &file_nameW );
423 return RtlNtStatusToDosError( status );
426 /* helper function for SE_SERVICE objects in [Get|Set]NamedSecurityInfo */
427 static inline DWORD get_security_service( LPWSTR full_service_name, DWORD access, HANDLE *service )
429 SC_HANDLE manager = 0;
430 DWORD err;
432 err = SERV_OpenSCManagerW( NULL, NULL, access, (SC_HANDLE *)&manager );
433 if (err == ERROR_SUCCESS)
435 err = SERV_OpenServiceW( manager, full_service_name, access, (SC_HANDLE *)service );
436 CloseServiceHandle( manager );
438 return err;
441 /* helper function for SE_REGISTRY_KEY objects in [Get|Set]NamedSecurityInfo */
442 static inline DWORD get_security_regkey( LPWSTR full_key_name, DWORD access, HANDLE *key )
444 WCHAR classes_rootW[] = {'C','L','A','S','S','E','S','_','R','O','O','T',0};
445 WCHAR current_userW[] = {'C','U','R','R','E','N','T','_','U','S','E','R',0};
446 WCHAR machineW[] = {'M','A','C','H','I','N','E',0};
447 WCHAR usersW[] = {'U','S','E','R','S',0};
448 LPWSTR p = strchrW(full_key_name, '\\');
449 int len = p-full_key_name;
450 HKEY hParent;
452 if (!p) return ERROR_INVALID_PARAMETER;
453 if (strncmpW( full_key_name, classes_rootW, len ) == 0)
454 hParent = HKEY_CLASSES_ROOT;
455 else if (strncmpW( full_key_name, current_userW, len ) == 0)
456 hParent = HKEY_CURRENT_USER;
457 else if (strncmpW( full_key_name, machineW, len ) == 0)
458 hParent = HKEY_LOCAL_MACHINE;
459 else if (strncmpW( full_key_name, usersW, len ) == 0)
460 hParent = HKEY_USERS;
461 else
462 return ERROR_INVALID_PARAMETER;
463 return RegOpenKeyExW( hParent, p+1, 0, access, (HKEY *)key );
466 #define WINE_SIZE_OF_WORLD_ACCESS_ACL (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD))
468 static void GetWorldAccessACL(PACL pACL)
470 PACCESS_ALLOWED_ACE pACE = (PACCESS_ALLOWED_ACE) (pACL + 1);
472 pACL->AclRevision = ACL_REVISION;
473 pACL->Sbz1 = 0;
474 pACL->AclSize = WINE_SIZE_OF_WORLD_ACCESS_ACL;
475 pACL->AceCount = 1;
476 pACL->Sbz2 = 0;
478 pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
479 pACE->Header.AceFlags = CONTAINER_INHERIT_ACE;
480 pACE->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD);
481 pACE->Mask = 0xf3ffffff; /* Everything except reserved bits */
482 memcpy(&pACE->SidStart, &sidWorld, sizeof(sidWorld));
485 /************************************************************
486 * ADVAPI_IsLocalComputer
488 * Checks whether the server name indicates local machine.
490 BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName)
492 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
493 BOOL Result;
494 LPWSTR buf;
496 if (!ServerName || !ServerName[0])
497 return TRUE;
499 buf = heap_alloc(dwSize * sizeof(WCHAR));
500 Result = GetComputerNameW(buf, &dwSize);
501 if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
502 ServerName += 2;
503 Result = Result && !lstrcmpW(ServerName, buf);
504 heap_free(buf);
506 return Result;
509 /************************************************************
510 * ADVAPI_GetComputerSid
512 BOOL ADVAPI_GetComputerSid(PSID sid)
514 static const struct /* same fields as struct SID */
516 BYTE Revision;
517 BYTE SubAuthorityCount;
518 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
519 DWORD SubAuthority[4];
520 } computer_sid =
521 { SID_REVISION, 4, { SECURITY_NT_AUTHORITY }, { SECURITY_NT_NON_UNIQUE, 0, 0, 0 } };
523 memcpy( sid, &computer_sid, sizeof(computer_sid) );
524 return TRUE;
527 /* ##############################
528 ###### TOKEN FUNCTIONS ######
529 ##############################
532 /******************************************************************************
533 * OpenProcessToken [ADVAPI32.@]
534 * Opens the access token associated with a process handle.
536 * PARAMS
537 * ProcessHandle [I] Handle to process
538 * DesiredAccess [I] Desired access to process
539 * TokenHandle [O] Pointer to handle of open access token
541 * RETURNS
542 * Success: TRUE. TokenHandle contains the access token.
543 * Failure: FALSE.
545 * NOTES
546 * See NtOpenProcessToken.
548 BOOL WINAPI
549 OpenProcessToken( HANDLE ProcessHandle, DWORD DesiredAccess,
550 HANDLE *TokenHandle )
552 return set_ntstatus(NtOpenProcessToken( ProcessHandle, DesiredAccess, TokenHandle ));
555 /******************************************************************************
556 * OpenThreadToken [ADVAPI32.@]
558 * Opens the access token associated with a thread handle.
560 * PARAMS
561 * ThreadHandle [I] Handle to process
562 * DesiredAccess [I] Desired access to the thread
563 * OpenAsSelf [I] ???
564 * TokenHandle [O] Destination for the token handle
566 * RETURNS
567 * Success: TRUE. TokenHandle contains the access token.
568 * Failure: FALSE.
570 * NOTES
571 * See NtOpenThreadToken.
573 BOOL WINAPI
574 OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess,
575 BOOL OpenAsSelf, HANDLE *TokenHandle)
577 return set_ntstatus( NtOpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle));
580 BOOL WINAPI
581 AdjustTokenGroups( HANDLE TokenHandle, BOOL ResetToDefault, PTOKEN_GROUPS NewState,
582 DWORD BufferLength, PTOKEN_GROUPS PreviousState, PDWORD ReturnLength )
584 return set_ntstatus( NtAdjustGroupsToken(TokenHandle, ResetToDefault, NewState, BufferLength,
585 PreviousState, ReturnLength));
588 /******************************************************************************
589 * AdjustTokenPrivileges [ADVAPI32.@]
591 * Adjust the privileges of an open token handle.
593 * PARAMS
594 * TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
595 * DisableAllPrivileges [I] TRUE=Remove all privileges, FALSE=Use NewState
596 * NewState [I] Desired new privileges of the token
597 * BufferLength [I] Length of NewState
598 * PreviousState [O] Destination for the previous state
599 * ReturnLength [I/O] Size of PreviousState
602 * RETURNS
603 * Success: TRUE. Privileges are set to NewState and PreviousState is updated.
604 * Failure: FALSE.
606 * NOTES
607 * See NtAdjustPrivilegesToken.
609 BOOL WINAPI
610 AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges,
611 PTOKEN_PRIVILEGES NewState, DWORD BufferLength,
612 PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength )
614 NTSTATUS status;
616 TRACE("(%p %d %p %d %p %p)\n", TokenHandle, DisableAllPrivileges, NewState, BufferLength,
617 PreviousState, ReturnLength);
619 status = NtAdjustPrivilegesToken(TokenHandle, DisableAllPrivileges,
620 NewState, BufferLength, PreviousState,
621 ReturnLength);
622 SetLastError( RtlNtStatusToDosError( status ));
623 if ((status == STATUS_SUCCESS) || (status == STATUS_NOT_ALL_ASSIGNED))
624 return TRUE;
625 else
626 return FALSE;
629 /******************************************************************************
630 * CheckTokenMembership [ADVAPI32.@]
632 * Determine if an access token is a member of a SID.
634 * PARAMS
635 * TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
636 * SidToCheck [I] SID that possibly contains the token
637 * IsMember [O] Destination for result.
639 * RETURNS
640 * Success: TRUE. IsMember is TRUE if TokenHandle is a member, FALSE otherwise.
641 * Failure: FALSE.
643 BOOL WINAPI
644 CheckTokenMembership( HANDLE token, PSID sid_to_check,
645 PBOOL is_member )
647 PTOKEN_GROUPS token_groups = NULL;
648 HANDLE thread_token = NULL;
649 DWORD size, i;
650 BOOL ret;
652 TRACE("(%p %s %p)\n", token, debugstr_sid(sid_to_check), is_member);
654 *is_member = FALSE;
656 if (!token)
658 if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &thread_token))
660 HANDLE process_token;
661 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &process_token);
662 if (!ret)
663 goto exit;
664 ret = DuplicateTokenEx(process_token, TOKEN_QUERY,
665 NULL, SecurityImpersonation, TokenImpersonation,
666 &thread_token);
667 CloseHandle(process_token);
668 if (!ret)
669 goto exit;
671 token = thread_token;
673 else
675 TOKEN_TYPE type;
677 ret = GetTokenInformation(token, TokenType, &type, sizeof(TOKEN_TYPE), &size);
678 if (!ret) goto exit;
680 if (type == TokenPrimary)
682 SetLastError(ERROR_NO_IMPERSONATION_TOKEN);
683 return FALSE;
687 ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
688 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
689 goto exit;
691 token_groups = heap_alloc(size);
692 if (!token_groups)
694 ret = FALSE;
695 goto exit;
698 ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
699 if (!ret)
700 goto exit;
702 for (i = 0; i < token_groups->GroupCount; i++)
704 TRACE("Groups[%d]: {0x%x, %s}\n", i,
705 token_groups->Groups[i].Attributes,
706 debugstr_sid(token_groups->Groups[i].Sid));
707 if ((token_groups->Groups[i].Attributes & SE_GROUP_ENABLED) &&
708 EqualSid(sid_to_check, token_groups->Groups[i].Sid))
710 *is_member = TRUE;
711 TRACE("sid enabled and found in token\n");
712 break;
716 exit:
717 heap_free(token_groups);
718 if (thread_token != NULL) CloseHandle(thread_token);
720 return ret;
723 /******************************************************************************
724 * GetTokenInformation [ADVAPI32.@]
726 * Get a type of information about an access token.
728 * PARAMS
729 * token [I] Handle from OpenProcessToken() or OpenThreadToken()
730 * tokeninfoclass [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
731 * tokeninfo [O] Destination for token information
732 * tokeninfolength [I] Length of tokeninfo
733 * retlen [O] Destination for returned token information length
735 * RETURNS
736 * Success: TRUE. tokeninfo contains retlen bytes of token information
737 * Failure: FALSE.
739 * NOTES
740 * See NtQueryInformationToken.
742 BOOL WINAPI
743 GetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
744 LPVOID tokeninfo, DWORD tokeninfolength, LPDWORD retlen )
746 TRACE("(%p, %s, %p, %d, %p):\n",
747 token,
748 (tokeninfoclass == TokenUser) ? "TokenUser" :
749 (tokeninfoclass == TokenGroups) ? "TokenGroups" :
750 (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
751 (tokeninfoclass == TokenOwner) ? "TokenOwner" :
752 (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
753 (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
754 (tokeninfoclass == TokenSource) ? "TokenSource" :
755 (tokeninfoclass == TokenType) ? "TokenType" :
756 (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
757 (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
758 (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
759 (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
760 (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
761 (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
762 (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
763 "Unknown",
764 tokeninfo, tokeninfolength, retlen);
765 return set_ntstatus( NtQueryInformationToken( token, tokeninfoclass, tokeninfo,
766 tokeninfolength, retlen));
769 /******************************************************************************
770 * SetTokenInformation [ADVAPI32.@]
772 * Set information for an access token.
774 * PARAMS
775 * token [I] Handle from OpenProcessToken() or OpenThreadToken()
776 * tokeninfoclass [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
777 * tokeninfo [I] Token information to set
778 * tokeninfolength [I] Length of tokeninfo
780 * RETURNS
781 * Success: TRUE. The information for the token is set to tokeninfo.
782 * Failure: FALSE.
784 BOOL WINAPI
785 SetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
786 LPVOID tokeninfo, DWORD tokeninfolength )
788 TRACE("(%p, %s, %p, %d): stub\n",
789 token,
790 (tokeninfoclass == TokenUser) ? "TokenUser" :
791 (tokeninfoclass == TokenGroups) ? "TokenGroups" :
792 (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
793 (tokeninfoclass == TokenOwner) ? "TokenOwner" :
794 (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
795 (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
796 (tokeninfoclass == TokenSource) ? "TokenSource" :
797 (tokeninfoclass == TokenType) ? "TokenType" :
798 (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
799 (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
800 (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
801 (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
802 (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
803 (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
804 (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
805 "Unknown",
806 tokeninfo, tokeninfolength);
808 return set_ntstatus( NtSetInformationToken( token, tokeninfoclass, tokeninfo, tokeninfolength ));
811 /*************************************************************************
812 * SetThreadToken [ADVAPI32.@]
814 * Assigns an 'impersonation token' to a thread so it can assume the
815 * security privileges of another thread or process. Can also remove
816 * a previously assigned token.
818 * PARAMS
819 * thread [O] Handle to thread to set the token for
820 * token [I] Token to set
822 * RETURNS
823 * Success: TRUE. The threads access token is set to token
824 * Failure: FALSE.
826 * NOTES
827 * Only supported on NT or higher. On Win9X this function does nothing.
828 * See SetTokenInformation.
830 BOOL WINAPI SetThreadToken(PHANDLE thread, HANDLE token)
832 return set_ntstatus( NtSetInformationThread( thread ? *thread : GetCurrentThread(),
833 ThreadImpersonationToken, &token, sizeof token ));
836 /*************************************************************************
837 * CreateRestrictedToken [ADVAPI32.@]
839 * Create a new more restricted token from an existing token.
841 * PARAMS
842 * baseToken [I] Token to base the new restricted token on
843 * flags [I] Options
844 * nDisableSids [I] Length of disableSids array
845 * disableSids [I] Array of SIDs to disable in the new token
846 * nDeletePrivs [I] Length of deletePrivs array
847 * deletePrivs [I] Array of privileges to delete in the new token
848 * nRestrictSids [I] Length of restrictSids array
849 * restrictSids [I] Array of SIDs to restrict in the new token
850 * newToken [O] Address where the new token is stored
852 * RETURNS
853 * Success: TRUE
854 * Failure: FALSE
856 BOOL WINAPI CreateRestrictedToken(
857 HANDLE baseToken,
858 DWORD flags,
859 DWORD nDisableSids,
860 PSID_AND_ATTRIBUTES disableSids,
861 DWORD nDeletePrivs,
862 PLUID_AND_ATTRIBUTES deletePrivs,
863 DWORD nRestrictSids,
864 PSID_AND_ATTRIBUTES restrictSids,
865 PHANDLE newToken)
867 TOKEN_TYPE type;
868 SECURITY_IMPERSONATION_LEVEL level = TokenImpersonationLevel;
869 DWORD size;
871 FIXME("(%p, 0x%x, %u, %p, %u, %p, %u, %p, %p): stub\n",
872 baseToken, flags, nDisableSids, disableSids,
873 nDeletePrivs, deletePrivs,
874 nRestrictSids, restrictSids,
875 newToken);
877 size = sizeof(type);
878 if (!GetTokenInformation( baseToken, TokenType, &type, size, &size )) return FALSE;
879 if (type == TokenImpersonation)
881 size = sizeof(level);
882 if (!GetTokenInformation( baseToken, TokenImpersonationLevel, &level, size, &size ))
883 return FALSE;
885 return DuplicateTokenEx( baseToken, MAXIMUM_ALLOWED, NULL, level, type, newToken );
888 /* ##############################
889 ###### SID FUNCTIONS ######
890 ##############################
893 /******************************************************************************
894 * AllocateAndInitializeSid [ADVAPI32.@]
896 * PARAMS
897 * pIdentifierAuthority []
898 * nSubAuthorityCount []
899 * nSubAuthority0 []
900 * nSubAuthority1 []
901 * nSubAuthority2 []
902 * nSubAuthority3 []
903 * nSubAuthority4 []
904 * nSubAuthority5 []
905 * nSubAuthority6 []
906 * nSubAuthority7 []
907 * pSid []
909 BOOL WINAPI
910 AllocateAndInitializeSid( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
911 BYTE nSubAuthorityCount,
912 DWORD nSubAuthority0, DWORD nSubAuthority1,
913 DWORD nSubAuthority2, DWORD nSubAuthority3,
914 DWORD nSubAuthority4, DWORD nSubAuthority5,
915 DWORD nSubAuthority6, DWORD nSubAuthority7,
916 PSID *pSid )
918 return set_ntstatus( RtlAllocateAndInitializeSid(
919 pIdentifierAuthority, nSubAuthorityCount,
920 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
921 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7,
922 pSid ));
925 /******************************************************************************
926 * FreeSid [ADVAPI32.@]
928 * PARAMS
929 * pSid []
931 PVOID WINAPI
932 FreeSid( PSID pSid )
934 RtlFreeSid(pSid);
935 return NULL; /* is documented like this */
938 /******************************************************************************
939 * CopySid [ADVAPI32.@]
941 * PARAMS
942 * nDestinationSidLength []
943 * pDestinationSid []
944 * pSourceSid []
946 BOOL WINAPI
947 CopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
949 return RtlCopySid(nDestinationSidLength, pDestinationSid, pSourceSid);
952 /******************************************************************************
953 * CreateWellKnownSid [ADVAPI32.@]
955 BOOL WINAPI
956 CreateWellKnownSid( WELL_KNOWN_SID_TYPE WellKnownSidType,
957 PSID DomainSid,
958 PSID pSid,
959 DWORD* cbSid)
961 unsigned int i;
962 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
964 if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
966 SetLastError(ERROR_INVALID_PARAMETER);
967 return FALSE;
970 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
971 if (WellKnownSids[i].Type == WellKnownSidType) {
972 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
974 if (*cbSid < length)
976 *cbSid = length;
977 SetLastError(ERROR_INSUFFICIENT_BUFFER);
978 return FALSE;
980 if (!pSid)
982 SetLastError(ERROR_INVALID_PARAMETER);
983 return FALSE;
985 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
986 *cbSid = length;
987 return TRUE;
991 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
993 SetLastError(ERROR_INVALID_PARAMETER);
994 return FALSE;
997 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
998 if (WellKnownRids[i].Type == WellKnownSidType) {
999 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
1000 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
1001 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
1003 if (*cbSid < output_sid_length)
1005 *cbSid = output_sid_length;
1006 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1007 return FALSE;
1009 if (!pSid)
1011 SetLastError(ERROR_INVALID_PARAMETER);
1012 return FALSE;
1014 CopyMemory(pSid, DomainSid, domain_sid_length);
1015 (*GetSidSubAuthorityCount(pSid))++;
1016 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
1017 *cbSid = output_sid_length;
1018 return TRUE;
1021 SetLastError(ERROR_INVALID_PARAMETER);
1022 return FALSE;
1025 /******************************************************************************
1026 * IsWellKnownSid [ADVAPI32.@]
1028 BOOL WINAPI
1029 IsWellKnownSid( PSID pSid, WELL_KNOWN_SID_TYPE WellKnownSidType )
1031 unsigned int i;
1032 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
1034 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
1035 if (WellKnownSids[i].Type == WellKnownSidType)
1036 if (EqualSid(pSid, (PSID)&(WellKnownSids[i].Sid.Revision)))
1037 return TRUE;
1039 return FALSE;
1042 BOOL WINAPI
1043 IsTokenRestricted( HANDLE TokenHandle )
1045 TOKEN_GROUPS *groups;
1046 DWORD size;
1047 NTSTATUS status;
1048 BOOL restricted;
1050 TRACE("(%p)\n", TokenHandle);
1052 status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, NULL, 0, &size);
1053 if (status != STATUS_BUFFER_TOO_SMALL)
1054 return FALSE;
1056 groups = heap_alloc(size);
1057 if (!groups)
1059 SetLastError(ERROR_OUTOFMEMORY);
1060 return FALSE;
1063 status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, groups, size, &size);
1064 if (status != STATUS_SUCCESS)
1066 heap_free(groups);
1067 return set_ntstatus(status);
1070 restricted = groups->GroupCount > 0;
1071 heap_free(groups);
1073 return restricted;
1076 /******************************************************************************
1077 * IsValidSid [ADVAPI32.@]
1079 * PARAMS
1080 * pSid []
1082 BOOL WINAPI
1083 IsValidSid( PSID pSid )
1085 return RtlValidSid( pSid );
1088 /******************************************************************************
1089 * EqualSid [ADVAPI32.@]
1091 * PARAMS
1092 * pSid1 []
1093 * pSid2 []
1095 BOOL WINAPI
1096 EqualSid( PSID pSid1, PSID pSid2 )
1098 BOOL ret = RtlEqualSid( pSid1, pSid2 );
1099 SetLastError(ERROR_SUCCESS);
1100 return ret;
1103 /******************************************************************************
1104 * EqualPrefixSid [ADVAPI32.@]
1106 BOOL WINAPI EqualPrefixSid (PSID pSid1, PSID pSid2)
1108 return RtlEqualPrefixSid(pSid1, pSid2);
1111 /******************************************************************************
1112 * GetSidLengthRequired [ADVAPI32.@]
1114 * PARAMS
1115 * nSubAuthorityCount []
1117 DWORD WINAPI
1118 GetSidLengthRequired( BYTE nSubAuthorityCount )
1120 return RtlLengthRequiredSid(nSubAuthorityCount);
1123 /******************************************************************************
1124 * InitializeSid [ADVAPI32.@]
1126 * PARAMS
1127 * pIdentifierAuthority []
1129 BOOL WINAPI
1130 InitializeSid (
1131 PSID pSid,
1132 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
1133 BYTE nSubAuthorityCount)
1135 return RtlInitializeSid(pSid, pIdentifierAuthority, nSubAuthorityCount);
1138 DWORD WINAPI
1139 GetEffectiveRightsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pAccessRights )
1141 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1143 *pAccessRights = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
1144 return 0;
1147 DWORD WINAPI
1148 GetEffectiveRightsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pAccessRights )
1150 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1152 return 1;
1155 /******************************************************************************
1156 * GetSidIdentifierAuthority [ADVAPI32.@]
1158 * PARAMS
1159 * pSid []
1161 PSID_IDENTIFIER_AUTHORITY WINAPI
1162 GetSidIdentifierAuthority( PSID pSid )
1164 return RtlIdentifierAuthoritySid(pSid);
1167 /******************************************************************************
1168 * GetSidSubAuthority [ADVAPI32.@]
1170 * PARAMS
1171 * pSid []
1172 * nSubAuthority []
1174 PDWORD WINAPI
1175 GetSidSubAuthority( PSID pSid, DWORD nSubAuthority )
1177 SetLastError(ERROR_SUCCESS);
1178 return RtlSubAuthoritySid(pSid, nSubAuthority);
1181 /******************************************************************************
1182 * GetSidSubAuthorityCount [ADVAPI32.@]
1184 * PARAMS
1185 * pSid []
1187 PUCHAR WINAPI
1188 GetSidSubAuthorityCount (PSID pSid)
1190 SetLastError(ERROR_SUCCESS);
1191 return RtlSubAuthorityCountSid(pSid);
1194 /******************************************************************************
1195 * GetLengthSid [ADVAPI32.@]
1197 * PARAMS
1198 * pSid []
1200 DWORD WINAPI
1201 GetLengthSid (PSID pSid)
1203 return RtlLengthSid(pSid);
1206 /* ##############################################
1207 ###### SECURITY DESCRIPTOR FUNCTIONS ######
1208 ##############################################
1211 /******************************************************************************
1212 * BuildSecurityDescriptorA [ADVAPI32.@]
1214 * Builds a SD from
1216 * PARAMS
1217 * pOwner [I]
1218 * pGroup [I]
1219 * cCountOfAccessEntries [I]
1220 * pListOfAccessEntries [I]
1221 * cCountOfAuditEntries [I]
1222 * pListofAuditEntries [I]
1223 * pOldSD [I]
1224 * lpdwBufferLength [I/O]
1225 * pNewSD [O]
1227 * RETURNS
1228 * Success: ERROR_SUCCESS
1229 * Failure: nonzero error code from Winerror.h
1231 DWORD WINAPI BuildSecurityDescriptorA(
1232 IN PTRUSTEEA pOwner,
1233 IN PTRUSTEEA pGroup,
1234 IN ULONG cCountOfAccessEntries,
1235 IN PEXPLICIT_ACCESSA pListOfAccessEntries,
1236 IN ULONG cCountOfAuditEntries,
1237 IN PEXPLICIT_ACCESSA pListofAuditEntries,
1238 IN PSECURITY_DESCRIPTOR pOldSD,
1239 IN OUT PULONG lpdwBufferLength,
1240 OUT PSECURITY_DESCRIPTOR* pNewSD)
1242 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1243 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1244 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1246 return ERROR_CALL_NOT_IMPLEMENTED;
1249 /******************************************************************************
1250 * BuildSecurityDescriptorW [ADVAPI32.@]
1252 * See BuildSecurityDescriptorA.
1254 DWORD WINAPI BuildSecurityDescriptorW(
1255 IN PTRUSTEEW pOwner,
1256 IN PTRUSTEEW pGroup,
1257 IN ULONG cCountOfAccessEntries,
1258 IN PEXPLICIT_ACCESSW pListOfAccessEntries,
1259 IN ULONG cCountOfAuditEntries,
1260 IN PEXPLICIT_ACCESSW pListofAuditEntries,
1261 IN PSECURITY_DESCRIPTOR pOldSD,
1262 IN OUT PULONG lpdwBufferLength,
1263 OUT PSECURITY_DESCRIPTOR* pNewSD)
1265 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1266 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1267 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1269 return ERROR_CALL_NOT_IMPLEMENTED;
1272 /******************************************************************************
1273 * InitializeSecurityDescriptor [ADVAPI32.@]
1275 * PARAMS
1276 * pDescr []
1277 * revision []
1279 BOOL WINAPI
1280 InitializeSecurityDescriptor( PSECURITY_DESCRIPTOR pDescr, DWORD revision )
1282 return set_ntstatus( RtlCreateSecurityDescriptor(pDescr, revision ));
1286 /******************************************************************************
1287 * MakeAbsoluteSD [ADVAPI32.@]
1289 BOOL WINAPI MakeAbsoluteSD (
1290 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1291 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1292 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
1293 OUT PACL pDacl,
1294 OUT LPDWORD lpdwDaclSize,
1295 OUT PACL pSacl,
1296 OUT LPDWORD lpdwSaclSize,
1297 OUT PSID pOwner,
1298 OUT LPDWORD lpdwOwnerSize,
1299 OUT PSID pPrimaryGroup,
1300 OUT LPDWORD lpdwPrimaryGroupSize)
1302 return set_ntstatus( RtlSelfRelativeToAbsoluteSD(pSelfRelativeSecurityDescriptor,
1303 pAbsoluteSecurityDescriptor,
1304 lpdwAbsoluteSecurityDescriptorSize,
1305 pDacl, lpdwDaclSize, pSacl, lpdwSaclSize,
1306 pOwner, lpdwOwnerSize,
1307 pPrimaryGroup, lpdwPrimaryGroupSize));
1310 /******************************************************************************
1311 * GetKernelObjectSecurity [ADVAPI32.@]
1313 BOOL WINAPI GetKernelObjectSecurity(
1314 HANDLE Handle,
1315 SECURITY_INFORMATION RequestedInformation,
1316 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1317 DWORD nLength,
1318 LPDWORD lpnLengthNeeded )
1320 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", Handle, RequestedInformation,
1321 pSecurityDescriptor, nLength, lpnLengthNeeded);
1323 return set_ntstatus( NtQuerySecurityObject(Handle, RequestedInformation, pSecurityDescriptor,
1324 nLength, lpnLengthNeeded ));
1327 /******************************************************************************
1328 * GetPrivateObjectSecurity [ADVAPI32.@]
1330 BOOL WINAPI GetPrivateObjectSecurity(
1331 PSECURITY_DESCRIPTOR ObjectDescriptor,
1332 SECURITY_INFORMATION SecurityInformation,
1333 PSECURITY_DESCRIPTOR ResultantDescriptor,
1334 DWORD DescriptorLength,
1335 PDWORD ReturnLength )
1337 SECURITY_DESCRIPTOR desc;
1338 BOOL defaulted, present;
1339 PACL pacl;
1340 PSID psid;
1342 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", ObjectDescriptor, SecurityInformation,
1343 ResultantDescriptor, DescriptorLength, ReturnLength);
1345 if (!InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION))
1346 return FALSE;
1348 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1350 if (!GetSecurityDescriptorOwner(ObjectDescriptor, &psid, &defaulted))
1351 return FALSE;
1352 SetSecurityDescriptorOwner(&desc, psid, defaulted);
1355 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1357 if (!GetSecurityDescriptorGroup(ObjectDescriptor, &psid, &defaulted))
1358 return FALSE;
1359 SetSecurityDescriptorGroup(&desc, psid, defaulted);
1362 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1364 if (!GetSecurityDescriptorDacl(ObjectDescriptor, &present, &pacl, &defaulted))
1365 return FALSE;
1366 SetSecurityDescriptorDacl(&desc, present, pacl, defaulted);
1369 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1371 if (!GetSecurityDescriptorSacl(ObjectDescriptor, &present, &pacl, &defaulted))
1372 return FALSE;
1373 SetSecurityDescriptorSacl(&desc, present, pacl, defaulted);
1376 *ReturnLength = DescriptorLength;
1377 return MakeSelfRelativeSD(&desc, ResultantDescriptor, ReturnLength);
1380 /******************************************************************************
1381 * GetSecurityDescriptorLength [ADVAPI32.@]
1383 DWORD WINAPI GetSecurityDescriptorLength( PSECURITY_DESCRIPTOR pDescr)
1385 return RtlLengthSecurityDescriptor(pDescr);
1388 /******************************************************************************
1389 * GetSecurityDescriptorOwner [ADVAPI32.@]
1391 * PARAMS
1392 * pOwner []
1393 * lpbOwnerDefaulted []
1395 BOOL WINAPI
1396 GetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pDescr, PSID *pOwner,
1397 LPBOOL lpbOwnerDefaulted )
1399 BOOLEAN defaulted;
1400 BOOL ret = set_ntstatus( RtlGetOwnerSecurityDescriptor( pDescr, pOwner, &defaulted ));
1401 *lpbOwnerDefaulted = defaulted;
1402 return ret;
1405 /******************************************************************************
1406 * SetSecurityDescriptorOwner [ADVAPI32.@]
1408 * PARAMS
1410 BOOL WINAPI SetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1411 PSID pOwner, BOOL bOwnerDefaulted)
1413 return set_ntstatus( RtlSetOwnerSecurityDescriptor(pSecurityDescriptor, pOwner, bOwnerDefaulted));
1415 /******************************************************************************
1416 * GetSecurityDescriptorGroup [ADVAPI32.@]
1418 BOOL WINAPI GetSecurityDescriptorGroup(
1419 PSECURITY_DESCRIPTOR SecurityDescriptor,
1420 PSID *Group,
1421 LPBOOL GroupDefaulted)
1423 BOOLEAN defaulted;
1424 BOOL ret = set_ntstatus( RtlGetGroupSecurityDescriptor(SecurityDescriptor, Group, &defaulted ));
1425 *GroupDefaulted = defaulted;
1426 return ret;
1428 /******************************************************************************
1429 * SetSecurityDescriptorGroup [ADVAPI32.@]
1431 BOOL WINAPI SetSecurityDescriptorGroup ( PSECURITY_DESCRIPTOR SecurityDescriptor,
1432 PSID Group, BOOL GroupDefaulted)
1434 return set_ntstatus( RtlSetGroupSecurityDescriptor( SecurityDescriptor, Group, GroupDefaulted));
1437 /******************************************************************************
1438 * IsValidSecurityDescriptor [ADVAPI32.@]
1440 * PARAMS
1441 * lpsecdesc []
1443 BOOL WINAPI
1444 IsValidSecurityDescriptor( PSECURITY_DESCRIPTOR SecurityDescriptor )
1446 return set_ntstatus( RtlValidSecurityDescriptor(SecurityDescriptor));
1449 /******************************************************************************
1450 * GetSecurityDescriptorDacl [ADVAPI32.@]
1452 BOOL WINAPI GetSecurityDescriptorDacl(
1453 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1454 OUT LPBOOL lpbDaclPresent,
1455 OUT PACL *pDacl,
1456 OUT LPBOOL lpbDaclDefaulted)
1458 BOOLEAN present, defaulted;
1459 BOOL ret = set_ntstatus( RtlGetDaclSecurityDescriptor(pSecurityDescriptor, &present, pDacl, &defaulted));
1460 *lpbDaclPresent = present;
1461 *lpbDaclDefaulted = defaulted;
1462 return ret;
1465 /******************************************************************************
1466 * SetSecurityDescriptorDacl [ADVAPI32.@]
1468 BOOL WINAPI
1469 SetSecurityDescriptorDacl (
1470 PSECURITY_DESCRIPTOR lpsd,
1471 BOOL daclpresent,
1472 PACL dacl,
1473 BOOL dacldefaulted )
1475 return set_ntstatus( RtlSetDaclSecurityDescriptor (lpsd, daclpresent, dacl, dacldefaulted ) );
1477 /******************************************************************************
1478 * GetSecurityDescriptorSacl [ADVAPI32.@]
1480 BOOL WINAPI GetSecurityDescriptorSacl(
1481 IN PSECURITY_DESCRIPTOR lpsd,
1482 OUT LPBOOL lpbSaclPresent,
1483 OUT PACL *pSacl,
1484 OUT LPBOOL lpbSaclDefaulted)
1486 BOOLEAN present, defaulted;
1487 BOOL ret = set_ntstatus( RtlGetSaclSecurityDescriptor(lpsd, &present, pSacl, &defaulted) );
1488 *lpbSaclPresent = present;
1489 *lpbSaclDefaulted = defaulted;
1490 return ret;
1493 /**************************************************************************
1494 * SetSecurityDescriptorSacl [ADVAPI32.@]
1496 BOOL WINAPI SetSecurityDescriptorSacl (
1497 PSECURITY_DESCRIPTOR lpsd,
1498 BOOL saclpresent,
1499 PACL lpsacl,
1500 BOOL sacldefaulted)
1502 return set_ntstatus (RtlSetSaclSecurityDescriptor(lpsd, saclpresent, lpsacl, sacldefaulted));
1504 /******************************************************************************
1505 * MakeSelfRelativeSD [ADVAPI32.@]
1507 * PARAMS
1508 * lpabssecdesc []
1509 * lpselfsecdesc []
1510 * lpbuflen []
1512 BOOL WINAPI
1513 MakeSelfRelativeSD(
1514 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1515 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1516 IN OUT LPDWORD lpdwBufferLength)
1518 return set_ntstatus( RtlMakeSelfRelativeSD( pAbsoluteSecurityDescriptor,
1519 pSelfRelativeSecurityDescriptor, lpdwBufferLength));
1522 /******************************************************************************
1523 * GetSecurityDescriptorControl [ADVAPI32.@]
1526 BOOL WINAPI GetSecurityDescriptorControl ( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1527 PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD lpdwRevision)
1529 return set_ntstatus( RtlGetControlSecurityDescriptor(pSecurityDescriptor,pControl,lpdwRevision));
1532 /******************************************************************************
1533 * SetSecurityDescriptorControl [ADVAPI32.@]
1535 BOOL WINAPI SetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1536 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1537 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet )
1539 return set_ntstatus( RtlSetControlSecurityDescriptor(
1540 pSecurityDescriptor, ControlBitsOfInterest, ControlBitsToSet ) );
1543 /******************************************************************************
1544 * GetWindowsAccountDomainSid [ADVAPI32.@]
1546 BOOL WINAPI GetWindowsAccountDomainSid( PSID sid, PSID domain_sid, DWORD *size )
1548 SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY };
1549 DWORD required_size;
1550 int i;
1552 FIXME( "(%p %p %p): semi-stub\n", sid, domain_sid, size );
1554 if (!sid || !IsValidSid( sid ))
1556 SetLastError( ERROR_INVALID_SID );
1557 return FALSE;
1560 if (!size)
1562 SetLastError( ERROR_INVALID_PARAMETER );
1563 return FALSE;
1566 if (*GetSidSubAuthorityCount( sid ) < 4)
1568 SetLastError( ERROR_INVALID_SID );
1569 return FALSE;
1572 required_size = GetSidLengthRequired( 4 );
1573 if (*size < required_size || !domain_sid)
1575 *size = required_size;
1576 SetLastError( domain_sid ? ERROR_INSUFFICIENT_BUFFER :
1577 ERROR_INVALID_PARAMETER );
1578 return FALSE;
1581 InitializeSid( domain_sid, &domain_ident, 4 );
1582 for (i = 0; i < 4; i++)
1583 *GetSidSubAuthority( domain_sid, i ) = *GetSidSubAuthority( sid, i );
1585 *size = required_size;
1586 return TRUE;
1589 /* ##############################
1590 ###### ACL FUNCTIONS ######
1591 ##############################
1594 /*************************************************************************
1595 * InitializeAcl [ADVAPI32.@]
1597 BOOL WINAPI InitializeAcl(PACL acl, DWORD size, DWORD rev)
1599 return set_ntstatus( RtlCreateAcl(acl, size, rev));
1602 BOOL WINAPI ImpersonateNamedPipeClient( HANDLE hNamedPipe )
1604 IO_STATUS_BLOCK io_block;
1606 TRACE("(%p)\n", hNamedPipe);
1608 return set_ntstatus( NtFsControlFile(hNamedPipe, NULL, NULL, NULL,
1609 &io_block, FSCTL_PIPE_IMPERSONATE, NULL, 0, NULL, 0) );
1612 /******************************************************************************
1613 * AddAccessAllowedAce [ADVAPI32.@]
1615 BOOL WINAPI AddAccessAllowedAce(
1616 IN OUT PACL pAcl,
1617 IN DWORD dwAceRevision,
1618 IN DWORD AccessMask,
1619 IN PSID pSid)
1621 return set_ntstatus(RtlAddAccessAllowedAce(pAcl, dwAceRevision, AccessMask, pSid));
1624 /******************************************************************************
1625 * AddAccessAllowedAceEx [ADVAPI32.@]
1627 BOOL WINAPI AddAccessAllowedAceEx(
1628 IN OUT PACL pAcl,
1629 IN DWORD dwAceRevision,
1630 IN DWORD AceFlags,
1631 IN DWORD AccessMask,
1632 IN PSID pSid)
1634 return set_ntstatus(RtlAddAccessAllowedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1637 /******************************************************************************
1638 * AddAccessDeniedAce [ADVAPI32.@]
1640 BOOL WINAPI AddAccessDeniedAce(
1641 IN OUT PACL pAcl,
1642 IN DWORD dwAceRevision,
1643 IN DWORD AccessMask,
1644 IN PSID pSid)
1646 return set_ntstatus(RtlAddAccessDeniedAce(pAcl, dwAceRevision, AccessMask, pSid));
1649 /******************************************************************************
1650 * AddAccessDeniedAceEx [ADVAPI32.@]
1652 BOOL WINAPI AddAccessDeniedAceEx(
1653 IN OUT PACL pAcl,
1654 IN DWORD dwAceRevision,
1655 IN DWORD AceFlags,
1656 IN DWORD AccessMask,
1657 IN PSID pSid)
1659 return set_ntstatus(RtlAddAccessDeniedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1662 /******************************************************************************
1663 * AddAce [ADVAPI32.@]
1665 BOOL WINAPI AddAce(
1666 IN OUT PACL pAcl,
1667 IN DWORD dwAceRevision,
1668 IN DWORD dwStartingAceIndex,
1669 LPVOID pAceList,
1670 DWORD nAceListLength)
1672 return set_ntstatus(RtlAddAce(pAcl, dwAceRevision, dwStartingAceIndex, pAceList, nAceListLength));
1675 BOOL WINAPI AddMandatoryAce(ACL *acl, DWORD ace_revision, DWORD ace_flags, DWORD mandatory_policy, PSID label_sid)
1677 FIXME("%p %x %x %x %p - stub\n", acl, ace_revision, ace_flags, mandatory_policy, label_sid);
1678 return FALSE;
1681 /******************************************************************************
1682 * DeleteAce [ADVAPI32.@]
1684 BOOL WINAPI DeleteAce(PACL pAcl, DWORD dwAceIndex)
1686 return set_ntstatus(RtlDeleteAce(pAcl, dwAceIndex));
1689 /******************************************************************************
1690 * FindFirstFreeAce [ADVAPI32.@]
1692 BOOL WINAPI FindFirstFreeAce(IN PACL pAcl, LPVOID * pAce)
1694 return RtlFirstFreeAce(pAcl, (PACE_HEADER *)pAce);
1697 /******************************************************************************
1698 * GetAce [ADVAPI32.@]
1700 BOOL WINAPI GetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1702 return set_ntstatus(RtlGetAce(pAcl, dwAceIndex, pAce));
1705 /******************************************************************************
1706 * GetAclInformation [ADVAPI32.@]
1708 BOOL WINAPI GetAclInformation(
1709 PACL pAcl,
1710 LPVOID pAclInformation,
1711 DWORD nAclInformationLength,
1712 ACL_INFORMATION_CLASS dwAclInformationClass)
1714 return set_ntstatus(RtlQueryInformationAcl(pAcl, pAclInformation,
1715 nAclInformationLength, dwAclInformationClass));
1718 /******************************************************************************
1719 * IsValidAcl [ADVAPI32.@]
1721 BOOL WINAPI IsValidAcl(IN PACL pAcl)
1723 return RtlValidAcl(pAcl);
1726 /* ##############################
1727 ###### MISC FUNCTIONS ######
1728 ##############################
1731 /******************************************************************************
1732 * AllocateLocallyUniqueId [ADVAPI32.@]
1734 * PARAMS
1735 * lpLuid []
1737 BOOL WINAPI AllocateLocallyUniqueId( PLUID lpLuid )
1739 return set_ntstatus(NtAllocateLocallyUniqueId(lpLuid));
1742 static const WCHAR SE_CREATE_TOKEN_NAME_W[] =
1743 { 'S','e','C','r','e','a','t','e','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 };
1744 static const WCHAR SE_ASSIGNPRIMARYTOKEN_NAME_W[] =
1745 { '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 };
1746 static const WCHAR SE_LOCK_MEMORY_NAME_W[] =
1747 { 'S','e','L','o','c','k','M','e','m','o','r','y','P','r','i','v','i','l','e','g','e',0 };
1748 static const WCHAR SE_INCREASE_QUOTA_NAME_W[] =
1749 { '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 };
1750 static const WCHAR SE_MACHINE_ACCOUNT_NAME_W[] =
1751 { '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 };
1752 static const WCHAR SE_TCB_NAME_W[] =
1753 { 'S','e','T','c','b','P','r','i','v','i','l','e','g','e',0 };
1754 static const WCHAR SE_SECURITY_NAME_W[] =
1755 { 'S','e','S','e','c','u','r','i','t','y','P','r','i','v','i','l','e','g','e',0 };
1756 static const WCHAR SE_TAKE_OWNERSHIP_NAME_W[] =
1757 { '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 };
1758 static const WCHAR SE_LOAD_DRIVER_NAME_W[] =
1759 { 'S','e','L','o','a','d','D','r','i','v','e','r','P','r','i','v','i','l','e','g','e',0 };
1760 static const WCHAR SE_SYSTEM_PROFILE_NAME_W[] =
1761 { '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 };
1762 static const WCHAR SE_SYSTEMTIME_NAME_W[] =
1763 { 'S','e','S','y','s','t','e','m','t','i','m','e','P','r','i','v','i','l','e','g','e',0 };
1764 static const WCHAR SE_PROF_SINGLE_PROCESS_NAME_W[] =
1765 { '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 };
1766 static const WCHAR SE_INC_BASE_PRIORITY_NAME_W[] =
1767 { '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 };
1768 static const WCHAR SE_CREATE_PAGEFILE_NAME_W[] =
1769 { '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 };
1770 static const WCHAR SE_CREATE_PERMANENT_NAME_W[] =
1771 { '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 };
1772 static const WCHAR SE_BACKUP_NAME_W[] =
1773 { 'S','e','B','a','c','k','u','p','P','r','i','v','i','l','e','g','e',0 };
1774 static const WCHAR SE_RESTORE_NAME_W[] =
1775 { 'S','e','R','e','s','t','o','r','e','P','r','i','v','i','l','e','g','e',0 };
1776 static const WCHAR SE_SHUTDOWN_NAME_W[] =
1777 { 'S','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 };
1778 static const WCHAR SE_DEBUG_NAME_W[] =
1779 { 'S','e','D','e','b','u','g','P','r','i','v','i','l','e','g','e',0 };
1780 static const WCHAR SE_AUDIT_NAME_W[] =
1781 { 'S','e','A','u','d','i','t','P','r','i','v','i','l','e','g','e',0 };
1782 static const WCHAR SE_SYSTEM_ENVIRONMENT_NAME_W[] =
1783 { '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 };
1784 static const WCHAR SE_CHANGE_NOTIFY_NAME_W[] =
1785 { 'S','e','C','h','a','n','g','e','N','o','t','i','f','y','P','r','i','v','i','l','e','g','e',0 };
1786 static const WCHAR SE_REMOTE_SHUTDOWN_NAME_W[] =
1787 { '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 };
1788 static const WCHAR SE_UNDOCK_NAME_W[] =
1789 { 'S','e','U','n','d','o','c','k','P','r','i','v','i','l','e','g','e',0 };
1790 static const WCHAR SE_SYNC_AGENT_NAME_W[] =
1791 { 'S','e','S','y','n','c','A','g','e','n','t','P','r','i','v','i','l','e','g','e',0 };
1792 static const WCHAR SE_ENABLE_DELEGATION_NAME_W[] =
1793 { '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 };
1794 static const WCHAR SE_MANAGE_VOLUME_NAME_W[] =
1795 { 'S','e','M','a','n','a','g','e','V','o','l','u','m','e','P','r','i','v','i','l','e','g','e',0 };
1796 static const WCHAR SE_IMPERSONATE_NAME_W[] =
1797 { 'S','e','I','m','p','e','r','s','o','n','a','t','e','P','r','i','v','i','l','e','g','e',0 };
1798 static const WCHAR SE_CREATE_GLOBAL_NAME_W[] =
1799 { 'S','e','C','r','e','a','t','e','G','l','o','b','a','l','P','r','i','v','i','l','e','g','e',0 };
1801 static const WCHAR * const WellKnownPrivNames[SE_MAX_WELL_KNOWN_PRIVILEGE + 1] =
1803 NULL,
1804 NULL,
1805 SE_CREATE_TOKEN_NAME_W,
1806 SE_ASSIGNPRIMARYTOKEN_NAME_W,
1807 SE_LOCK_MEMORY_NAME_W,
1808 SE_INCREASE_QUOTA_NAME_W,
1809 SE_MACHINE_ACCOUNT_NAME_W,
1810 SE_TCB_NAME_W,
1811 SE_SECURITY_NAME_W,
1812 SE_TAKE_OWNERSHIP_NAME_W,
1813 SE_LOAD_DRIVER_NAME_W,
1814 SE_SYSTEM_PROFILE_NAME_W,
1815 SE_SYSTEMTIME_NAME_W,
1816 SE_PROF_SINGLE_PROCESS_NAME_W,
1817 SE_INC_BASE_PRIORITY_NAME_W,
1818 SE_CREATE_PAGEFILE_NAME_W,
1819 SE_CREATE_PERMANENT_NAME_W,
1820 SE_BACKUP_NAME_W,
1821 SE_RESTORE_NAME_W,
1822 SE_SHUTDOWN_NAME_W,
1823 SE_DEBUG_NAME_W,
1824 SE_AUDIT_NAME_W,
1825 SE_SYSTEM_ENVIRONMENT_NAME_W,
1826 SE_CHANGE_NOTIFY_NAME_W,
1827 SE_REMOTE_SHUTDOWN_NAME_W,
1828 SE_UNDOCK_NAME_W,
1829 SE_SYNC_AGENT_NAME_W,
1830 SE_ENABLE_DELEGATION_NAME_W,
1831 SE_MANAGE_VOLUME_NAME_W,
1832 SE_IMPERSONATE_NAME_W,
1833 SE_CREATE_GLOBAL_NAME_W,
1836 /******************************************************************************
1837 * LookupPrivilegeValueW [ADVAPI32.@]
1839 * See LookupPrivilegeValueA.
1841 BOOL WINAPI
1842 LookupPrivilegeValueW( LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid )
1844 UINT i;
1846 TRACE("%s,%s,%p\n",debugstr_w(lpSystemName), debugstr_w(lpName), lpLuid);
1848 if (!ADVAPI_IsLocalComputer(lpSystemName))
1850 SetLastError(RPC_S_SERVER_UNAVAILABLE);
1851 return FALSE;
1853 if (!lpName)
1855 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1856 return FALSE;
1858 for( i=SE_MIN_WELL_KNOWN_PRIVILEGE; i<=SE_MAX_WELL_KNOWN_PRIVILEGE; i++ )
1860 if( !WellKnownPrivNames[i] )
1861 continue;
1862 if( strcmpiW( WellKnownPrivNames[i], lpName) )
1863 continue;
1864 lpLuid->LowPart = i;
1865 lpLuid->HighPart = 0;
1866 TRACE( "%s -> %08x-%08x\n",debugstr_w( lpSystemName ),
1867 lpLuid->HighPart, lpLuid->LowPart );
1868 return TRUE;
1870 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1871 return FALSE;
1874 /******************************************************************************
1875 * LookupPrivilegeValueA [ADVAPI32.@]
1877 * Retrieves LUID used on a system to represent the privilege name.
1879 * PARAMS
1880 * lpSystemName [I] Name of the system
1881 * lpName [I] Name of the privilege
1882 * lpLuid [O] Destination for the resulting LUID
1884 * RETURNS
1885 * Success: TRUE. lpLuid contains the requested LUID.
1886 * Failure: FALSE.
1888 BOOL WINAPI
1889 LookupPrivilegeValueA( LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid )
1891 UNICODE_STRING lpSystemNameW;
1892 UNICODE_STRING lpNameW;
1893 BOOL ret;
1895 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1896 RtlCreateUnicodeStringFromAsciiz(&lpNameW,lpName);
1897 ret = LookupPrivilegeValueW(lpSystemNameW.Buffer, lpNameW.Buffer, lpLuid);
1898 RtlFreeUnicodeString(&lpNameW);
1899 RtlFreeUnicodeString(&lpSystemNameW);
1900 return ret;
1903 BOOL WINAPI LookupPrivilegeDisplayNameA( LPCSTR lpSystemName, LPCSTR lpName, LPSTR lpDisplayName,
1904 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1906 FIXME("%s %s %s %p %p - stub\n", debugstr_a(lpSystemName), debugstr_a(lpName),
1907 debugstr_a(lpDisplayName), cchDisplayName, lpLanguageId);
1909 return FALSE;
1912 BOOL WINAPI LookupPrivilegeDisplayNameW( LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName,
1913 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1915 FIXME("%s %s %s %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpName),
1916 debugstr_w(lpDisplayName), cchDisplayName, lpLanguageId);
1918 return FALSE;
1921 /******************************************************************************
1922 * LookupPrivilegeNameA [ADVAPI32.@]
1924 * See LookupPrivilegeNameW.
1926 BOOL WINAPI
1927 LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName,
1928 LPDWORD cchName)
1930 UNICODE_STRING lpSystemNameW;
1931 BOOL ret;
1932 DWORD wLen = 0;
1934 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
1936 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1937 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
1938 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1940 LPWSTR lpNameW = heap_alloc(wLen * sizeof(WCHAR));
1942 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
1943 &wLen);
1944 if (ret)
1946 /* Windows crashes if cchName is NULL, so will I */
1947 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
1948 *cchName, NULL, NULL);
1950 if (len == 0)
1952 /* WideCharToMultiByte failed */
1953 ret = FALSE;
1955 else if (len > *cchName)
1957 *cchName = len;
1958 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1959 ret = FALSE;
1961 else
1963 /* WideCharToMultiByte succeeded, output length needs to be
1964 * length not including NULL terminator
1966 *cchName = len - 1;
1969 heap_free(lpNameW);
1971 RtlFreeUnicodeString(&lpSystemNameW);
1972 return ret;
1975 /******************************************************************************
1976 * LookupPrivilegeNameW [ADVAPI32.@]
1978 * Retrieves the privilege name referred to by the LUID lpLuid.
1980 * PARAMS
1981 * lpSystemName [I] Name of the system
1982 * lpLuid [I] Privilege value
1983 * lpName [O] Name of the privilege
1984 * cchName [I/O] Number of characters in lpName.
1986 * RETURNS
1987 * Success: TRUE. lpName contains the name of the privilege whose value is
1988 * *lpLuid.
1989 * Failure: FALSE.
1991 * REMARKS
1992 * Only well-known privilege names (those defined in winnt.h) can be retrieved
1993 * using this function.
1994 * If the length of lpName is too small, on return *cchName will contain the
1995 * number of WCHARs needed to contain the privilege, including the NULL
1996 * terminator, and GetLastError will return ERROR_INSUFFICIENT_BUFFER.
1997 * On success, *cchName will contain the number of characters stored in
1998 * lpName, NOT including the NULL terminator.
2000 BOOL WINAPI
2001 LookupPrivilegeNameW( LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName,
2002 LPDWORD cchName)
2004 size_t privNameLen;
2006 TRACE("%s,%p,%p,%p\n",debugstr_w(lpSystemName), lpLuid, lpName, cchName);
2008 if (!ADVAPI_IsLocalComputer(lpSystemName))
2010 SetLastError(RPC_S_SERVER_UNAVAILABLE);
2011 return FALSE;
2013 if (lpLuid->HighPart || (lpLuid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
2014 lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
2016 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
2017 return FALSE;
2019 privNameLen = strlenW(WellKnownPrivNames[lpLuid->LowPart]);
2020 /* Windows crashes if cchName is NULL, so will I */
2021 if (*cchName <= privNameLen)
2023 *cchName = privNameLen + 1;
2024 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2025 return FALSE;
2027 else
2029 strcpyW(lpName, WellKnownPrivNames[lpLuid->LowPart]);
2030 *cchName = privNameLen;
2031 return TRUE;
2035 /******************************************************************************
2036 * GetFileSecurityA [ADVAPI32.@]
2038 * Obtains Specified information about the security of a file or directory.
2040 * PARAMS
2041 * lpFileName [I] Name of the file to get info for
2042 * RequestedInformation [I] SE_ flags from "winnt.h"
2043 * pSecurityDescriptor [O] Destination for security information
2044 * nLength [I] Length of pSecurityDescriptor
2045 * lpnLengthNeeded [O] Destination for length of returned security information
2047 * RETURNS
2048 * Success: TRUE. pSecurityDescriptor contains the requested information.
2049 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
2051 * NOTES
2052 * The information returned is constrained by the callers access rights and
2053 * privileges.
2055 BOOL WINAPI
2056 GetFileSecurityA( LPCSTR lpFileName,
2057 SECURITY_INFORMATION RequestedInformation,
2058 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2059 DWORD nLength, LPDWORD lpnLengthNeeded )
2061 BOOL r;
2062 LPWSTR name;
2064 name = SERV_dup(lpFileName);
2065 r = GetFileSecurityW( name, RequestedInformation, pSecurityDescriptor,
2066 nLength, lpnLengthNeeded );
2067 heap_free( name );
2069 return r;
2072 /******************************************************************************
2073 * GetFileSecurityW [ADVAPI32.@]
2075 * See GetFileSecurityA.
2077 BOOL WINAPI
2078 GetFileSecurityW( LPCWSTR lpFileName,
2079 SECURITY_INFORMATION RequestedInformation,
2080 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2081 DWORD nLength, LPDWORD lpnLengthNeeded )
2083 HANDLE hfile;
2084 NTSTATUS status;
2085 DWORD access = 0, err;
2087 TRACE("(%s,%d,%p,%d,%p)\n", debugstr_w(lpFileName),
2088 RequestedInformation, pSecurityDescriptor,
2089 nLength, lpnLengthNeeded);
2091 if (RequestedInformation & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|
2092 DACL_SECURITY_INFORMATION))
2093 access |= READ_CONTROL;
2094 if (RequestedInformation & SACL_SECURITY_INFORMATION)
2095 access |= ACCESS_SYSTEM_SECURITY;
2097 err = get_security_file( lpFileName, access, &hfile);
2098 if (err)
2100 SetLastError(err);
2101 return FALSE;
2104 status = NtQuerySecurityObject( hfile, RequestedInformation, pSecurityDescriptor,
2105 nLength, lpnLengthNeeded );
2106 CloseHandle( hfile );
2107 return set_ntstatus( status );
2111 /******************************************************************************
2112 * LookupAccountSidA [ADVAPI32.@]
2114 BOOL WINAPI
2115 LookupAccountSidA(
2116 IN LPCSTR system,
2117 IN PSID sid,
2118 OUT LPSTR account,
2119 IN OUT LPDWORD accountSize,
2120 OUT LPSTR domain,
2121 IN OUT LPDWORD domainSize,
2122 OUT PSID_NAME_USE name_use )
2124 DWORD len;
2125 BOOL r;
2126 LPWSTR systemW;
2127 LPWSTR accountW = NULL;
2128 LPWSTR domainW = NULL;
2129 DWORD accountSizeW = *accountSize;
2130 DWORD domainSizeW = *domainSize;
2132 systemW = SERV_dup(system);
2133 if (account)
2134 accountW = heap_alloc( accountSizeW * sizeof(WCHAR) );
2135 if (domain)
2136 domainW = heap_alloc( domainSizeW * sizeof(WCHAR) );
2138 r = LookupAccountSidW( systemW, sid, accountW, &accountSizeW, domainW, &domainSizeW, name_use );
2140 if (r) {
2141 if (accountW && *accountSize) {
2142 len = WideCharToMultiByte( CP_ACP, 0, accountW, -1, NULL, 0, NULL, NULL );
2143 WideCharToMultiByte( CP_ACP, 0, accountW, -1, account, len, NULL, NULL );
2144 *accountSize = len;
2145 } else
2146 *accountSize = accountSizeW + 1;
2148 if (domainW && *domainSize) {
2149 len = WideCharToMultiByte( CP_ACP, 0, domainW, -1, NULL, 0, NULL, NULL );
2150 WideCharToMultiByte( CP_ACP, 0, domainW, -1, domain, len, NULL, NULL );
2151 *domainSize = len;
2152 } else
2153 *domainSize = domainSizeW + 1;
2155 else
2157 *accountSize = accountSizeW + 1;
2158 *domainSize = domainSizeW + 1;
2161 heap_free( systemW );
2162 heap_free( accountW );
2163 heap_free( domainW );
2165 return r;
2168 /******************************************************************************
2169 * LookupAccountSidW [ADVAPI32.@]
2171 * PARAMS
2172 * system []
2173 * sid []
2174 * account []
2175 * accountSize []
2176 * domain []
2177 * domainSize []
2178 * name_use []
2181 BOOL WINAPI
2182 LookupAccountSidW(
2183 IN LPCWSTR system,
2184 IN PSID sid,
2185 OUT LPWSTR account,
2186 IN OUT LPDWORD accountSize,
2187 OUT LPWSTR domain,
2188 IN OUT LPDWORD domainSize,
2189 OUT PSID_NAME_USE name_use )
2191 unsigned int i, j;
2192 const WCHAR * ac = NULL;
2193 const WCHAR * dm = NULL;
2194 SID_NAME_USE use = 0;
2195 LPWSTR computer_name = NULL;
2196 LPWSTR account_name = NULL;
2198 TRACE("(%s,sid=%s,%p,%p(%u),%p,%p(%u),%p)\n",
2199 debugstr_w(system),debugstr_sid(sid),
2200 account,accountSize,accountSize?*accountSize:0,
2201 domain,domainSize,domainSize?*domainSize:0,
2202 name_use);
2204 if (!ADVAPI_IsLocalComputer(system)) {
2205 FIXME("Only local computer supported!\n");
2206 SetLastError(RPC_S_SERVER_UNAVAILABLE);
2207 return FALSE;
2210 /* check the well known SIDs first */
2211 for (i = 0; i <= 60; i++) {
2212 if (IsWellKnownSid(sid, i)) {
2213 for (j = 0; j < (sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0])); j++) {
2214 if (ACCOUNT_SIDS[j].type == i) {
2215 ac = ACCOUNT_SIDS[j].account;
2216 dm = ACCOUNT_SIDS[j].domain;
2217 use = ACCOUNT_SIDS[j].name_use;
2220 break;
2224 if (dm == NULL) {
2225 MAX_SID local;
2227 /* check for the local computer next */
2228 if (ADVAPI_GetComputerSid(&local)) {
2229 DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
2230 BOOL result;
2232 computer_name = heap_alloc(size * sizeof(WCHAR));
2233 result = GetComputerNameW(computer_name, &size);
2235 if (result) {
2236 if (EqualSid(sid, &local)) {
2237 dm = computer_name;
2238 ac = Blank;
2239 use = 3;
2240 } else {
2241 local.SubAuthorityCount++;
2243 if (EqualPrefixSid(sid, &local)) {
2244 dm = computer_name;
2245 use = 1;
2246 switch (((MAX_SID *)sid)->SubAuthority[4]) {
2247 case DOMAIN_USER_RID_ADMIN:
2248 ac = Administrator;
2249 break;
2250 case DOMAIN_USER_RID_GUEST:
2251 ac = Guest;
2252 break;
2253 case DOMAIN_GROUP_RID_ADMINS:
2254 ac = Domain_Admins;
2255 break;
2256 case DOMAIN_GROUP_RID_USERS:
2257 ac = Domain_Users;
2258 break;
2259 case DOMAIN_GROUP_RID_GUESTS:
2260 ac = Domain_Guests;
2261 break;
2262 case DOMAIN_GROUP_RID_COMPUTERS:
2263 ac = Domain_Computers;
2264 break;
2265 case DOMAIN_GROUP_RID_CONTROLLERS:
2266 ac = Domain_Controllers;
2267 break;
2268 case DOMAIN_GROUP_RID_CERT_ADMINS:
2269 ac = Cert_Publishers;
2270 break;
2271 case DOMAIN_GROUP_RID_SCHEMA_ADMINS:
2272 ac = Schema_Admins;
2273 break;
2274 case DOMAIN_GROUP_RID_ENTERPRISE_ADMINS:
2275 ac = Enterprise_Admins;
2276 break;
2277 case DOMAIN_GROUP_RID_POLICY_ADMINS:
2278 ac = Group_Policy_Creator_Owners;
2279 break;
2280 case DOMAIN_ALIAS_RID_RAS_SERVERS:
2281 ac = RAS_and_IAS_Servers;
2282 break;
2283 case 1000: /* first user account */
2284 size = UNLEN + 1;
2285 account_name = heap_alloc(size * sizeof(WCHAR));
2286 if (GetUserNameW(account_name, &size))
2287 ac = account_name;
2288 else
2289 dm = NULL;
2291 break;
2292 default:
2293 dm = NULL;
2294 break;
2302 if (dm) {
2303 DWORD ac_len = lstrlenW(ac);
2304 DWORD dm_len = lstrlenW(dm);
2305 BOOL status = TRUE;
2307 if (*accountSize > ac_len) {
2308 if (account)
2309 lstrcpyW(account, ac);
2311 if (*domainSize > dm_len) {
2312 if (domain)
2313 lstrcpyW(domain, dm);
2315 if ((*accountSize && *accountSize < ac_len) ||
2316 (!account && !*accountSize && ac_len) ||
2317 (*domainSize && *domainSize < dm_len) ||
2318 (!domain && !*domainSize && dm_len))
2320 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2321 status = FALSE;
2323 if (*domainSize)
2324 *domainSize = dm_len;
2325 else
2326 *domainSize = dm_len + 1;
2327 if (*accountSize)
2328 *accountSize = ac_len;
2329 else
2330 *accountSize = ac_len + 1;
2332 heap_free(account_name);
2333 heap_free(computer_name);
2334 if (status) *name_use = use;
2335 return status;
2338 heap_free(account_name);
2339 heap_free(computer_name);
2340 SetLastError(ERROR_NONE_MAPPED);
2341 return FALSE;
2344 /******************************************************************************
2345 * SetFileSecurityA [ADVAPI32.@]
2347 * See SetFileSecurityW.
2349 BOOL WINAPI SetFileSecurityA( LPCSTR lpFileName,
2350 SECURITY_INFORMATION RequestedInformation,
2351 PSECURITY_DESCRIPTOR pSecurityDescriptor)
2353 BOOL r;
2354 LPWSTR name;
2356 name = SERV_dup(lpFileName);
2357 r = SetFileSecurityW( name, RequestedInformation, pSecurityDescriptor );
2358 heap_free( name );
2360 return r;
2363 /******************************************************************************
2364 * SetFileSecurityW [ADVAPI32.@]
2366 * Sets the security of a file or directory.
2368 * PARAMS
2369 * lpFileName []
2370 * RequestedInformation []
2371 * pSecurityDescriptor []
2373 * RETURNS
2374 * Success: TRUE.
2375 * Failure: FALSE.
2377 BOOL WINAPI
2378 SetFileSecurityW( LPCWSTR lpFileName,
2379 SECURITY_INFORMATION RequestedInformation,
2380 PSECURITY_DESCRIPTOR pSecurityDescriptor )
2382 HANDLE file;
2383 DWORD access = 0, err;
2384 NTSTATUS status;
2386 TRACE("(%s, 0x%x, %p)\n", debugstr_w(lpFileName), RequestedInformation,
2387 pSecurityDescriptor );
2389 if (RequestedInformation & OWNER_SECURITY_INFORMATION ||
2390 RequestedInformation & GROUP_SECURITY_INFORMATION)
2391 access |= WRITE_OWNER;
2392 if (RequestedInformation & SACL_SECURITY_INFORMATION)
2393 access |= ACCESS_SYSTEM_SECURITY;
2394 if (RequestedInformation & DACL_SECURITY_INFORMATION)
2395 access |= WRITE_DAC;
2397 err = get_security_file( lpFileName, access, &file);
2398 if (err)
2400 SetLastError(err);
2401 return FALSE;
2404 status = NtSetSecurityObject( file, RequestedInformation, pSecurityDescriptor );
2405 CloseHandle( file );
2406 return set_ntstatus( status );
2409 /******************************************************************************
2410 * QueryWindows31FilesMigration [ADVAPI32.@]
2412 * PARAMS
2413 * x1 []
2415 BOOL WINAPI
2416 QueryWindows31FilesMigration( DWORD x1 )
2418 FIXME("(%d):stub\n",x1);
2419 return TRUE;
2422 /******************************************************************************
2423 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
2425 * PARAMS
2426 * x1 []
2427 * x2 []
2428 * x3 []
2429 * x4 []
2431 BOOL WINAPI
2432 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
2433 DWORD x4 )
2435 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
2436 return TRUE;
2439 /******************************************************************************
2440 * NotifyBootConfigStatus [ADVAPI32.@]
2442 * PARAMS
2443 * x1 []
2445 BOOL WINAPI
2446 NotifyBootConfigStatus( BOOL x1 )
2448 FIXME("(0x%08d):stub\n",x1);
2449 return TRUE;
2452 /******************************************************************************
2453 * RevertToSelf [ADVAPI32.@]
2455 * Ends the impersonation of a user.
2457 * PARAMS
2458 * void []
2460 * RETURNS
2461 * Success: TRUE.
2462 * Failure: FALSE.
2464 BOOL WINAPI
2465 RevertToSelf( void )
2467 HANDLE Token = NULL;
2468 return set_ntstatus( NtSetInformationThread( GetCurrentThread(),
2469 ThreadImpersonationToken, &Token, sizeof(Token) ) );
2472 /******************************************************************************
2473 * ImpersonateSelf [ADVAPI32.@]
2475 * Makes an impersonation token that represents the process user and assigns
2476 * to the current thread.
2478 * PARAMS
2479 * ImpersonationLevel [I] Level at which to impersonate.
2481 * RETURNS
2482 * Success: TRUE.
2483 * Failure: FALSE.
2485 BOOL WINAPI
2486 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
2488 return set_ntstatus( RtlImpersonateSelf( ImpersonationLevel ) );
2491 /******************************************************************************
2492 * ImpersonateLoggedOnUser [ADVAPI32.@]
2494 BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken)
2496 DWORD size;
2497 NTSTATUS Status;
2498 HANDLE ImpersonationToken;
2499 TOKEN_TYPE Type;
2500 static BOOL warn = TRUE;
2502 if (warn)
2504 FIXME( "(%p)\n", hToken );
2505 warn = FALSE;
2507 if (!GetTokenInformation( hToken, TokenType, &Type,
2508 sizeof(TOKEN_TYPE), &size ))
2509 return FALSE;
2511 if (Type == TokenPrimary)
2513 OBJECT_ATTRIBUTES ObjectAttributes;
2515 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
2517 Status = NtDuplicateToken( hToken,
2518 TOKEN_IMPERSONATE | TOKEN_QUERY,
2519 &ObjectAttributes,
2520 SecurityImpersonation,
2521 TokenImpersonation,
2522 &ImpersonationToken );
2523 if (Status != STATUS_SUCCESS)
2525 ERR( "NtDuplicateToken failed with error 0x%08x\n", Status );
2526 SetLastError( RtlNtStatusToDosError( Status ) );
2527 return FALSE;
2530 else
2531 ImpersonationToken = hToken;
2533 Status = NtSetInformationThread( GetCurrentThread(),
2534 ThreadImpersonationToken,
2535 &ImpersonationToken,
2536 sizeof(ImpersonationToken) );
2538 if (Type == TokenPrimary)
2539 NtClose( ImpersonationToken );
2541 if (Status != STATUS_SUCCESS)
2543 ERR( "NtSetInformationThread failed with error 0x%08x\n", Status );
2544 SetLastError( RtlNtStatusToDosError( Status ) );
2545 return FALSE;
2548 return TRUE;
2551 /******************************************************************************
2552 * ImpersonateAnonymousToken [ADVAPI32.@]
2554 BOOL WINAPI ImpersonateAnonymousToken( HANDLE thread )
2556 TRACE("(%p)\n", thread);
2557 return set_ntstatus( NtImpersonateAnonymousToken( thread ) );
2560 /******************************************************************************
2561 * AccessCheck [ADVAPI32.@]
2563 BOOL WINAPI
2564 AccessCheck(
2565 PSECURITY_DESCRIPTOR SecurityDescriptor,
2566 HANDLE ClientToken,
2567 DWORD DesiredAccess,
2568 PGENERIC_MAPPING GenericMapping,
2569 PPRIVILEGE_SET PrivilegeSet,
2570 LPDWORD PrivilegeSetLength,
2571 LPDWORD GrantedAccess,
2572 LPBOOL AccessStatus)
2574 NTSTATUS access_status;
2575 BOOL ret = set_ntstatus( NtAccessCheck(SecurityDescriptor, ClientToken, DesiredAccess,
2576 GenericMapping, PrivilegeSet, PrivilegeSetLength,
2577 GrantedAccess, &access_status) );
2578 if (ret) *AccessStatus = set_ntstatus( access_status );
2579 return ret;
2583 /******************************************************************************
2584 * AccessCheckByType [ADVAPI32.@]
2586 BOOL WINAPI AccessCheckByType(
2587 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2588 PSID PrincipalSelfSid,
2589 HANDLE ClientToken,
2590 DWORD DesiredAccess,
2591 POBJECT_TYPE_LIST ObjectTypeList,
2592 DWORD ObjectTypeListLength,
2593 PGENERIC_MAPPING GenericMapping,
2594 PPRIVILEGE_SET PrivilegeSet,
2595 LPDWORD PrivilegeSetLength,
2596 LPDWORD GrantedAccess,
2597 LPBOOL AccessStatus)
2599 FIXME("stub\n");
2601 *AccessStatus = TRUE;
2603 return !*AccessStatus;
2606 /******************************************************************************
2607 * MapGenericMask [ADVAPI32.@]
2609 * Maps generic access rights into specific access rights according to the
2610 * supplied mapping.
2612 * PARAMS
2613 * AccessMask [I/O] Access rights.
2614 * GenericMapping [I] The mapping between generic and specific rights.
2616 * RETURNS
2617 * Nothing.
2619 VOID WINAPI MapGenericMask( PDWORD AccessMask, PGENERIC_MAPPING GenericMapping )
2621 RtlMapGenericMask( AccessMask, GenericMapping );
2624 /*************************************************************************
2625 * SetKernelObjectSecurity [ADVAPI32.@]
2627 BOOL WINAPI SetKernelObjectSecurity (
2628 IN HANDLE Handle,
2629 IN SECURITY_INFORMATION SecurityInformation,
2630 IN PSECURITY_DESCRIPTOR SecurityDescriptor )
2632 return set_ntstatus (NtSetSecurityObject (Handle, SecurityInformation, SecurityDescriptor));
2636 /******************************************************************************
2637 * AddAuditAccessAce [ADVAPI32.@]
2639 BOOL WINAPI AddAuditAccessAce(
2640 IN OUT PACL pAcl,
2641 IN DWORD dwAceRevision,
2642 IN DWORD dwAccessMask,
2643 IN PSID pSid,
2644 IN BOOL bAuditSuccess,
2645 IN BOOL bAuditFailure)
2647 return set_ntstatus( RtlAddAuditAccessAce(pAcl, dwAceRevision, dwAccessMask, pSid,
2648 bAuditSuccess, bAuditFailure) );
2651 /******************************************************************************
2652 * AddAuditAccessAce [ADVAPI32.@]
2654 BOOL WINAPI AddAuditAccessAceEx(
2655 IN OUT PACL pAcl,
2656 IN DWORD dwAceRevision,
2657 IN DWORD dwAceFlags,
2658 IN DWORD dwAccessMask,
2659 IN PSID pSid,
2660 IN BOOL bAuditSuccess,
2661 IN BOOL bAuditFailure)
2663 return set_ntstatus( RtlAddAuditAccessAceEx(pAcl, dwAceRevision, dwAceFlags, dwAccessMask, pSid,
2664 bAuditSuccess, bAuditFailure) );
2667 /******************************************************************************
2668 * LookupAccountNameA [ADVAPI32.@]
2670 BOOL WINAPI
2671 LookupAccountNameA(
2672 IN LPCSTR system,
2673 IN LPCSTR account,
2674 OUT PSID sid,
2675 OUT LPDWORD cbSid,
2676 LPSTR ReferencedDomainName,
2677 IN OUT LPDWORD cbReferencedDomainName,
2678 OUT PSID_NAME_USE name_use )
2680 BOOL ret;
2681 UNICODE_STRING lpSystemW;
2682 UNICODE_STRING lpAccountW;
2683 LPWSTR lpReferencedDomainNameW = NULL;
2685 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, system);
2686 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, account);
2688 if (ReferencedDomainName)
2689 lpReferencedDomainNameW = heap_alloc(*cbReferencedDomainName * sizeof(WCHAR));
2691 ret = LookupAccountNameW(lpSystemW.Buffer, lpAccountW.Buffer, sid, cbSid, lpReferencedDomainNameW,
2692 cbReferencedDomainName, name_use);
2694 if (ret && lpReferencedDomainNameW)
2696 WideCharToMultiByte(CP_ACP, 0, lpReferencedDomainNameW, -1,
2697 ReferencedDomainName, *cbReferencedDomainName+1, NULL, NULL);
2700 RtlFreeUnicodeString(&lpSystemW);
2701 RtlFreeUnicodeString(&lpAccountW);
2702 heap_free(lpReferencedDomainNameW);
2704 return ret;
2707 /******************************************************************************
2708 * lookup_user_account_name
2710 static BOOL lookup_user_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2711 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2713 char buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
2714 DWORD len = sizeof(buffer);
2715 HANDLE token;
2716 BOOL ret;
2717 PSID pSid;
2718 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
2719 DWORD nameLen;
2721 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
2723 if (GetLastError() != ERROR_NO_TOKEN) return FALSE;
2724 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) return FALSE;
2727 ret = GetTokenInformation(token, TokenUser, buffer, len, &len);
2728 CloseHandle( token );
2730 if (!ret) return FALSE;
2732 pSid = ((TOKEN_USER *)buffer)->User.Sid;
2734 if (Sid != NULL && (*cbSid >= GetLengthSid(pSid)))
2735 CopySid(*cbSid, Sid, pSid);
2736 if (*cbSid < GetLengthSid(pSid))
2738 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2739 ret = FALSE;
2741 *cbSid = GetLengthSid(pSid);
2743 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
2744 if (!GetComputerNameW(domainName, &nameLen))
2746 domainName[0] = 0;
2747 nameLen = 0;
2749 if (*cchReferencedDomainName <= nameLen || !ret)
2751 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2752 nameLen += 1;
2753 ret = FALSE;
2755 else if (ReferencedDomainName)
2756 strcpyW(ReferencedDomainName, domainName);
2758 *cchReferencedDomainName = nameLen;
2760 if (ret)
2761 *peUse = SidTypeUser;
2763 return ret;
2766 /******************************************************************************
2767 * lookup_computer_account_name
2769 static BOOL lookup_computer_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2770 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2772 MAX_SID local;
2773 BOOL ret;
2774 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
2775 DWORD nameLen;
2777 if ((ret = ADVAPI_GetComputerSid(&local)))
2779 if (Sid != NULL && (*cbSid >= GetLengthSid(&local)))
2780 CopySid(*cbSid, Sid, &local);
2781 if (*cbSid < GetLengthSid(&local))
2783 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2784 ret = FALSE;
2786 *cbSid = GetLengthSid(&local);
2789 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
2790 if (!GetComputerNameW(domainName, &nameLen))
2792 domainName[0] = 0;
2793 nameLen = 0;
2795 if (*cchReferencedDomainName <= nameLen || !ret)
2797 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2798 nameLen += 1;
2799 ret = FALSE;
2801 else if (ReferencedDomainName)
2802 strcpyW(ReferencedDomainName, domainName);
2804 *cchReferencedDomainName = nameLen;
2806 if (ret)
2807 *peUse = SidTypeDomain;
2809 return ret;
2812 static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STRING *account,
2813 LSA_UNICODE_STRING *domain )
2815 WCHAR *p = str->Buffer + str->Length / sizeof(WCHAR) - 1;
2817 while (p > str->Buffer && *p != '\\') p--;
2819 if (*p == '\\')
2821 domain->Buffer = str->Buffer;
2822 domain->Length = (p - str->Buffer) * sizeof(WCHAR);
2824 account->Buffer = p + 1;
2825 account->Length = str->Length - ((p - str->Buffer + 1) * sizeof(WCHAR));
2827 else
2829 domain->Buffer = NULL;
2830 domain->Length = 0;
2832 account->Buffer = str->Buffer;
2833 account->Length = str->Length;
2837 static BOOL match_domain( ULONG idx, const LSA_UNICODE_STRING *domain )
2839 ULONG len = strlenW( ACCOUNT_SIDS[idx].domain );
2841 if (len == domain->Length / sizeof(WCHAR) && !strncmpiW( domain->Buffer, ACCOUNT_SIDS[idx].domain, len ))
2842 return TRUE;
2844 return FALSE;
2847 static BOOL match_account( ULONG idx, const LSA_UNICODE_STRING *account )
2849 ULONG len = strlenW( ACCOUNT_SIDS[idx].account );
2851 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].account, len ))
2852 return TRUE;
2854 if (ACCOUNT_SIDS[idx].alias)
2856 len = strlenW( ACCOUNT_SIDS[idx].alias );
2857 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].alias, len ))
2858 return TRUE;
2860 return FALSE;
2864 * Helper function for LookupAccountNameW
2866 BOOL lookup_local_wellknown_name( const LSA_UNICODE_STRING *account_and_domain,
2867 PSID Sid, LPDWORD cbSid,
2868 LPWSTR ReferencedDomainName,
2869 LPDWORD cchReferencedDomainName,
2870 PSID_NAME_USE peUse, BOOL *handled )
2872 PSID pSid;
2873 LSA_UNICODE_STRING account, domain;
2874 BOOL ret = TRUE;
2875 ULONG i;
2877 *handled = FALSE;
2878 split_domain_account( account_and_domain, &account, &domain );
2880 for (i = 0; i < sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0]); i++)
2882 /* check domain first */
2883 if (domain.Buffer && !match_domain( i, &domain )) continue;
2885 if (match_account( i, &account ))
2887 DWORD len, sidLen = SECURITY_MAX_SID_SIZE;
2889 if (!(pSid = heap_alloc( sidLen ))) return FALSE;
2891 if ((ret = CreateWellKnownSid( ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen )))
2893 if (*cbSid < sidLen)
2895 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2896 ret = FALSE;
2898 else if (Sid)
2900 CopySid(*cbSid, Sid, pSid);
2902 *cbSid = sidLen;
2905 len = strlenW( ACCOUNT_SIDS[i].domain );
2906 if (*cchReferencedDomainName <= len || !ret)
2908 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2909 len++;
2910 ret = FALSE;
2912 else if (ReferencedDomainName)
2914 strcpyW( ReferencedDomainName, ACCOUNT_SIDS[i].domain );
2917 *cchReferencedDomainName = len;
2918 if (ret)
2919 *peUse = ACCOUNT_SIDS[i].name_use;
2921 heap_free(pSid);
2922 *handled = TRUE;
2923 return ret;
2926 return ret;
2929 BOOL lookup_local_user_name( const LSA_UNICODE_STRING *account_and_domain,
2930 PSID Sid, LPDWORD cbSid,
2931 LPWSTR ReferencedDomainName,
2932 LPDWORD cchReferencedDomainName,
2933 PSID_NAME_USE peUse, BOOL *handled )
2935 DWORD nameLen;
2936 LPWSTR userName = NULL;
2937 LSA_UNICODE_STRING account, domain;
2938 BOOL ret = TRUE;
2940 *handled = FALSE;
2941 split_domain_account( account_and_domain, &account, &domain );
2943 /* Let the current Unix user id masquerade as first Windows user account */
2945 nameLen = UNLEN + 1;
2946 if (!(userName = heap_alloc( nameLen * sizeof(WCHAR) ))) return FALSE;
2948 if (domain.Buffer)
2950 /* check to make sure this account is on this computer */
2951 if (GetComputerNameW( userName, &nameLen ) &&
2952 (domain.Length / sizeof(WCHAR) != nameLen || strncmpW( domain.Buffer, userName, nameLen )))
2954 SetLastError(ERROR_NONE_MAPPED);
2955 ret = FALSE;
2957 nameLen = UNLEN + 1;
2960 if (GetUserNameW( userName, &nameLen ) &&
2961 account.Length / sizeof(WCHAR) == nameLen - 1 && !strncmpW( account.Buffer, userName, nameLen - 1 ))
2963 ret = lookup_user_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2964 *handled = TRUE;
2966 else
2968 nameLen = UNLEN + 1;
2969 if (GetComputerNameW( userName, &nameLen ) &&
2970 account.Length / sizeof(WCHAR) == nameLen && !strncmpW( account.Buffer, userName , nameLen ))
2972 ret = lookup_computer_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2973 *handled = TRUE;
2977 heap_free(userName);
2978 return ret;
2981 /******************************************************************************
2982 * LookupAccountNameW [ADVAPI32.@]
2984 BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
2985 LPDWORD cbSid, LPWSTR ReferencedDomainName,
2986 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2988 BOOL ret, handled;
2989 LSA_UNICODE_STRING account;
2991 TRACE("%s %s %p %p %p %p %p\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
2992 Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
2994 if (!ADVAPI_IsLocalComputer( lpSystemName ))
2996 FIXME("remote computer not supported\n");
2997 SetLastError( RPC_S_SERVER_UNAVAILABLE );
2998 return FALSE;
3001 if (!lpAccountName || !strcmpW( lpAccountName, Blank ))
3003 lpAccountName = BUILTIN;
3006 RtlInitUnicodeString( &account, lpAccountName );
3008 /* Check well known SIDs first */
3009 ret = lookup_local_wellknown_name( &account, Sid, cbSid, ReferencedDomainName,
3010 cchReferencedDomainName, peUse, &handled );
3011 if (handled)
3012 return ret;
3014 /* Check user names */
3015 ret = lookup_local_user_name( &account, Sid, cbSid, ReferencedDomainName,
3016 cchReferencedDomainName, peUse, &handled);
3017 if (handled)
3018 return ret;
3020 SetLastError( ERROR_NONE_MAPPED );
3021 return FALSE;
3024 /******************************************************************************
3025 * PrivilegeCheck [ADVAPI32.@]
3027 BOOL WINAPI PrivilegeCheck( HANDLE ClientToken, PPRIVILEGE_SET RequiredPrivileges, LPBOOL pfResult)
3029 BOOL ret;
3030 BOOLEAN Result;
3032 TRACE("%p %p %p\n", ClientToken, RequiredPrivileges, pfResult);
3034 ret = set_ntstatus (NtPrivilegeCheck (ClientToken, RequiredPrivileges, &Result));
3035 if (ret)
3036 *pfResult = Result;
3037 return ret;
3040 /******************************************************************************
3041 * AccessCheckAndAuditAlarmA [ADVAPI32.@]
3043 BOOL WINAPI AccessCheckAndAuditAlarmA(LPCSTR Subsystem, LPVOID HandleId, LPSTR ObjectTypeName,
3044 LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
3045 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
3046 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
3048 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_a(Subsystem),
3049 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName),
3050 SecurityDescriptor, DesiredAccess, GenericMapping,
3051 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
3052 return TRUE;
3055 /******************************************************************************
3056 * AccessCheckAndAuditAlarmW [ADVAPI32.@]
3058 BOOL WINAPI AccessCheckAndAuditAlarmW(LPCWSTR Subsystem, LPVOID HandleId, LPWSTR ObjectTypeName,
3059 LPWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
3060 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
3061 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
3063 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_w(Subsystem),
3064 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName),
3065 SecurityDescriptor, DesiredAccess, GenericMapping,
3066 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
3067 return TRUE;
3070 BOOL WINAPI ObjectCloseAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3072 FIXME("stub (%s,%p,%x)\n", debugstr_a(SubsystemName), HandleId, GenerateOnClose);
3074 return TRUE;
3077 BOOL WINAPI ObjectCloseAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3079 FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
3081 return TRUE;
3084 BOOL WINAPI ObjectDeleteAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3086 FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
3088 return TRUE;
3091 BOOL WINAPI ObjectOpenAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName,
3092 LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3093 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3094 LPBOOL GenerateOnClose)
3096 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_a(SubsystemName),
3097 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName), pSecurityDescriptor,
3098 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3099 GenerateOnClose);
3101 return TRUE;
3104 BOOL WINAPI ObjectOpenAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName,
3105 LPWSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3106 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3107 LPBOOL GenerateOnClose)
3109 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_w(SubsystemName),
3110 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName), pSecurityDescriptor,
3111 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3112 GenerateOnClose);
3114 return TRUE;
3117 BOOL WINAPI ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3118 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3120 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_a(SubsystemName), HandleId, ClientToken,
3121 DesiredAccess, Privileges, AccessGranted);
3123 return TRUE;
3126 BOOL WINAPI ObjectPrivilegeAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3127 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3129 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_w(SubsystemName), HandleId, ClientToken,
3130 DesiredAccess, Privileges, AccessGranted);
3132 return TRUE;
3135 BOOL WINAPI PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken,
3136 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3138 FIXME("stub (%s,%s,%p,%p,%x)\n", debugstr_a(SubsystemName), debugstr_a(ServiceName),
3139 ClientToken, Privileges, AccessGranted);
3141 return TRUE;
3144 BOOL WINAPI PrivilegedServiceAuditAlarmW( LPCWSTR SubsystemName, LPCWSTR ServiceName, HANDLE ClientToken,
3145 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3147 FIXME("stub %s,%s,%p,%p,%x)\n", debugstr_w(SubsystemName), debugstr_w(ServiceName),
3148 ClientToken, Privileges, AccessGranted);
3150 return TRUE;
3153 /******************************************************************************
3154 * GetSecurityInfo [ADVAPI32.@]
3156 * Retrieves a copy of the security descriptor associated with an object.
3158 * PARAMS
3159 * hObject [I] A handle for the object.
3160 * ObjectType [I] The type of object.
3161 * SecurityInfo [I] A bitmask indicating what info to retrieve.
3162 * ppsidOwner [O] If non-null, receives a pointer to the owner SID.
3163 * ppsidGroup [O] If non-null, receives a pointer to the group SID.
3164 * ppDacl [O] If non-null, receives a pointer to the DACL.
3165 * ppSacl [O] If non-null, receives a pointer to the SACL.
3166 * ppSecurityDescriptor [O] Receives a pointer to the security descriptor,
3167 * which must be freed with LocalFree.
3169 * RETURNS
3170 * ERROR_SUCCESS if all's well, and a WIN32 error code otherwise.
3172 DWORD WINAPI GetSecurityInfo(
3173 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3174 SECURITY_INFORMATION SecurityInfo, PSID *ppsidOwner,
3175 PSID *ppsidGroup, PACL *ppDacl, PACL *ppSacl,
3176 PSECURITY_DESCRIPTOR *ppSecurityDescriptor
3179 PSECURITY_DESCRIPTOR sd;
3180 NTSTATUS status;
3181 ULONG n1, n2;
3182 BOOL present, defaulted;
3184 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
3185 if (!(ppsidOwner||ppsidGroup||ppDacl||ppSacl||ppSecurityDescriptor)) return ERROR_INVALID_PARAMETER;
3187 /* If no descriptor, we have to check that there's a pointer for the requested information */
3188 if( !ppSecurityDescriptor && (
3189 ((SecurityInfo & OWNER_SECURITY_INFORMATION) && !ppsidOwner)
3190 || ((SecurityInfo & GROUP_SECURITY_INFORMATION) && !ppsidGroup)
3191 || ((SecurityInfo & DACL_SECURITY_INFORMATION) && !ppDacl)
3192 || ((SecurityInfo & SACL_SECURITY_INFORMATION) && !ppSacl) ))
3193 return ERROR_INVALID_PARAMETER;
3195 switch (ObjectType)
3197 case SE_SERVICE:
3198 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, NULL, 0, &n1);
3199 break;
3200 default:
3201 status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1);
3202 break;
3204 if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS)
3205 return RtlNtStatusToDosError(status);
3207 sd = LocalAlloc(0, n1);
3208 if (!sd)
3209 return ERROR_NOT_ENOUGH_MEMORY;
3211 switch (ObjectType)
3213 case SE_SERVICE:
3214 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, sd, n1, &n2);
3215 break;
3216 default:
3217 status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2);
3218 break;
3220 if (status != STATUS_SUCCESS)
3222 LocalFree(sd);
3223 return RtlNtStatusToDosError(status);
3226 if (ppsidOwner)
3228 *ppsidOwner = NULL;
3229 GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted);
3231 if (ppsidGroup)
3233 *ppsidGroup = NULL;
3234 GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted);
3236 if (ppDacl)
3238 *ppDacl = NULL;
3239 GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted);
3241 if (ppSacl)
3243 *ppSacl = NULL;
3244 GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted);
3246 if (ppSecurityDescriptor)
3247 *ppSecurityDescriptor = sd;
3249 /* The security descriptor (sd) cannot be freed if ppSecurityDescriptor is
3250 * NULL, because native happily returns the SIDs and ACLs that are requested
3251 * in this case.
3254 return ERROR_SUCCESS;
3257 /******************************************************************************
3258 * GetSecurityInfoExA [ADVAPI32.@]
3260 DWORD WINAPI GetSecurityInfoExA(
3261 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3262 SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
3263 LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
3264 PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
3267 FIXME("stub!\n");
3268 return ERROR_BAD_PROVIDER;
3271 /******************************************************************************
3272 * GetSecurityInfoExW [ADVAPI32.@]
3274 DWORD WINAPI GetSecurityInfoExW(
3275 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3276 SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
3277 LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList,
3278 PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
3281 FIXME("stub!\n");
3282 return ERROR_BAD_PROVIDER;
3285 /******************************************************************************
3286 * BuildExplicitAccessWithNameA [ADVAPI32.@]
3288 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
3289 LPSTR pTrusteeName, DWORD AccessPermissions,
3290 ACCESS_MODE AccessMode, DWORD Inheritance )
3292 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_a(pTrusteeName),
3293 AccessPermissions, AccessMode, Inheritance);
3295 pExplicitAccess->grfAccessPermissions = AccessPermissions;
3296 pExplicitAccess->grfAccessMode = AccessMode;
3297 pExplicitAccess->grfInheritance = Inheritance;
3299 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3300 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3301 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3302 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3303 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3306 /******************************************************************************
3307 * BuildExplicitAccessWithNameW [ADVAPI32.@]
3309 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
3310 LPWSTR pTrusteeName, DWORD AccessPermissions,
3311 ACCESS_MODE AccessMode, DWORD Inheritance )
3313 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_w(pTrusteeName),
3314 AccessPermissions, AccessMode, Inheritance);
3316 pExplicitAccess->grfAccessPermissions = AccessPermissions;
3317 pExplicitAccess->grfAccessMode = AccessMode;
3318 pExplicitAccess->grfInheritance = Inheritance;
3320 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3321 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3322 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3323 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3324 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3327 /******************************************************************************
3328 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
3330 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
3331 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
3332 LPSTR InheritedObjectTypeName, LPSTR Name )
3334 DWORD ObjectsPresent = 0;
3336 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3337 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
3339 /* Fill the OBJECTS_AND_NAME structure */
3340 pObjName->ObjectType = ObjectType;
3341 if (ObjectTypeName != NULL)
3343 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3346 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3347 if (InheritedObjectTypeName != NULL)
3349 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3352 pObjName->ObjectsPresent = ObjectsPresent;
3353 pObjName->ptstrName = Name;
3355 /* Fill the TRUSTEE structure */
3356 pTrustee->pMultipleTrustee = NULL;
3357 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3358 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3359 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3360 pTrustee->ptstrName = (LPSTR)pObjName;
3363 /******************************************************************************
3364 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
3366 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
3367 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
3368 LPWSTR InheritedObjectTypeName, LPWSTR Name )
3370 DWORD ObjectsPresent = 0;
3372 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3373 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
3375 /* Fill the OBJECTS_AND_NAME structure */
3376 pObjName->ObjectType = ObjectType;
3377 if (ObjectTypeName != NULL)
3379 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3382 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3383 if (InheritedObjectTypeName != NULL)
3385 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3388 pObjName->ObjectsPresent = ObjectsPresent;
3389 pObjName->ptstrName = Name;
3391 /* Fill the TRUSTEE structure */
3392 pTrustee->pMultipleTrustee = NULL;
3393 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3394 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3395 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3396 pTrustee->ptstrName = (LPWSTR)pObjName;
3399 /******************************************************************************
3400 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
3402 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
3403 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3405 DWORD ObjectsPresent = 0;
3407 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3409 /* Fill the OBJECTS_AND_SID structure */
3410 if (pObjectGuid != NULL)
3412 pObjSid->ObjectTypeGuid = *pObjectGuid;
3413 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3415 else
3417 ZeroMemory(&pObjSid->ObjectTypeGuid,
3418 sizeof(GUID));
3421 if (pInheritedObjectGuid != NULL)
3423 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3424 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3426 else
3428 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3429 sizeof(GUID));
3432 pObjSid->ObjectsPresent = ObjectsPresent;
3433 pObjSid->pSid = pSid;
3435 /* Fill the TRUSTEE structure */
3436 pTrustee->pMultipleTrustee = NULL;
3437 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3438 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3439 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3440 pTrustee->ptstrName = (LPSTR) pObjSid;
3443 /******************************************************************************
3444 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
3446 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
3447 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3449 DWORD ObjectsPresent = 0;
3451 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3453 /* Fill the OBJECTS_AND_SID structure */
3454 if (pObjectGuid != NULL)
3456 pObjSid->ObjectTypeGuid = *pObjectGuid;
3457 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3459 else
3461 ZeroMemory(&pObjSid->ObjectTypeGuid,
3462 sizeof(GUID));
3465 if (pInheritedObjectGuid != NULL)
3467 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3468 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3470 else
3472 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3473 sizeof(GUID));
3476 pObjSid->ObjectsPresent = ObjectsPresent;
3477 pObjSid->pSid = pSid;
3479 /* Fill the TRUSTEE structure */
3480 pTrustee->pMultipleTrustee = NULL;
3481 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3482 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3483 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3484 pTrustee->ptstrName = (LPWSTR) pObjSid;
3487 /******************************************************************************
3488 * BuildTrusteeWithSidA [ADVAPI32.@]
3490 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid)
3492 TRACE("%p %p\n", pTrustee, pSid);
3494 pTrustee->pMultipleTrustee = NULL;
3495 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3496 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3497 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3498 pTrustee->ptstrName = pSid;
3501 /******************************************************************************
3502 * BuildTrusteeWithSidW [ADVAPI32.@]
3504 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
3506 TRACE("%p %p\n", pTrustee, pSid);
3508 pTrustee->pMultipleTrustee = NULL;
3509 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3510 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3511 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3512 pTrustee->ptstrName = pSid;
3515 /******************************************************************************
3516 * BuildTrusteeWithNameA [ADVAPI32.@]
3518 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
3520 TRACE("%p %s\n", pTrustee, debugstr_a(name) );
3522 pTrustee->pMultipleTrustee = NULL;
3523 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3524 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3525 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3526 pTrustee->ptstrName = name;
3529 /******************************************************************************
3530 * BuildTrusteeWithNameW [ADVAPI32.@]
3532 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
3534 TRACE("%p %s\n", pTrustee, debugstr_w(name) );
3536 pTrustee->pMultipleTrustee = NULL;
3537 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3538 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3539 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3540 pTrustee->ptstrName = name;
3543 /******************************************************************************
3544 * GetTrusteeFormA [ADVAPI32.@]
3546 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee)
3548 TRACE("(%p)\n", pTrustee);
3550 if (!pTrustee)
3551 return TRUSTEE_BAD_FORM;
3553 return pTrustee->TrusteeForm;
3556 /******************************************************************************
3557 * GetTrusteeFormW [ADVAPI32.@]
3559 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee)
3561 TRACE("(%p)\n", pTrustee);
3563 if (!pTrustee)
3564 return TRUSTEE_BAD_FORM;
3566 return pTrustee->TrusteeForm;
3569 /******************************************************************************
3570 * GetTrusteeNameA [ADVAPI32.@]
3572 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee)
3574 TRACE("(%p)\n", pTrustee);
3576 if (!pTrustee)
3577 return NULL;
3579 return pTrustee->ptstrName;
3582 /******************************************************************************
3583 * GetTrusteeNameW [ADVAPI32.@]
3585 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee)
3587 TRACE("(%p)\n", pTrustee);
3589 if (!pTrustee)
3590 return NULL;
3592 return pTrustee->ptstrName;
3595 /******************************************************************************
3596 * GetTrusteeTypeA [ADVAPI32.@]
3598 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee)
3600 TRACE("(%p)\n", pTrustee);
3602 if (!pTrustee)
3603 return TRUSTEE_IS_UNKNOWN;
3605 return pTrustee->TrusteeType;
3608 /******************************************************************************
3609 * GetTrusteeTypeW [ADVAPI32.@]
3611 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee)
3613 TRACE("(%p)\n", pTrustee);
3615 if (!pTrustee)
3616 return TRUSTEE_IS_UNKNOWN;
3618 return pTrustee->TrusteeType;
3621 BOOL WINAPI SetAclInformation( PACL pAcl, LPVOID pAclInformation,
3622 DWORD nAclInformationLength,
3623 ACL_INFORMATION_CLASS dwAclInformationClass )
3625 FIXME("%p %p 0x%08x 0x%08x - stub\n", pAcl, pAclInformation,
3626 nAclInformationLength, dwAclInformationClass);
3628 return TRUE;
3631 static DWORD trustee_name_A_to_W(TRUSTEE_FORM form, char *trustee_nameA, WCHAR **ptrustee_nameW)
3633 switch (form)
3635 case TRUSTEE_IS_NAME:
3637 *ptrustee_nameW = SERV_dup(trustee_nameA);
3638 return ERROR_SUCCESS;
3640 case TRUSTEE_IS_OBJECTS_AND_NAME:
3642 OBJECTS_AND_NAME_A *objA = (OBJECTS_AND_NAME_A *)trustee_nameA;
3643 OBJECTS_AND_NAME_W *objW = NULL;
3645 if (objA)
3647 if (!(objW = heap_alloc( sizeof(OBJECTS_AND_NAME_W) )))
3648 return ERROR_NOT_ENOUGH_MEMORY;
3650 objW->ObjectsPresent = objA->ObjectsPresent;
3651 objW->ObjectType = objA->ObjectType;
3652 objW->ObjectTypeName = SERV_dup(objA->ObjectTypeName);
3653 objW->InheritedObjectTypeName = SERV_dup(objA->InheritedObjectTypeName);
3654 objW->ptstrName = SERV_dup(objA->ptstrName);
3657 *ptrustee_nameW = (WCHAR *)objW;
3658 return ERROR_SUCCESS;
3660 /* These forms do not require conversion. */
3661 case TRUSTEE_IS_SID:
3662 case TRUSTEE_IS_OBJECTS_AND_SID:
3663 *ptrustee_nameW = (WCHAR *)trustee_nameA;
3664 return ERROR_SUCCESS;
3665 default:
3666 return ERROR_INVALID_PARAMETER;
3670 static void free_trustee_name(TRUSTEE_FORM form, WCHAR *trustee_nameW)
3672 switch (form)
3674 case TRUSTEE_IS_NAME:
3675 heap_free( trustee_nameW );
3676 break;
3677 case TRUSTEE_IS_OBJECTS_AND_NAME:
3679 OBJECTS_AND_NAME_W *objW = (OBJECTS_AND_NAME_W *)trustee_nameW;
3681 if (objW)
3683 heap_free( objW->ptstrName );
3684 heap_free( objW->InheritedObjectTypeName );
3685 heap_free( objW->ObjectTypeName );
3686 heap_free( objW );
3689 break;
3691 /* Other forms did not require allocation, so no freeing is necessary. */
3692 default:
3693 break;
3697 /******************************************************************************
3698 * SetEntriesInAclA [ADVAPI32.@]
3700 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
3701 PACL OldAcl, PACL* NewAcl )
3703 DWORD err = ERROR_SUCCESS;
3704 EXPLICIT_ACCESSW *pEntriesW;
3705 UINT alloc_index, free_index;
3707 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3709 if (NewAcl)
3710 *NewAcl = NULL;
3712 if (!count && !OldAcl)
3713 return ERROR_SUCCESS;
3715 pEntriesW = heap_alloc( count * sizeof(EXPLICIT_ACCESSW) );
3716 if (!pEntriesW)
3717 return ERROR_NOT_ENOUGH_MEMORY;
3719 for (alloc_index = 0; alloc_index < count; ++alloc_index)
3721 pEntriesW[alloc_index].grfAccessPermissions = pEntries[alloc_index].grfAccessPermissions;
3722 pEntriesW[alloc_index].grfAccessMode = pEntries[alloc_index].grfAccessMode;
3723 pEntriesW[alloc_index].grfInheritance = pEntries[alloc_index].grfInheritance;
3724 pEntriesW[alloc_index].Trustee.pMultipleTrustee = NULL; /* currently not supported */
3725 pEntriesW[alloc_index].Trustee.MultipleTrusteeOperation = pEntries[alloc_index].Trustee.MultipleTrusteeOperation;
3726 pEntriesW[alloc_index].Trustee.TrusteeForm = pEntries[alloc_index].Trustee.TrusteeForm;
3727 pEntriesW[alloc_index].Trustee.TrusteeType = pEntries[alloc_index].Trustee.TrusteeType;
3729 err = trustee_name_A_to_W( pEntries[alloc_index].Trustee.TrusteeForm,
3730 pEntries[alloc_index].Trustee.ptstrName,
3731 &pEntriesW[alloc_index].Trustee.ptstrName );
3732 if (err != ERROR_SUCCESS)
3734 if (err == ERROR_INVALID_PARAMETER)
3735 WARN("bad trustee form %d for trustee %d\n",
3736 pEntries[alloc_index].Trustee.TrusteeForm, alloc_index);
3738 goto cleanup;
3742 err = SetEntriesInAclW( count, pEntriesW, OldAcl, NewAcl );
3744 cleanup:
3745 /* Free any previously allocated trustee name buffers, taking into account
3746 * a possible out-of-memory condition while building the EXPLICIT_ACCESSW
3747 * list. */
3748 for (free_index = 0; free_index < alloc_index; ++free_index)
3749 free_trustee_name( pEntriesW[free_index].Trustee.TrusteeForm, pEntriesW[free_index].Trustee.ptstrName );
3751 heap_free( pEntriesW );
3752 return err;
3755 /******************************************************************************
3756 * SetEntriesInAclW [ADVAPI32.@]
3758 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
3759 PACL OldAcl, PACL* NewAcl )
3761 ULONG i;
3762 PSID *ppsid;
3763 DWORD ret = ERROR_SUCCESS;
3764 DWORD acl_size = sizeof(ACL);
3765 NTSTATUS status;
3767 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3769 if (NewAcl)
3770 *NewAcl = NULL;
3772 if (!count && !OldAcl)
3773 return ERROR_SUCCESS;
3775 /* allocate array of maximum sized sids allowed */
3776 ppsid = heap_alloc(count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
3777 if (!ppsid)
3778 return ERROR_OUTOFMEMORY;
3780 for (i = 0; i < count; i++)
3782 ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3784 TRACE("[%d]:\n\tgrfAccessPermissions = 0x%x\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%x\n\t"
3785 "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
3786 "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
3787 pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
3788 pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
3789 pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
3790 pEntries[i].Trustee.ptstrName);
3792 if (pEntries[i].Trustee.MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
3794 WARN("bad multiple trustee operation %d for trustee %d\n", pEntries[i].Trustee.MultipleTrusteeOperation, i);
3795 ret = ERROR_INVALID_PARAMETER;
3796 goto exit;
3799 switch (pEntries[i].Trustee.TrusteeForm)
3801 case TRUSTEE_IS_SID:
3802 if (!CopySid(FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]),
3803 ppsid[i], pEntries[i].Trustee.ptstrName))
3805 WARN("bad sid %p for trustee %d\n", pEntries[i].Trustee.ptstrName, i);
3806 ret = ERROR_INVALID_PARAMETER;
3807 goto exit;
3809 break;
3810 case TRUSTEE_IS_NAME:
3812 DWORD sid_size = FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3813 DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
3814 SID_NAME_USE use;
3815 if (!strcmpW( pEntries[i].Trustee.ptstrName, CURRENT_USER ))
3817 if (!lookup_user_account_name( ppsid[i], &sid_size, NULL, &domain_size, &use ))
3819 ret = GetLastError();
3820 goto exit;
3823 else if (!LookupAccountNameW(NULL, pEntries[i].Trustee.ptstrName, ppsid[i], &sid_size, NULL, &domain_size, &use))
3825 WARN("bad user name %s for trustee %d\n", debugstr_w(pEntries[i].Trustee.ptstrName), i);
3826 ret = ERROR_INVALID_PARAMETER;
3827 goto exit;
3829 break;
3831 case TRUSTEE_IS_OBJECTS_AND_SID:
3832 FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
3833 break;
3834 case TRUSTEE_IS_OBJECTS_AND_NAME:
3835 FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
3836 break;
3837 default:
3838 WARN("bad trustee form %d for trustee %d\n", pEntries[i].Trustee.TrusteeForm, i);
3839 ret = ERROR_INVALID_PARAMETER;
3840 goto exit;
3843 /* Note: we overestimate the ACL size here as a tradeoff between
3844 * instructions (simplicity) and memory */
3845 switch (pEntries[i].grfAccessMode)
3847 case GRANT_ACCESS:
3848 case SET_ACCESS:
3849 acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3850 break;
3851 case DENY_ACCESS:
3852 acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3853 break;
3854 case SET_AUDIT_SUCCESS:
3855 case SET_AUDIT_FAILURE:
3856 acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
3857 break;
3858 case REVOKE_ACCESS:
3859 break;
3860 default:
3861 WARN("bad access mode %d for trustee %d\n", pEntries[i].grfAccessMode, i);
3862 ret = ERROR_INVALID_PARAMETER;
3863 goto exit;
3867 if (OldAcl)
3869 ACL_SIZE_INFORMATION size_info;
3871 status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
3872 if (status != STATUS_SUCCESS)
3874 ret = RtlNtStatusToDosError(status);
3875 goto exit;
3877 acl_size += size_info.AclBytesInUse - sizeof(ACL);
3880 *NewAcl = LocalAlloc(0, acl_size);
3881 if (!*NewAcl)
3883 ret = ERROR_OUTOFMEMORY;
3884 goto exit;
3887 status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
3888 if (status != STATUS_SUCCESS)
3890 ret = RtlNtStatusToDosError(status);
3891 goto exit;
3894 for (i = 0; i < count; i++)
3896 switch (pEntries[i].grfAccessMode)
3898 case GRANT_ACCESS:
3899 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3900 pEntries[i].grfInheritance,
3901 pEntries[i].grfAccessPermissions,
3902 ppsid[i]);
3903 break;
3904 case SET_ACCESS:
3906 ULONG j;
3907 BOOL add = TRUE;
3908 if (OldAcl)
3910 for (j = 0; ; j++)
3912 const ACE_HEADER *existing_ace_header;
3913 status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
3914 if (status != STATUS_SUCCESS)
3915 break;
3916 if (pEntries[i].grfAccessMode == SET_ACCESS &&
3917 existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3918 EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
3920 add = FALSE;
3921 break;
3925 if (add)
3926 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3927 pEntries[i].grfInheritance,
3928 pEntries[i].grfAccessPermissions,
3929 ppsid[i]);
3930 break;
3932 case DENY_ACCESS:
3933 status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
3934 pEntries[i].grfInheritance,
3935 pEntries[i].grfAccessPermissions,
3936 ppsid[i]);
3937 break;
3938 case SET_AUDIT_SUCCESS:
3939 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3940 pEntries[i].grfInheritance,
3941 pEntries[i].grfAccessPermissions,
3942 ppsid[i], TRUE, FALSE);
3943 break;
3944 case SET_AUDIT_FAILURE:
3945 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3946 pEntries[i].grfInheritance,
3947 pEntries[i].grfAccessPermissions,
3948 ppsid[i], FALSE, TRUE);
3949 break;
3950 default:
3951 FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
3955 if (OldAcl)
3957 for (i = 0; ; i++)
3959 BOOL add = TRUE;
3960 ULONG j;
3961 const ACE_HEADER *old_ace_header;
3962 status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
3963 if (status != STATUS_SUCCESS) break;
3964 for (j = 0; j < count; j++)
3966 if (pEntries[j].grfAccessMode == SET_ACCESS &&
3967 old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3968 EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3970 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
3971 add = FALSE;
3972 break;
3974 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
3976 switch (old_ace_header->AceType)
3978 case ACCESS_ALLOWED_ACE_TYPE:
3979 if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3980 add = FALSE;
3981 break;
3982 case ACCESS_DENIED_ACE_TYPE:
3983 if (EqualSid(ppsid[j], &((ACCESS_DENIED_ACE *)old_ace_header)->SidStart))
3984 add = FALSE;
3985 break;
3986 case SYSTEM_AUDIT_ACE_TYPE:
3987 if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
3988 add = FALSE;
3989 break;
3990 case SYSTEM_ALARM_ACE_TYPE:
3991 if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
3992 add = FALSE;
3993 break;
3994 default:
3995 FIXME("unhandled ace type %d\n", old_ace_header->AceType);
3998 if (!add)
3999 break;
4002 if (add)
4003 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
4004 if (status != STATUS_SUCCESS)
4006 WARN("RtlAddAce failed with error 0x%08x\n", status);
4007 ret = RtlNtStatusToDosError(status);
4008 break;
4013 exit:
4014 heap_free(ppsid);
4015 return ret;
4018 /******************************************************************************
4019 * SetNamedSecurityInfoA [ADVAPI32.@]
4021 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
4022 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
4023 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
4025 LPWSTR wstr;
4026 DWORD r;
4028 TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
4029 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
4031 wstr = SERV_dup(pObjectName);
4032 r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
4033 psidGroup, pDacl, pSacl );
4035 heap_free( wstr );
4037 return r;
4040 BOOL WINAPI SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation,
4041 PSECURITY_DESCRIPTOR ModificationDescriptor,
4042 PSECURITY_DESCRIPTOR* ObjectsSecurityDescriptor,
4043 PGENERIC_MAPPING GenericMapping,
4044 HANDLE Token )
4046 FIXME("0x%08x %p %p %p %p - stub\n", SecurityInformation, ModificationDescriptor,
4047 ObjectsSecurityDescriptor, GenericMapping, Token);
4049 return TRUE;
4052 BOOL WINAPI AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
4054 return RtlAreAllAccessesGranted( GrantedAccess, DesiredAccess );
4057 /******************************************************************************
4058 * AreAnyAccessesGranted [ADVAPI32.@]
4060 * Determines whether or not any of a set of specified access permissions have
4061 * been granted or not.
4063 * PARAMS
4064 * GrantedAccess [I] The permissions that have been granted.
4065 * DesiredAccess [I] The permissions that you want to have.
4067 * RETURNS
4068 * Nonzero if any of the permissions have been granted, zero if none of the
4069 * permissions have been granted.
4072 BOOL WINAPI AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
4074 return RtlAreAnyAccessesGranted( GrantedAccess, DesiredAccess );
4077 /******************************************************************************
4078 * SetNamedSecurityInfoW [ADVAPI32.@]
4080 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
4081 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
4082 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
4084 DWORD access = 0;
4085 HANDLE handle;
4086 DWORD err;
4088 TRACE( "%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
4089 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
4091 if (!pObjectName) return ERROR_INVALID_PARAMETER;
4093 if (SecurityInfo & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION))
4094 access |= WRITE_OWNER;
4095 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4096 access |= WRITE_DAC;
4097 if (SecurityInfo & SACL_SECURITY_INFORMATION)
4098 access |= ACCESS_SYSTEM_SECURITY;
4100 switch (ObjectType)
4102 case SE_SERVICE:
4103 if (!(err = get_security_service( pObjectName, access, &handle )))
4105 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4106 CloseServiceHandle( handle );
4108 break;
4109 case SE_REGISTRY_KEY:
4110 if (!(err = get_security_regkey( pObjectName, access, &handle )))
4112 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4113 RegCloseKey( handle );
4115 break;
4116 case SE_FILE_OBJECT:
4117 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4118 access |= READ_CONTROL;
4119 if (!(err = get_security_file( pObjectName, access, &handle )))
4121 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4122 CloseHandle( handle );
4124 break;
4125 default:
4126 FIXME( "Object type %d is not currently supported.\n", ObjectType );
4127 return ERROR_SUCCESS;
4129 return err;
4132 /******************************************************************************
4133 * GetExplicitEntriesFromAclA [ADVAPI32.@]
4135 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
4136 PEXPLICIT_ACCESSA* pListOfExplicitEntries)
4138 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
4139 return ERROR_CALL_NOT_IMPLEMENTED;
4142 /******************************************************************************
4143 * GetExplicitEntriesFromAclW [ADVAPI32.@]
4145 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
4146 PEXPLICIT_ACCESSW* pListOfExplicitEntries)
4148 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
4149 return ERROR_CALL_NOT_IMPLEMENTED;
4152 /******************************************************************************
4153 * GetAuditedPermissionsFromAclA [ADVAPI32.@]
4155 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
4156 PACCESS_MASK pFailedAuditRights)
4158 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
4159 return ERROR_CALL_NOT_IMPLEMENTED;
4163 /******************************************************************************
4164 * GetAuditedPermissionsFromAclW [ADVAPI32.@]
4166 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
4167 PACCESS_MASK pFailedAuditRights)
4169 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
4170 return ERROR_CALL_NOT_IMPLEMENTED;
4174 /******************************************************************************
4175 * ParseAclStringFlags
4177 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
4179 DWORD flags = 0;
4180 LPCWSTR szAcl = *StringAcl;
4182 while (*szAcl != '(')
4184 if (*szAcl == 'P')
4186 flags |= SE_DACL_PROTECTED;
4188 else if (*szAcl == 'A')
4190 szAcl++;
4191 if (*szAcl == 'R')
4192 flags |= SE_DACL_AUTO_INHERIT_REQ;
4193 else if (*szAcl == 'I')
4194 flags |= SE_DACL_AUTO_INHERITED;
4196 szAcl++;
4199 *StringAcl = szAcl;
4200 return flags;
4203 /******************************************************************************
4204 * ParseAceStringType
4206 static const ACEFLAG AceType[] =
4208 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
4209 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
4210 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
4211 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
4212 { SDDL_MANDATORY_LABEL,SYSTEM_MANDATORY_LABEL_ACE_TYPE },
4214 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
4215 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
4216 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
4217 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
4219 { NULL, 0 },
4222 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
4224 UINT len = 0;
4225 LPCWSTR szAcl = *StringAcl;
4226 const ACEFLAG *lpaf = AceType;
4228 while (*szAcl == ' ')
4229 szAcl++;
4231 while (lpaf->wstr &&
4232 (len = strlenW(lpaf->wstr)) &&
4233 strncmpW(lpaf->wstr, szAcl, len))
4234 lpaf++;
4236 if (!lpaf->wstr)
4237 return 0;
4239 *StringAcl = szAcl + len;
4240 return lpaf->value;
4244 /******************************************************************************
4245 * ParseAceStringFlags
4247 static const ACEFLAG AceFlags[] =
4249 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
4250 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
4251 { SDDL_INHERITED, INHERITED_ACE },
4252 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
4253 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
4254 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
4255 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
4256 { NULL, 0 },
4259 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
4261 UINT len = 0;
4262 BYTE flags = 0;
4263 LPCWSTR szAcl = *StringAcl;
4265 while (*szAcl == ' ')
4266 szAcl++;
4268 while (*szAcl != ';')
4270 const ACEFLAG *lpaf = AceFlags;
4272 while (lpaf->wstr &&
4273 (len = strlenW(lpaf->wstr)) &&
4274 strncmpW(lpaf->wstr, szAcl, len))
4275 lpaf++;
4277 if (!lpaf->wstr)
4278 return 0;
4280 flags |= lpaf->value;
4281 szAcl += len;
4284 *StringAcl = szAcl;
4285 return flags;
4289 /******************************************************************************
4290 * ParseAceStringRights
4292 static const ACEFLAG AceRights[] =
4294 { SDDL_GENERIC_ALL, GENERIC_ALL },
4295 { SDDL_GENERIC_READ, GENERIC_READ },
4296 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
4297 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
4299 { SDDL_READ_CONTROL, READ_CONTROL },
4300 { SDDL_STANDARD_DELETE, DELETE },
4301 { SDDL_WRITE_DAC, WRITE_DAC },
4302 { SDDL_WRITE_OWNER, WRITE_OWNER },
4304 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
4305 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
4306 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
4307 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
4308 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
4309 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
4310 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
4311 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
4312 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
4314 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
4315 { SDDL_FILE_READ, FILE_GENERIC_READ },
4316 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
4317 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
4319 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
4320 { SDDL_KEY_READ, KEY_READ },
4321 { SDDL_KEY_WRITE, KEY_WRITE },
4322 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
4324 { SDDL_NO_READ_UP, SYSTEM_MANDATORY_LABEL_NO_READ_UP },
4325 { SDDL_NO_WRITE_UP, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP },
4326 { SDDL_NO_EXECUTE_UP, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP },
4327 { NULL, 0 },
4330 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
4332 UINT len = 0;
4333 DWORD rights = 0;
4334 LPCWSTR szAcl = *StringAcl;
4336 while (*szAcl == ' ')
4337 szAcl++;
4339 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
4341 LPCWSTR p = szAcl;
4343 while (*p && *p != ';')
4344 p++;
4346 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
4348 rights = strtoulW(szAcl, NULL, 16);
4349 szAcl = p;
4351 else
4352 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
4354 else
4356 while (*szAcl != ';')
4358 const ACEFLAG *lpaf = AceRights;
4360 while (lpaf->wstr &&
4361 (len = strlenW(lpaf->wstr)) &&
4362 strncmpW(lpaf->wstr, szAcl, len))
4364 lpaf++;
4367 if (!lpaf->wstr)
4368 return 0;
4370 rights |= lpaf->value;
4371 szAcl += len;
4375 *StringAcl = szAcl;
4376 return rights;
4380 /******************************************************************************
4381 * ParseStringAclToAcl
4383 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
4385 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
4386 PACL pAcl, LPDWORD cBytes)
4388 DWORD val;
4389 DWORD sidlen;
4390 DWORD length = sizeof(ACL);
4391 DWORD acesize = 0;
4392 DWORD acecount = 0;
4393 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
4394 DWORD error = ERROR_INVALID_ACL;
4396 TRACE("%s\n", debugstr_w(StringAcl));
4398 if (!StringAcl)
4399 return FALSE;
4401 if (pAcl) /* pAce is only useful if we're setting values */
4402 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
4404 /* Parse ACL flags */
4405 *lpdwFlags = ParseAclStringFlags(&StringAcl);
4407 /* Parse ACE */
4408 while (*StringAcl == '(')
4410 StringAcl++;
4412 /* Parse ACE type */
4413 val = ParseAceStringType(&StringAcl);
4414 if (pAce)
4415 pAce->Header.AceType = (BYTE) val;
4416 if (*StringAcl != ';')
4418 error = RPC_S_INVALID_STRING_UUID;
4419 goto lerr;
4421 StringAcl++;
4423 /* Parse ACE flags */
4424 val = ParseAceStringFlags(&StringAcl);
4425 if (pAce)
4426 pAce->Header.AceFlags = (BYTE) val;
4427 if (*StringAcl != ';')
4428 goto lerr;
4429 StringAcl++;
4431 /* Parse ACE rights */
4432 val = ParseAceStringRights(&StringAcl);
4433 if (pAce)
4434 pAce->Mask = val;
4435 if (*StringAcl != ';')
4436 goto lerr;
4437 StringAcl++;
4439 /* Parse ACE object guid */
4440 while (*StringAcl == ' ')
4441 StringAcl++;
4442 if (*StringAcl != ';')
4444 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4445 goto lerr;
4447 StringAcl++;
4449 /* Parse ACE inherit object guid */
4450 while (*StringAcl == ' ')
4451 StringAcl++;
4452 if (*StringAcl != ';')
4454 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4455 goto lerr;
4457 StringAcl++;
4459 /* Parse ACE account sid */
4460 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
4462 while (*StringAcl && *StringAcl != ')')
4463 StringAcl++;
4466 if (*StringAcl != ')')
4467 goto lerr;
4468 StringAcl++;
4470 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
4471 length += acesize;
4472 if (pAce)
4474 pAce->Header.AceSize = acesize;
4475 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
4477 acecount++;
4480 *cBytes = length;
4482 if (length > 0xffff)
4484 ERR("ACL too large\n");
4485 goto lerr;
4488 if (pAcl)
4490 pAcl->AclRevision = ACL_REVISION;
4491 pAcl->Sbz1 = 0;
4492 pAcl->AclSize = length;
4493 pAcl->AceCount = acecount++;
4494 pAcl->Sbz2 = 0;
4496 return TRUE;
4498 lerr:
4499 SetLastError(error);
4500 WARN("Invalid ACE string format\n");
4501 return FALSE;
4505 /******************************************************************************
4506 * ParseStringSecurityDescriptorToSecurityDescriptor
4508 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
4509 LPCWSTR StringSecurityDescriptor,
4510 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
4511 LPDWORD cBytes)
4513 BOOL bret = FALSE;
4514 WCHAR toktype;
4515 WCHAR tok[MAX_PATH];
4516 LPCWSTR lptoken;
4517 LPBYTE lpNext = NULL;
4518 DWORD len;
4520 *cBytes = sizeof(SECURITY_DESCRIPTOR);
4522 if (SecurityDescriptor)
4523 lpNext = (LPBYTE)(SecurityDescriptor + 1);
4525 while (*StringSecurityDescriptor == ' ')
4526 StringSecurityDescriptor++;
4528 while (*StringSecurityDescriptor)
4530 toktype = *StringSecurityDescriptor;
4532 /* Expect char identifier followed by ':' */
4533 StringSecurityDescriptor++;
4534 if (*StringSecurityDescriptor != ':')
4536 SetLastError(ERROR_INVALID_PARAMETER);
4537 goto lend;
4539 StringSecurityDescriptor++;
4541 /* Extract token */
4542 lptoken = StringSecurityDescriptor;
4543 while (*lptoken && *lptoken != ':')
4544 lptoken++;
4546 if (*lptoken)
4547 lptoken--;
4549 len = lptoken - StringSecurityDescriptor;
4550 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
4551 tok[len] = 0;
4553 switch (toktype)
4555 case 'O':
4557 DWORD bytes;
4559 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4560 goto lend;
4562 if (SecurityDescriptor)
4564 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
4565 lpNext += bytes; /* Advance to next token */
4568 *cBytes += bytes;
4570 break;
4573 case 'G':
4575 DWORD bytes;
4577 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4578 goto lend;
4580 if (SecurityDescriptor)
4582 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
4583 lpNext += bytes; /* Advance to next token */
4586 *cBytes += bytes;
4588 break;
4591 case 'D':
4593 DWORD flags;
4594 DWORD bytes;
4596 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4597 goto lend;
4599 if (SecurityDescriptor)
4601 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
4602 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
4603 lpNext += bytes; /* Advance to next token */
4606 *cBytes += bytes;
4608 break;
4611 case 'S':
4613 DWORD flags;
4614 DWORD bytes;
4616 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4617 goto lend;
4619 if (SecurityDescriptor)
4621 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
4622 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
4623 lpNext += bytes; /* Advance to next token */
4626 *cBytes += bytes;
4628 break;
4631 default:
4632 FIXME("Unknown token\n");
4633 SetLastError(ERROR_INVALID_PARAMETER);
4634 goto lend;
4637 StringSecurityDescriptor = lptoken;
4640 bret = TRUE;
4642 lend:
4643 return bret;
4646 /******************************************************************************
4647 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
4649 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
4650 LPCSTR StringSecurityDescriptor,
4651 DWORD StringSDRevision,
4652 PSECURITY_DESCRIPTOR* SecurityDescriptor,
4653 PULONG SecurityDescriptorSize)
4655 BOOL ret;
4656 LPWSTR StringSecurityDescriptorW;
4658 if(!StringSecurityDescriptor)
4659 return FALSE;
4661 StringSecurityDescriptorW = SERV_dup(StringSecurityDescriptor);
4662 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
4663 StringSDRevision, SecurityDescriptor,
4664 SecurityDescriptorSize);
4665 heap_free(StringSecurityDescriptorW);
4667 return ret;
4670 /******************************************************************************
4671 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
4673 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
4674 LPCWSTR StringSecurityDescriptor,
4675 DWORD StringSDRevision,
4676 PSECURITY_DESCRIPTOR* SecurityDescriptor,
4677 PULONG SecurityDescriptorSize)
4679 DWORD cBytes;
4680 SECURITY_DESCRIPTOR* psd;
4681 BOOL bret = FALSE;
4683 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
4685 if (GetVersion() & 0x80000000)
4687 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4688 goto lend;
4690 else if (!StringSecurityDescriptor || !SecurityDescriptor)
4692 SetLastError(ERROR_INVALID_PARAMETER);
4693 goto lend;
4695 else if (StringSDRevision != SID_REVISION)
4697 SetLastError(ERROR_UNKNOWN_REVISION);
4698 goto lend;
4701 /* Compute security descriptor length */
4702 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4703 NULL, &cBytes))
4704 goto lend;
4706 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
4707 if (!psd) goto lend;
4709 psd->Revision = SID_REVISION;
4710 psd->Control |= SE_SELF_RELATIVE;
4712 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4713 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
4715 LocalFree(psd);
4716 goto lend;
4719 if (SecurityDescriptorSize)
4720 *SecurityDescriptorSize = cBytes;
4722 bret = TRUE;
4724 lend:
4725 TRACE(" ret=%d\n", bret);
4726 return bret;
4729 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
4731 if (cch == -1)
4732 cch = strlenW(string);
4734 if (plen)
4735 *plen += cch;
4737 if (pwptr)
4739 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
4740 *pwptr += cch;
4744 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
4746 DWORD i;
4747 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
4748 WCHAR subauthfmt[] = { '-','%','u',0 };
4749 WCHAR buf[26];
4750 SID *pisid = psid;
4752 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
4754 SetLastError(ERROR_INVALID_SID);
4755 return FALSE;
4758 if (pisid->IdentifierAuthority.Value[0] ||
4759 pisid->IdentifierAuthority.Value[1])
4761 FIXME("not matching MS' bugs\n");
4762 SetLastError(ERROR_INVALID_SID);
4763 return FALSE;
4766 sprintfW( buf, fmt, pisid->Revision,
4767 MAKELONG(
4768 MAKEWORD( pisid->IdentifierAuthority.Value[5],
4769 pisid->IdentifierAuthority.Value[4] ),
4770 MAKEWORD( pisid->IdentifierAuthority.Value[3],
4771 pisid->IdentifierAuthority.Value[2] )
4772 ) );
4773 DumpString(buf, -1, pwptr, plen);
4775 for( i=0; i<pisid->SubAuthorityCount; i++ )
4777 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
4778 DumpString(buf, -1, pwptr, plen);
4780 return TRUE;
4783 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
4785 size_t i;
4786 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
4788 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
4790 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
4791 return TRUE;
4795 return DumpSidNumeric(psid, pwptr, plen);
4798 static const LPCWSTR AceRightBitNames[32] = {
4799 SDDL_CREATE_CHILD, /* 0 */
4800 SDDL_DELETE_CHILD,
4801 SDDL_LIST_CHILDREN,
4802 SDDL_SELF_WRITE,
4803 SDDL_READ_PROPERTY, /* 4 */
4804 SDDL_WRITE_PROPERTY,
4805 SDDL_DELETE_TREE,
4806 SDDL_LIST_OBJECT,
4807 SDDL_CONTROL_ACCESS, /* 8 */
4808 NULL,
4809 NULL,
4810 NULL,
4811 NULL, /* 12 */
4812 NULL,
4813 NULL,
4814 NULL,
4815 SDDL_STANDARD_DELETE, /* 16 */
4816 SDDL_READ_CONTROL,
4817 SDDL_WRITE_DAC,
4818 SDDL_WRITE_OWNER,
4819 NULL, /* 20 */
4820 NULL,
4821 NULL,
4822 NULL,
4823 NULL, /* 24 */
4824 NULL,
4825 NULL,
4826 NULL,
4827 SDDL_GENERIC_ALL, /* 28 */
4828 SDDL_GENERIC_EXECUTE,
4829 SDDL_GENERIC_WRITE,
4830 SDDL_GENERIC_READ
4833 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
4835 static const WCHAR fmtW[] = {'0','x','%','x',0};
4836 WCHAR buf[15];
4837 size_t i;
4839 if (mask == 0)
4840 return;
4842 /* first check if the right have name */
4843 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
4845 if (AceRights[i].wstr == NULL)
4846 break;
4847 if (mask == AceRights[i].value)
4849 DumpString(AceRights[i].wstr, -1, pwptr, plen);
4850 return;
4854 /* then check if it can be built from bit names */
4855 for (i = 0; i < 32; i++)
4857 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
4859 /* can't be built from bit names */
4860 sprintfW(buf, fmtW, mask);
4861 DumpString(buf, -1, pwptr, plen);
4862 return;
4866 /* build from bit names */
4867 for (i = 0; i < 32; i++)
4868 if (mask & (1 << i))
4869 DumpString(AceRightBitNames[i], -1, pwptr, plen);
4872 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
4874 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
4875 static const WCHAR openbr = '(';
4876 static const WCHAR closebr = ')';
4877 static const WCHAR semicolon = ';';
4879 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
4881 SetLastError(ERROR_INVALID_ACL);
4882 return FALSE;
4885 piace = pace;
4886 DumpString(&openbr, 1, pwptr, plen);
4887 switch (piace->Header.AceType)
4889 case ACCESS_ALLOWED_ACE_TYPE:
4890 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
4891 break;
4892 case ACCESS_DENIED_ACE_TYPE:
4893 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
4894 break;
4895 case SYSTEM_AUDIT_ACE_TYPE:
4896 DumpString(SDDL_AUDIT, -1, pwptr, plen);
4897 break;
4898 case SYSTEM_ALARM_ACE_TYPE:
4899 DumpString(SDDL_ALARM, -1, pwptr, plen);
4900 break;
4902 DumpString(&semicolon, 1, pwptr, plen);
4904 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
4905 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
4906 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
4907 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
4908 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
4909 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
4910 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
4911 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
4912 if (piace->Header.AceFlags & INHERITED_ACE)
4913 DumpString(SDDL_INHERITED, -1, pwptr, plen);
4914 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
4915 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
4916 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
4917 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
4918 DumpString(&semicolon, 1, pwptr, plen);
4919 DumpRights(piace->Mask, pwptr, plen);
4920 DumpString(&semicolon, 1, pwptr, plen);
4921 /* objects not supported */
4922 DumpString(&semicolon, 1, pwptr, plen);
4923 /* objects not supported */
4924 DumpString(&semicolon, 1, pwptr, plen);
4925 if (!DumpSid(&piace->SidStart, pwptr, plen))
4926 return FALSE;
4927 DumpString(&closebr, 1, pwptr, plen);
4928 return TRUE;
4931 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
4933 WORD count;
4934 UINT i;
4936 if (protected)
4937 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
4938 if (autoInheritReq)
4939 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
4940 if (autoInherited)
4941 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
4943 if (pacl == NULL)
4944 return TRUE;
4946 if (!IsValidAcl(pacl))
4947 return FALSE;
4949 count = pacl->AceCount;
4950 for (i = 0; i < count; i++)
4952 LPVOID ace;
4953 if (!GetAce(pacl, i, &ace))
4954 return FALSE;
4955 if (!DumpAce(ace, pwptr, plen))
4956 return FALSE;
4959 return TRUE;
4962 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4964 static const WCHAR prefix[] = {'O',':',0};
4965 BOOL bDefaulted;
4966 PSID psid;
4968 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
4969 return FALSE;
4971 if (psid == NULL)
4972 return TRUE;
4974 DumpString(prefix, -1, pwptr, plen);
4975 if (!DumpSid(psid, pwptr, plen))
4976 return FALSE;
4977 return TRUE;
4980 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4982 static const WCHAR prefix[] = {'G',':',0};
4983 BOOL bDefaulted;
4984 PSID psid;
4986 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
4987 return FALSE;
4989 if (psid == NULL)
4990 return TRUE;
4992 DumpString(prefix, -1, pwptr, plen);
4993 if (!DumpSid(psid, pwptr, plen))
4994 return FALSE;
4995 return TRUE;
4998 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
5000 static const WCHAR dacl[] = {'D',':',0};
5001 SECURITY_DESCRIPTOR_CONTROL control;
5002 BOOL present, defaulted;
5003 DWORD revision;
5004 PACL pacl;
5006 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
5007 return FALSE;
5009 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
5010 return FALSE;
5012 if (!present)
5013 return TRUE;
5015 DumpString(dacl, 2, pwptr, plen);
5016 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
5017 return FALSE;
5018 return TRUE;
5021 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
5023 static const WCHAR sacl[] = {'S',':',0};
5024 SECURITY_DESCRIPTOR_CONTROL control;
5025 BOOL present, defaulted;
5026 DWORD revision;
5027 PACL pacl;
5029 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
5030 return FALSE;
5032 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
5033 return FALSE;
5035 if (!present)
5036 return TRUE;
5038 DumpString(sacl, 2, pwptr, plen);
5039 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
5040 return FALSE;
5041 return TRUE;
5044 /******************************************************************************
5045 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
5047 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
5049 ULONG len;
5050 WCHAR *wptr, *wstr;
5052 if (SDRevision != SDDL_REVISION_1)
5054 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
5055 SetLastError(ERROR_UNKNOWN_REVISION);
5056 return FALSE;
5059 len = 0;
5060 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
5061 if (!DumpOwner(SecurityDescriptor, NULL, &len))
5062 return FALSE;
5063 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
5064 if (!DumpGroup(SecurityDescriptor, NULL, &len))
5065 return FALSE;
5066 if (RequestedInformation & DACL_SECURITY_INFORMATION)
5067 if (!DumpDacl(SecurityDescriptor, NULL, &len))
5068 return FALSE;
5069 if (RequestedInformation & SACL_SECURITY_INFORMATION)
5070 if (!DumpSacl(SecurityDescriptor, NULL, &len))
5071 return FALSE;
5073 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
5074 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
5075 if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) {
5076 LocalFree (wstr);
5077 return FALSE;
5079 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
5080 if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) {
5081 LocalFree (wstr);
5082 return FALSE;
5084 if (RequestedInformation & DACL_SECURITY_INFORMATION)
5085 if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) {
5086 LocalFree (wstr);
5087 return FALSE;
5089 if (RequestedInformation & SACL_SECURITY_INFORMATION)
5090 if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) {
5091 LocalFree (wstr);
5092 return FALSE;
5094 *wptr = 0;
5096 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
5097 *OutputString = wstr;
5098 if (OutputLen)
5099 *OutputLen = strlenW(*OutputString)+1;
5100 return TRUE;
5103 /******************************************************************************
5104 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
5106 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
5108 LPWSTR wstr;
5109 ULONG len;
5110 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
5112 int lenA;
5114 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
5115 *OutputString = heap_alloc(lenA);
5116 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
5117 LocalFree(wstr);
5119 if (OutputLen != NULL)
5120 *OutputLen = lenA;
5121 return TRUE;
5123 else
5125 *OutputString = NULL;
5126 if (OutputLen)
5127 *OutputLen = 0;
5128 return FALSE;
5132 /******************************************************************************
5133 * ConvertStringSidToSidW [ADVAPI32.@]
5135 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
5137 BOOL bret = FALSE;
5138 DWORD cBytes;
5140 TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
5141 if (GetVersion() & 0x80000000)
5142 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5143 else if (!StringSid || !Sid)
5144 SetLastError(ERROR_INVALID_PARAMETER);
5145 else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
5147 PSID pSid = *Sid = LocalAlloc(0, cBytes);
5149 bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
5150 if (!bret)
5151 LocalFree(*Sid);
5153 return bret;
5156 /******************************************************************************
5157 * ConvertStringSidToSidA [ADVAPI32.@]
5159 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
5161 BOOL bret = FALSE;
5163 TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
5164 if (GetVersion() & 0x80000000)
5165 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5166 else if (!StringSid || !Sid)
5167 SetLastError(ERROR_INVALID_PARAMETER);
5168 else
5170 WCHAR *wStringSid = SERV_dup(StringSid);
5171 bret = ConvertStringSidToSidW(wStringSid, Sid);
5172 heap_free(wStringSid);
5174 return bret;
5177 /******************************************************************************
5178 * ConvertSidToStringSidW [ADVAPI32.@]
5180 * format of SID string is:
5181 * S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
5182 * where
5183 * <rev> is the revision of the SID encoded as decimal
5184 * <auth> is the identifier authority encoded as hex
5185 * <subauthN> is the subauthority id encoded as decimal
5187 BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
5189 DWORD len = 0;
5190 LPWSTR wstr, wptr;
5192 TRACE("%p %p\n", pSid, pstr );
5194 len = 0;
5195 if (!DumpSidNumeric(pSid, NULL, &len))
5196 return FALSE;
5197 wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
5198 DumpSidNumeric(pSid, &wptr, NULL);
5199 *wptr = 0;
5201 *pstr = wstr;
5202 return TRUE;
5205 /******************************************************************************
5206 * ConvertSidToStringSidA [ADVAPI32.@]
5208 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
5210 LPWSTR wstr = NULL;
5211 LPSTR str;
5212 UINT len;
5214 TRACE("%p %p\n", pSid, pstr );
5216 if( !ConvertSidToStringSidW( pSid, &wstr ) )
5217 return FALSE;
5219 len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
5220 str = LocalAlloc( 0, len );
5221 WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
5222 LocalFree( wstr );
5224 *pstr = str;
5226 return TRUE;
5229 BOOL WINAPI ConvertToAutoInheritPrivateObjectSecurity(
5230 PSECURITY_DESCRIPTOR pdesc,
5231 PSECURITY_DESCRIPTOR cdesc,
5232 PSECURITY_DESCRIPTOR* ndesc,
5233 GUID* objtype,
5234 BOOL isdir,
5235 PGENERIC_MAPPING genmap )
5237 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
5239 return FALSE;
5242 BOOL WINAPI CreatePrivateObjectSecurity(
5243 PSECURITY_DESCRIPTOR ParentDescriptor,
5244 PSECURITY_DESCRIPTOR CreatorDescriptor,
5245 PSECURITY_DESCRIPTOR* NewDescriptor,
5246 BOOL IsDirectoryObject,
5247 HANDLE Token,
5248 PGENERIC_MAPPING GenericMapping )
5250 SECURITY_DESCRIPTOR_RELATIVE *relative;
5251 DWORD needed, offset;
5252 BYTE *buffer;
5254 FIXME("%p %p %p %d %p %p - returns fake SECURITY_DESCRIPTOR\n", ParentDescriptor,
5255 CreatorDescriptor, NewDescriptor, IsDirectoryObject, Token, GenericMapping);
5257 needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5258 needed += sizeof(sidWorld);
5259 needed += sizeof(sidWorld);
5260 needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5261 needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5263 if (!(buffer = heap_alloc( needed ))) return FALSE;
5264 relative = (SECURITY_DESCRIPTOR_RELATIVE *)buffer;
5265 if (!InitializeSecurityDescriptor( relative, SECURITY_DESCRIPTOR_REVISION ))
5267 heap_free( buffer );
5268 return FALSE;
5270 relative->Control |= SE_SELF_RELATIVE;
5271 offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5273 memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5274 relative->Owner = offset;
5275 offset += sizeof(sidWorld);
5277 memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5278 relative->Group = offset;
5279 offset += sizeof(sidWorld);
5281 GetWorldAccessACL( (ACL *)(buffer + offset) );
5282 relative->Dacl = offset;
5283 offset += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5285 GetWorldAccessACL( (ACL *)(buffer + offset) );
5286 relative->Sacl = offset;
5288 *NewDescriptor = relative;
5289 return TRUE;
5292 BOOL WINAPI DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR* ObjectDescriptor )
5294 FIXME("%p - stub\n", ObjectDescriptor);
5296 heap_free( *ObjectDescriptor );
5297 return TRUE;
5300 BOOL WINAPI CreateProcessAsUserA(
5301 HANDLE hToken,
5302 LPCSTR lpApplicationName,
5303 LPSTR lpCommandLine,
5304 LPSECURITY_ATTRIBUTES lpProcessAttributes,
5305 LPSECURITY_ATTRIBUTES lpThreadAttributes,
5306 BOOL bInheritHandles,
5307 DWORD dwCreationFlags,
5308 LPVOID lpEnvironment,
5309 LPCSTR lpCurrentDirectory,
5310 LPSTARTUPINFOA lpStartupInfo,
5311 LPPROCESS_INFORMATION lpProcessInformation )
5313 BOOL ret;
5314 WCHAR *appW, *cmdlnW, *cwdW;
5315 STARTUPINFOW sinfo;
5317 TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_a(lpApplicationName),
5318 debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
5319 dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5321 appW = SERV_dup(lpApplicationName);
5322 cmdlnW = SERV_dup(lpCommandLine);
5323 cwdW = SERV_dup(lpCurrentDirectory);
5324 sinfo.cb = sizeof(sinfo);
5325 sinfo.lpReserved = SERV_dup(lpStartupInfo->lpReserved);
5326 sinfo.lpDesktop = SERV_dup(lpStartupInfo->lpDesktop);
5327 sinfo.lpTitle = SERV_dup(lpStartupInfo->lpTitle);
5328 sinfo.dwX = lpStartupInfo->dwX;
5329 sinfo.dwY = lpStartupInfo->dwY;
5330 sinfo.dwXSize = lpStartupInfo->dwXSize;
5331 sinfo.dwYSize = lpStartupInfo->dwYSize;
5332 sinfo.dwXCountChars = lpStartupInfo->dwXCountChars;
5333 sinfo.dwYCountChars = lpStartupInfo->dwYCountChars;
5334 sinfo.dwFillAttribute = lpStartupInfo->dwFillAttribute;
5335 sinfo.dwFlags = lpStartupInfo->dwFlags;
5336 sinfo.wShowWindow = lpStartupInfo->wShowWindow;
5337 sinfo.cbReserved2 = lpStartupInfo->cbReserved2;
5338 sinfo.lpReserved2 = lpStartupInfo->lpReserved2;
5339 sinfo.hStdInput = lpStartupInfo->hStdInput;
5340 sinfo.hStdOutput = lpStartupInfo->hStdOutput;
5341 sinfo.hStdError = lpStartupInfo->hStdError;
5342 ret = CreateProcessAsUserW(hToken, appW, cmdlnW, lpProcessAttributes,
5343 lpThreadAttributes, bInheritHandles, dwCreationFlags,
5344 lpEnvironment, cwdW, &sinfo, lpProcessInformation);
5345 heap_free(appW);
5346 heap_free(cmdlnW);
5347 heap_free(cwdW);
5348 heap_free(sinfo.lpReserved);
5349 heap_free(sinfo.lpDesktop);
5350 heap_free(sinfo.lpTitle);
5352 return ret;
5355 BOOL WINAPI CreateProcessAsUserW(
5356 HANDLE hToken,
5357 LPCWSTR lpApplicationName,
5358 LPWSTR lpCommandLine,
5359 LPSECURITY_ATTRIBUTES lpProcessAttributes,
5360 LPSECURITY_ATTRIBUTES lpThreadAttributes,
5361 BOOL bInheritHandles,
5362 DWORD dwCreationFlags,
5363 LPVOID lpEnvironment,
5364 LPCWSTR lpCurrentDirectory,
5365 LPSTARTUPINFOW lpStartupInfo,
5366 LPPROCESS_INFORMATION lpProcessInformation )
5368 FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - semi-stub\n", hToken,
5369 debugstr_w(lpApplicationName), debugstr_w(lpCommandLine), lpProcessAttributes,
5370 lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
5371 debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5373 /* We should create the process with a suspended main thread */
5374 if (!CreateProcessW (lpApplicationName,
5375 lpCommandLine,
5376 lpProcessAttributes,
5377 lpThreadAttributes,
5378 bInheritHandles,
5379 dwCreationFlags, /* CREATE_SUSPENDED */
5380 lpEnvironment,
5381 lpCurrentDirectory,
5382 lpStartupInfo,
5383 lpProcessInformation))
5385 return FALSE;
5388 return TRUE;
5391 /******************************************************************************
5392 * CreateProcessWithLogonW
5394 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
5395 LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
5396 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
5398 FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
5399 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
5400 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
5401 lpStartupInfo, lpProcessInformation);
5403 return FALSE;
5406 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line,
5407 DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info,
5408 PROCESS_INFORMATION *process_information )
5410 FIXME("%p 0x%08x %s %s 0x%08x %p %s %p %p - semi-stub\n", token,
5411 logon_flags, debugstr_w(application_name), debugstr_w(command_line),
5412 creation_flags, environment, debugstr_w(current_directory),
5413 startup_info, process_information);
5415 /* FIXME: check if handles should be inherited */
5416 return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment,
5417 current_directory, startup_info, process_information );
5420 /******************************************************************************
5421 * DuplicateTokenEx [ADVAPI32.@]
5423 BOOL WINAPI DuplicateTokenEx(
5424 HANDLE ExistingTokenHandle, DWORD dwDesiredAccess,
5425 LPSECURITY_ATTRIBUTES lpTokenAttributes,
5426 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5427 TOKEN_TYPE TokenType,
5428 PHANDLE DuplicateTokenHandle )
5430 OBJECT_ATTRIBUTES ObjectAttributes;
5432 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
5433 ImpersonationLevel, TokenType, DuplicateTokenHandle);
5435 InitializeObjectAttributes(
5436 &ObjectAttributes,
5437 NULL,
5438 (lpTokenAttributes && lpTokenAttributes->bInheritHandle) ? OBJ_INHERIT : 0,
5439 NULL,
5440 lpTokenAttributes ? lpTokenAttributes->lpSecurityDescriptor : NULL );
5442 return set_ntstatus( NtDuplicateToken( ExistingTokenHandle,
5443 dwDesiredAccess,
5444 &ObjectAttributes,
5445 ImpersonationLevel,
5446 TokenType,
5447 DuplicateTokenHandle ) );
5450 BOOL WINAPI DuplicateToken(
5451 HANDLE ExistingTokenHandle,
5452 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5453 PHANDLE DuplicateTokenHandle )
5455 return DuplicateTokenEx( ExistingTokenHandle, TOKEN_IMPERSONATE | TOKEN_QUERY,
5456 NULL, ImpersonationLevel, TokenImpersonation,
5457 DuplicateTokenHandle );
5460 /******************************************************************************
5461 * ComputeStringSidSize
5463 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
5465 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
5467 int ctok = 0;
5468 while (*StringSid)
5470 if (*StringSid == '-')
5471 ctok++;
5472 StringSid++;
5475 if (ctok >= 3)
5476 return GetSidLengthRequired(ctok - 2);
5478 else /* String constant format - Only available in winxp and above */
5480 unsigned int i;
5482 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5483 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5484 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
5486 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
5487 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
5489 MAX_SID local;
5490 ADVAPI_GetComputerSid(&local);
5491 return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1);
5496 return GetSidLengthRequired(0);
5499 /******************************************************************************
5500 * ParseStringSidToSid
5502 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
5504 BOOL bret = FALSE;
5505 SID* pisid=pSid;
5507 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
5508 if (!StringSid)
5510 SetLastError(ERROR_INVALID_PARAMETER);
5511 TRACE("StringSid is NULL, returning FALSE\n");
5512 return FALSE;
5515 while (*StringSid == ' ')
5516 StringSid++;
5518 *cBytes = ComputeStringSidSize(StringSid);
5519 if (!pisid) /* Simply compute the size */
5521 TRACE("only size requested, returning TRUE with %d\n", *cBytes);
5522 return TRUE;
5525 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
5527 DWORD i = 0, identAuth;
5528 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
5530 StringSid += 2; /* Advance to Revision */
5531 pisid->Revision = atoiW(StringSid);
5533 if (pisid->Revision != SDDL_REVISION)
5535 TRACE("Revision %d is unknown\n", pisid->Revision);
5536 goto lend; /* ERROR_INVALID_SID */
5538 if (csubauth == 0)
5540 TRACE("SubAuthorityCount is 0\n");
5541 goto lend; /* ERROR_INVALID_SID */
5544 pisid->SubAuthorityCount = csubauth;
5546 /* Advance to identifier authority */
5547 while (*StringSid && *StringSid != '-')
5548 StringSid++;
5549 if (*StringSid == '-')
5550 StringSid++;
5552 /* MS' implementation can't handle values greater than 2^32 - 1, so
5553 * we don't either; assume most significant bytes are always 0
5555 pisid->IdentifierAuthority.Value[0] = 0;
5556 pisid->IdentifierAuthority.Value[1] = 0;
5557 identAuth = atoiW(StringSid);
5558 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
5559 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
5560 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
5561 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
5563 /* Advance to first sub authority */
5564 while (*StringSid && *StringSid != '-')
5565 StringSid++;
5566 if (*StringSid == '-')
5567 StringSid++;
5569 while (*StringSid)
5571 pisid->SubAuthority[i++] = atoiW(StringSid);
5573 while (*StringSid && *StringSid != '-')
5574 StringSid++;
5575 if (*StringSid == '-')
5576 StringSid++;
5579 if (i != pisid->SubAuthorityCount)
5580 goto lend; /* ERROR_INVALID_SID */
5582 bret = TRUE;
5584 else /* String constant format - Only available in winxp and above */
5586 unsigned int i;
5587 pisid->Revision = SDDL_REVISION;
5589 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5590 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5592 DWORD j;
5593 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
5594 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
5595 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
5596 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
5597 bret = TRUE;
5600 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
5601 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
5603 ADVAPI_GetComputerSid(pisid);
5604 pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid;
5605 pisid->SubAuthorityCount++;
5606 bret = TRUE;
5609 if (!bret)
5610 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
5613 lend:
5614 if (!bret)
5615 SetLastError(ERROR_INVALID_SID);
5617 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
5618 return bret;
5621 /******************************************************************************
5622 * GetNamedSecurityInfoA [ADVAPI32.@]
5624 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
5625 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5626 PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
5627 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
5629 LPWSTR wstr;
5630 DWORD r;
5632 TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
5633 ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
5635 wstr = SERV_dup(pObjectName);
5636 r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
5637 ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
5639 heap_free( wstr );
5641 return r;
5644 /******************************************************************************
5645 * GetNamedSecurityInfoW [ADVAPI32.@]
5647 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
5648 SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
5649 PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
5651 DWORD access = 0;
5652 HANDLE handle;
5653 DWORD err;
5655 TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
5656 group, dacl, sacl, descriptor );
5658 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
5659 if (!name || !(owner||group||dacl||sacl||descriptor) ) return ERROR_INVALID_PARAMETER;
5661 /* If no descriptor, we have to check that there's a pointer for the requested information */
5662 if( !descriptor && (
5663 ((info & OWNER_SECURITY_INFORMATION) && !owner)
5664 || ((info & GROUP_SECURITY_INFORMATION) && !group)
5665 || ((info & DACL_SECURITY_INFORMATION) && !dacl)
5666 || ((info & SACL_SECURITY_INFORMATION) && !sacl) ))
5667 return ERROR_INVALID_PARAMETER;
5669 if (info & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION))
5670 access |= READ_CONTROL;
5671 if (info & SACL_SECURITY_INFORMATION)
5672 access |= ACCESS_SYSTEM_SECURITY;
5674 switch (type)
5676 case SE_SERVICE:
5677 if (!(err = get_security_service( name, access, &handle )))
5679 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5680 CloseServiceHandle( handle );
5682 break;
5683 case SE_REGISTRY_KEY:
5684 if (!(err = get_security_regkey( name, access, &handle )))
5686 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5687 RegCloseKey( handle );
5689 break;
5690 case SE_FILE_OBJECT:
5691 if (!(err = get_security_file( name, access, &handle )))
5693 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5694 CloseHandle( handle );
5696 break;
5697 default:
5698 FIXME( "Object type %d is not currently supported.\n", type );
5699 if (owner) *owner = NULL;
5700 if (group) *group = NULL;
5701 if (dacl) *dacl = NULL;
5702 if (sacl) *sacl = NULL;
5703 if (descriptor) *descriptor = NULL;
5704 return ERROR_SUCCESS;
5706 return err;
5709 /******************************************************************************
5710 * GetNamedSecurityInfoExW [ADVAPI32.@]
5712 DWORD WINAPI GetNamedSecurityInfoExW( LPCWSTR object, SE_OBJECT_TYPE type,
5713 SECURITY_INFORMATION info, LPCWSTR provider, LPCWSTR property,
5714 PACTRL_ACCESSW* access_list, PACTRL_AUDITW* audit_list, LPWSTR* owner, LPWSTR* group )
5716 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_w(object), type, info,
5717 debugstr_w(provider), debugstr_w(property), access_list, audit_list, owner, group);
5718 return ERROR_CALL_NOT_IMPLEMENTED;
5721 /******************************************************************************
5722 * GetNamedSecurityInfoExA [ADVAPI32.@]
5724 DWORD WINAPI GetNamedSecurityInfoExA( LPCSTR object, SE_OBJECT_TYPE type,
5725 SECURITY_INFORMATION info, LPCSTR provider, LPCSTR property,
5726 PACTRL_ACCESSA* access_list, PACTRL_AUDITA* audit_list, LPSTR* owner, LPSTR* group )
5728 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_a(object), type, info,
5729 debugstr_a(provider), debugstr_a(property), access_list, audit_list, owner, group);
5730 return ERROR_CALL_NOT_IMPLEMENTED;
5733 /******************************************************************************
5734 * DecryptFileW [ADVAPI32.@]
5736 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
5738 FIXME("(%s, %08x): stub\n", debugstr_w(lpFileName), dwReserved);
5739 return TRUE;
5742 /******************************************************************************
5743 * DecryptFileA [ADVAPI32.@]
5745 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
5747 FIXME("(%s, %08x): stub\n", debugstr_a(lpFileName), dwReserved);
5748 return TRUE;
5751 /******************************************************************************
5752 * EncryptFileW [ADVAPI32.@]
5754 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
5756 FIXME("(%s): stub\n", debugstr_w(lpFileName));
5757 return TRUE;
5760 /******************************************************************************
5761 * EncryptFileA [ADVAPI32.@]
5763 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
5765 FIXME("(%s): stub\n", debugstr_a(lpFileName));
5766 return TRUE;
5769 /******************************************************************************
5770 * FileEncryptionStatusW [ADVAPI32.@]
5772 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
5774 FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
5775 if (!lpStatus)
5776 return FALSE;
5777 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5778 return TRUE;
5781 /******************************************************************************
5782 * FileEncryptionStatusA [ADVAPI32.@]
5784 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
5786 FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
5787 if (!lpStatus)
5788 return FALSE;
5789 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5790 return TRUE;
5793 /******************************************************************************
5794 * SetSecurityInfo [ADVAPI32.@]
5796 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType,
5797 SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
5798 PSID psidGroup, PACL pDacl, PACL pSacl)
5800 SECURITY_DESCRIPTOR sd;
5801 PACL dacl = pDacl;
5802 NTSTATUS status;
5804 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
5805 return ERROR_INVALID_SECURITY_DESCR;
5807 if (SecurityInfo & OWNER_SECURITY_INFORMATION)
5808 SetSecurityDescriptorOwner(&sd, psidOwner, FALSE);
5809 if (SecurityInfo & GROUP_SECURITY_INFORMATION)
5810 SetSecurityDescriptorGroup(&sd, psidGroup, FALSE);
5811 if (SecurityInfo & DACL_SECURITY_INFORMATION)
5813 if (ObjectType == SE_FILE_OBJECT && pDacl)
5815 SECURITY_DESCRIPTOR_CONTROL control;
5816 PSECURITY_DESCRIPTOR psd;
5817 OBJECT_NAME_INFORMATION *name_info;
5818 DWORD size, rev;
5820 status = NtQuerySecurityObject(handle, SecurityInfo, NULL, 0, &size);
5821 if (status != STATUS_BUFFER_TOO_SMALL)
5822 return RtlNtStatusToDosError(status);
5824 psd = heap_alloc(size);
5825 if (!psd)
5826 return ERROR_NOT_ENOUGH_MEMORY;
5828 status = NtQuerySecurityObject(handle, SecurityInfo, psd, size, &size);
5829 if (status)
5831 heap_free(psd);
5832 return RtlNtStatusToDosError(status);
5835 status = RtlGetControlSecurityDescriptor(psd, &control, &rev);
5836 heap_free(psd);
5837 if (status)
5838 return RtlNtStatusToDosError(status);
5839 /* TODO: copy some control flags to new sd */
5841 /* inherit parent directory DACL */
5842 if (!(control & SE_DACL_PROTECTED))
5844 status = NtQueryObject(handle, ObjectNameInformation, NULL, 0, &size);
5845 if (status != STATUS_INFO_LENGTH_MISMATCH)
5846 return RtlNtStatusToDosError(status);
5848 name_info = heap_alloc(size);
5849 if (!name_info)
5850 return ERROR_NOT_ENOUGH_MEMORY;
5852 status = NtQueryObject(handle, ObjectNameInformation, name_info, size, NULL);
5853 if (status)
5855 heap_free(name_info);
5856 return RtlNtStatusToDosError(status);
5859 for (name_info->Name.Length-=2; name_info->Name.Length>0; name_info->Name.Length-=2)
5860 if (name_info->Name.Buffer[name_info->Name.Length/2-1]=='\\' ||
5861 name_info->Name.Buffer[name_info->Name.Length/2-1]=='/')
5862 break;
5863 if (name_info->Name.Length)
5865 OBJECT_ATTRIBUTES attr;
5866 IO_STATUS_BLOCK io;
5867 HANDLE parent;
5868 PSECURITY_DESCRIPTOR parent_sd;
5869 ACL *parent_dacl;
5870 DWORD err = ERROR_ACCESS_DENIED;
5872 name_info->Name.Buffer[name_info->Name.Length/2] = 0;
5874 attr.Length = sizeof(attr);
5875 attr.RootDirectory = 0;
5876 attr.Attributes = 0;
5877 attr.ObjectName = &name_info->Name;
5878 attr.SecurityDescriptor = NULL;
5879 status = NtOpenFile(&parent, READ_CONTROL, &attr, &io,
5880 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5881 FILE_OPEN_FOR_BACKUP_INTENT);
5882 heap_free(name_info);
5883 if (!status)
5885 err = GetSecurityInfo(parent, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
5886 NULL, NULL, &parent_dacl, NULL, &parent_sd);
5887 CloseHandle(parent);
5890 if (!err)
5892 int i;
5894 dacl = heap_alloc_zero(pDacl->AclSize+parent_dacl->AclSize);
5895 if (!dacl)
5897 LocalFree(parent_sd);
5898 return ERROR_NOT_ENOUGH_MEMORY;
5900 memcpy(dacl, pDacl, pDacl->AclSize);
5901 dacl->AclSize = pDacl->AclSize+parent_dacl->AclSize;
5903 for (i=0; i<parent_dacl->AceCount; i++)
5905 ACE_HEADER *ace;
5907 if (!GetAce(parent_dacl, i, (void*)&ace))
5908 continue;
5909 if (!(ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)))
5910 continue;
5911 if ((ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) !=
5912 (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE))
5914 FIXME("unsupported flags: %x\n", ace->AceFlags);
5915 continue;
5918 if (ace->AceFlags & NO_PROPAGATE_INHERIT_ACE)
5919 ace->AceFlags &= ~(OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE|NO_PROPAGATE_INHERIT_ACE);
5920 ace->AceFlags &= ~INHERIT_ONLY_ACE;
5921 ace->AceFlags |= INHERITED_ACE;
5923 if(!AddAce(dacl, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
5924 WARN("error adding inherited ACE\n");
5926 LocalFree(parent_sd);
5929 else
5930 heap_free(name_info);
5934 SetSecurityDescriptorDacl(&sd, TRUE, dacl, FALSE);
5936 if (SecurityInfo & SACL_SECURITY_INFORMATION)
5937 SetSecurityDescriptorSacl(&sd, TRUE, pSacl, FALSE);
5939 switch (ObjectType)
5941 case SE_SERVICE:
5942 FIXME("stub: Service objects are not supported at this time.\n");
5943 status = STATUS_SUCCESS; /* Implement SetServiceObjectSecurity */
5944 break;
5945 default:
5946 status = NtSetSecurityObject(handle, SecurityInfo, &sd);
5947 break;
5949 if (dacl != pDacl)
5950 heap_free(dacl);
5951 return RtlNtStatusToDosError(status);
5954 /******************************************************************************
5955 * SaferCreateLevel [ADVAPI32.@]
5957 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
5958 SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
5960 FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
5962 *LevelHandle = (SAFER_LEVEL_HANDLE)0xdeadbeef;
5963 return TRUE;
5966 /******************************************************************************
5967 * SaferComputeTokenFromLevel [ADVAPI32.@]
5969 BOOL WINAPI SaferComputeTokenFromLevel(SAFER_LEVEL_HANDLE handle, HANDLE token, PHANDLE access_token,
5970 DWORD flags, LPVOID reserved)
5972 FIXME("(%p, %p, %p, %x, %p) stub\n", handle, token, access_token, flags, reserved);
5974 *access_token = (HANDLE)0xdeadbeef;
5975 return TRUE;
5978 /******************************************************************************
5979 * SaferCloseLevel [ADVAPI32.@]
5981 BOOL WINAPI SaferCloseLevel(SAFER_LEVEL_HANDLE handle)
5983 FIXME("(%p) stub\n", handle);
5984 return TRUE;
5987 DWORD WINAPI TreeResetNamedSecurityInfoW( LPWSTR pObjectName,
5988 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5989 PSID pOwner, PSID pGroup, PACL pDacl, PACL pSacl,
5990 BOOL KeepExplicit, FN_PROGRESS fnProgress,
5991 PROG_INVOKE_SETTING ProgressInvokeSetting, PVOID Args)
5993 FIXME("(%s, %i, %i, %p, %p, %p, %p, %i, %p, %i, %p) stub\n",
5994 debugstr_w(pObjectName), ObjectType, SecurityInfo, pOwner, pGroup,
5995 pDacl, pSacl, KeepExplicit, fnProgress, ProgressInvokeSetting, Args);
5997 return ERROR_SUCCESS;
6000 /******************************************************************************
6001 * SaferGetPolicyInformation [ADVAPI32.@]
6003 BOOL WINAPI SaferGetPolicyInformation(DWORD scope, SAFER_POLICY_INFO_CLASS class, DWORD size,
6004 PVOID buffer, PDWORD required, LPVOID lpReserved)
6006 FIXME("(%u %u %u %p %p %p) stub\n", scope, class, size, buffer, required, lpReserved);
6007 return FALSE;
6010 /******************************************************************************
6011 * SaferSetLevelInformation [ADVAPI32.@]
6013 BOOL WINAPI SaferSetLevelInformation(SAFER_LEVEL_HANDLE handle, SAFER_OBJECT_INFO_CLASS infotype,
6014 LPVOID buffer, DWORD size)
6016 FIXME("(%p %u %p %u) stub\n", handle, infotype, buffer, size);
6017 return FALSE;