advapi32: Add DACL inheritance support in SetSecurityInfo.
[wine/multimedia.git] / dlls / advapi32 / security.c
blob71a8c9245be08c2fec2b379f5446b3e52a540c6b
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};
315 * ACL flags
317 static const WCHAR SDDL_PROTECTED[] = {'P',0};
318 static const WCHAR SDDL_AUTO_INHERIT_REQ[] = {'A','R',0};
319 static const WCHAR SDDL_AUTO_INHERITED[] = {'A','I',0};
322 * ACE types
324 static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0};
325 static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0};
326 static const WCHAR SDDL_AUDIT[] = {'A','U',0};
327 static const WCHAR SDDL_ALARM[] = {'A','L',0};
330 * ACE flags
332 static const WCHAR SDDL_CONTAINER_INHERIT[] = {'C','I',0};
333 static const WCHAR SDDL_OBJECT_INHERIT[] = {'O','I',0};
334 static const WCHAR SDDL_NO_PROPAGATE[] = {'N','P',0};
335 static const WCHAR SDDL_INHERIT_ONLY[] = {'I','O',0};
336 static const WCHAR SDDL_INHERITED[] = {'I','D',0};
337 static const WCHAR SDDL_AUDIT_SUCCESS[] = {'S','A',0};
338 static const WCHAR SDDL_AUDIT_FAILURE[] = {'F','A',0};
340 const char * debugstr_sid(PSID sid)
342 int auth = 0;
343 SID * psid = sid;
345 if (psid == NULL)
346 return "(null)";
348 auth = psid->IdentifierAuthority.Value[5] +
349 (psid->IdentifierAuthority.Value[4] << 8) +
350 (psid->IdentifierAuthority.Value[3] << 16) +
351 (psid->IdentifierAuthority.Value[2] << 24);
353 switch (psid->SubAuthorityCount) {
354 case 0:
355 return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
356 case 1:
357 return wine_dbg_sprintf("S-%d-%d-%u", psid->Revision, auth,
358 psid->SubAuthority[0]);
359 case 2:
360 return wine_dbg_sprintf("S-%d-%d-%u-%u", psid->Revision, auth,
361 psid->SubAuthority[0], psid->SubAuthority[1]);
362 case 3:
363 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u", psid->Revision, auth,
364 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
365 case 4:
366 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u", psid->Revision, auth,
367 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
368 psid->SubAuthority[3]);
369 case 5:
370 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u", psid->Revision, auth,
371 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
372 psid->SubAuthority[3], psid->SubAuthority[4]);
373 case 6:
374 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
375 psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
376 psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
377 case 7:
378 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
379 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
380 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
381 psid->SubAuthority[6]);
382 case 8:
383 return wine_dbg_sprintf("S-%d-%d-%u-%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], psid->SubAuthority[7]);
388 return "(too-big)";
391 /* set last error code from NT status and get the proper boolean return value */
392 /* used for functions that are a simple wrapper around the corresponding ntdll API */
393 static inline BOOL set_ntstatus( NTSTATUS status )
395 if (status) SetLastError( RtlNtStatusToDosError( status ));
396 return !status;
399 /* helper function for SE_FILE_OBJECT objects in [Get|Set]NamedSecurityInfo */
400 static inline DWORD get_security_file( LPCWSTR full_file_name, DWORD access, HANDLE *file )
402 UNICODE_STRING file_nameW;
403 OBJECT_ATTRIBUTES attr;
404 IO_STATUS_BLOCK io;
405 NTSTATUS status;
407 if (!RtlDosPathNameToNtPathName_U( full_file_name, &file_nameW, NULL, NULL ))
408 return ERROR_PATH_NOT_FOUND;
409 attr.Length = sizeof(attr);
410 attr.RootDirectory = 0;
411 attr.Attributes = OBJ_CASE_INSENSITIVE;
412 attr.ObjectName = &file_nameW;
413 attr.SecurityDescriptor = NULL;
414 status = NtCreateFile( file, access, &attr, &io, NULL, FILE_FLAG_BACKUP_SEMANTICS,
415 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
416 FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 );
417 RtlFreeUnicodeString( &file_nameW );
418 return RtlNtStatusToDosError( status );
421 /* helper function for SE_SERVICE objects in [Get|Set]NamedSecurityInfo */
422 static inline DWORD get_security_service( LPWSTR full_service_name, DWORD access, HANDLE *service )
424 SC_HANDLE manager = 0;
425 DWORD err;
427 err = SERV_OpenSCManagerW( NULL, NULL, access, (SC_HANDLE *)&manager );
428 if (err == ERROR_SUCCESS)
429 err = SERV_OpenServiceW( manager, full_service_name, access, (SC_HANDLE *)service );
430 CloseServiceHandle( manager );
431 return err;
434 /* helper function for SE_REGISTRY_KEY objects in [Get|Set]NamedSecurityInfo */
435 static inline DWORD get_security_regkey( LPWSTR full_key_name, DWORD access, HANDLE *key )
437 WCHAR classes_rootW[] = {'C','L','A','S','S','E','S','_','R','O','O','T',0};
438 WCHAR current_userW[] = {'C','U','R','R','E','N','T','_','U','S','E','R',0};
439 WCHAR machineW[] = {'M','A','C','H','I','N','E',0};
440 WCHAR usersW[] = {'U','S','E','R','S',0};
441 LPWSTR p = strchrW(full_key_name, '\\');
442 int len = p-full_key_name;
443 HKEY hParent;
445 if (!p) return ERROR_INVALID_PARAMETER;
446 if (strncmpW( full_key_name, classes_rootW, len ) == 0)
447 hParent = HKEY_CLASSES_ROOT;
448 else if (strncmpW( full_key_name, current_userW, len ) == 0)
449 hParent = HKEY_CURRENT_USER;
450 else if (strncmpW( full_key_name, machineW, len ) == 0)
451 hParent = HKEY_LOCAL_MACHINE;
452 else if (strncmpW( full_key_name, usersW, len ) == 0)
453 hParent = HKEY_USERS;
454 else
455 return ERROR_INVALID_PARAMETER;
456 return RegOpenKeyExW( hParent, p+1, 0, access, (HKEY *)key );
459 #define WINE_SIZE_OF_WORLD_ACCESS_ACL (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD))
461 static void GetWorldAccessACL(PACL pACL)
463 PACCESS_ALLOWED_ACE pACE = (PACCESS_ALLOWED_ACE) (pACL + 1);
465 pACL->AclRevision = ACL_REVISION;
466 pACL->Sbz1 = 0;
467 pACL->AclSize = WINE_SIZE_OF_WORLD_ACCESS_ACL;
468 pACL->AceCount = 1;
469 pACL->Sbz2 = 0;
471 pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
472 pACE->Header.AceFlags = CONTAINER_INHERIT_ACE;
473 pACE->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD);
474 pACE->Mask = 0xf3ffffff; /* Everything except reserved bits */
475 memcpy(&pACE->SidStart, &sidWorld, sizeof(sidWorld));
478 /************************************************************
479 * ADVAPI_IsLocalComputer
481 * Checks whether the server name indicates local machine.
483 BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName)
485 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
486 BOOL Result;
487 LPWSTR buf;
489 if (!ServerName || !ServerName[0])
490 return TRUE;
492 buf = heap_alloc(dwSize * sizeof(WCHAR));
493 Result = GetComputerNameW(buf, &dwSize);
494 if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
495 ServerName += 2;
496 Result = Result && !lstrcmpW(ServerName, buf);
497 heap_free(buf);
499 return Result;
502 /************************************************************
503 * ADVAPI_GetComputerSid
505 BOOL ADVAPI_GetComputerSid(PSID sid)
507 static const struct /* same fields as struct SID */
509 BYTE Revision;
510 BYTE SubAuthorityCount;
511 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
512 DWORD SubAuthority[4];
513 } computer_sid =
514 { SID_REVISION, 4, { SECURITY_NT_AUTHORITY }, { SECURITY_NT_NON_UNIQUE, 0, 0, 0 } };
516 memcpy( sid, &computer_sid, sizeof(computer_sid) );
517 return TRUE;
520 /* ##############################
521 ###### TOKEN FUNCTIONS ######
522 ##############################
525 /******************************************************************************
526 * OpenProcessToken [ADVAPI32.@]
527 * Opens the access token associated with a process handle.
529 * PARAMS
530 * ProcessHandle [I] Handle to process
531 * DesiredAccess [I] Desired access to process
532 * TokenHandle [O] Pointer to handle of open access token
534 * RETURNS
535 * Success: TRUE. TokenHandle contains the access token.
536 * Failure: FALSE.
538 * NOTES
539 * See NtOpenProcessToken.
541 BOOL WINAPI
542 OpenProcessToken( HANDLE ProcessHandle, DWORD DesiredAccess,
543 HANDLE *TokenHandle )
545 return set_ntstatus(NtOpenProcessToken( ProcessHandle, DesiredAccess, TokenHandle ));
548 /******************************************************************************
549 * OpenThreadToken [ADVAPI32.@]
551 * Opens the access token associated with a thread handle.
553 * PARAMS
554 * ThreadHandle [I] Handle to process
555 * DesiredAccess [I] Desired access to the thread
556 * OpenAsSelf [I] ???
557 * TokenHandle [O] Destination for the token handle
559 * RETURNS
560 * Success: TRUE. TokenHandle contains the access token.
561 * Failure: FALSE.
563 * NOTES
564 * See NtOpenThreadToken.
566 BOOL WINAPI
567 OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess,
568 BOOL OpenAsSelf, HANDLE *TokenHandle)
570 return set_ntstatus( NtOpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle));
573 BOOL WINAPI
574 AdjustTokenGroups( HANDLE TokenHandle, BOOL ResetToDefault, PTOKEN_GROUPS NewState,
575 DWORD BufferLength, PTOKEN_GROUPS PreviousState, PDWORD ReturnLength )
577 return set_ntstatus( NtAdjustGroupsToken(TokenHandle, ResetToDefault, NewState, BufferLength,
578 PreviousState, ReturnLength));
581 /******************************************************************************
582 * AdjustTokenPrivileges [ADVAPI32.@]
584 * Adjust the privileges of an open token handle.
586 * PARAMS
587 * TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
588 * DisableAllPrivileges [I] TRUE=Remove all privileges, FALSE=Use NewState
589 * NewState [I] Desired new privileges of the token
590 * BufferLength [I] Length of NewState
591 * PreviousState [O] Destination for the previous state
592 * ReturnLength [I/O] Size of PreviousState
595 * RETURNS
596 * Success: TRUE. Privileges are set to NewState and PreviousState is updated.
597 * Failure: FALSE.
599 * NOTES
600 * See NtAdjustPrivilegesToken.
602 BOOL WINAPI
603 AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges,
604 PTOKEN_PRIVILEGES NewState, DWORD BufferLength,
605 PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength )
607 NTSTATUS status;
609 TRACE("(%p %d %p %d %p %p)\n", TokenHandle, DisableAllPrivileges, NewState, BufferLength,
610 PreviousState, ReturnLength);
612 status = NtAdjustPrivilegesToken(TokenHandle, DisableAllPrivileges,
613 NewState, BufferLength, PreviousState,
614 ReturnLength);
615 SetLastError( RtlNtStatusToDosError( status ));
616 if ((status == STATUS_SUCCESS) || (status == STATUS_NOT_ALL_ASSIGNED))
617 return TRUE;
618 else
619 return FALSE;
622 /******************************************************************************
623 * CheckTokenMembership [ADVAPI32.@]
625 * Determine if an access token is a member of a SID.
627 * PARAMS
628 * TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
629 * SidToCheck [I] SID that possibly contains the token
630 * IsMember [O] Destination for result.
632 * RETURNS
633 * Success: TRUE. IsMember is TRUE if TokenHandle is a member, FALSE otherwise.
634 * Failure: FALSE.
636 BOOL WINAPI
637 CheckTokenMembership( HANDLE token, PSID sid_to_check,
638 PBOOL is_member )
640 PTOKEN_GROUPS token_groups = NULL;
641 HANDLE thread_token = NULL;
642 DWORD size, i;
643 BOOL ret;
645 TRACE("(%p %s %p)\n", token, debugstr_sid(sid_to_check), is_member);
647 *is_member = FALSE;
649 if (!token)
651 if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &thread_token))
653 HANDLE process_token;
654 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &process_token);
655 if (!ret)
656 goto exit;
657 ret = DuplicateTokenEx(process_token, TOKEN_QUERY,
658 NULL, SecurityImpersonation, TokenImpersonation,
659 &thread_token);
660 CloseHandle(process_token);
661 if (!ret)
662 goto exit;
664 token = thread_token;
666 else
668 TOKEN_TYPE type;
670 ret = GetTokenInformation(token, TokenType, &type, sizeof(TOKEN_TYPE), &size);
671 if (!ret) goto exit;
673 if (type == TokenPrimary)
675 SetLastError(ERROR_NO_IMPERSONATION_TOKEN);
676 return FALSE;
680 ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
681 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
682 goto exit;
684 token_groups = heap_alloc(size);
685 if (!token_groups)
687 ret = FALSE;
688 goto exit;
691 ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
692 if (!ret)
693 goto exit;
695 for (i = 0; i < token_groups->GroupCount; i++)
697 TRACE("Groups[%d]: {0x%x, %s}\n", i,
698 token_groups->Groups[i].Attributes,
699 debugstr_sid(token_groups->Groups[i].Sid));
700 if ((token_groups->Groups[i].Attributes & SE_GROUP_ENABLED) &&
701 EqualSid(sid_to_check, token_groups->Groups[i].Sid))
703 *is_member = TRUE;
704 TRACE("sid enabled and found in token\n");
705 break;
709 exit:
710 heap_free(token_groups);
711 if (thread_token != NULL) CloseHandle(thread_token);
713 return ret;
716 /******************************************************************************
717 * GetTokenInformation [ADVAPI32.@]
719 * Get a type of information about an access token.
721 * PARAMS
722 * token [I] Handle from OpenProcessToken() or OpenThreadToken()
723 * tokeninfoclass [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
724 * tokeninfo [O] Destination for token information
725 * tokeninfolength [I] Length of tokeninfo
726 * retlen [O] Destination for returned token information length
728 * RETURNS
729 * Success: TRUE. tokeninfo contains retlen bytes of token information
730 * Failure: FALSE.
732 * NOTES
733 * See NtQueryInformationToken.
735 BOOL WINAPI
736 GetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
737 LPVOID tokeninfo, DWORD tokeninfolength, LPDWORD retlen )
739 TRACE("(%p, %s, %p, %d, %p):\n",
740 token,
741 (tokeninfoclass == TokenUser) ? "TokenUser" :
742 (tokeninfoclass == TokenGroups) ? "TokenGroups" :
743 (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
744 (tokeninfoclass == TokenOwner) ? "TokenOwner" :
745 (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
746 (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
747 (tokeninfoclass == TokenSource) ? "TokenSource" :
748 (tokeninfoclass == TokenType) ? "TokenType" :
749 (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
750 (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
751 (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
752 (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
753 (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
754 (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
755 (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
756 "Unknown",
757 tokeninfo, tokeninfolength, retlen);
758 return set_ntstatus( NtQueryInformationToken( token, tokeninfoclass, tokeninfo,
759 tokeninfolength, retlen));
762 /******************************************************************************
763 * SetTokenInformation [ADVAPI32.@]
765 * Set information for an access token.
767 * PARAMS
768 * token [I] Handle from OpenProcessToken() or OpenThreadToken()
769 * tokeninfoclass [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
770 * tokeninfo [I] Token information to set
771 * tokeninfolength [I] Length of tokeninfo
773 * RETURNS
774 * Success: TRUE. The information for the token is set to tokeninfo.
775 * Failure: FALSE.
777 BOOL WINAPI
778 SetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
779 LPVOID tokeninfo, DWORD tokeninfolength )
781 TRACE("(%p, %s, %p, %d): stub\n",
782 token,
783 (tokeninfoclass == TokenUser) ? "TokenUser" :
784 (tokeninfoclass == TokenGroups) ? "TokenGroups" :
785 (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
786 (tokeninfoclass == TokenOwner) ? "TokenOwner" :
787 (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
788 (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
789 (tokeninfoclass == TokenSource) ? "TokenSource" :
790 (tokeninfoclass == TokenType) ? "TokenType" :
791 (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
792 (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
793 (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
794 (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
795 (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
796 (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
797 (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
798 "Unknown",
799 tokeninfo, tokeninfolength);
801 return set_ntstatus( NtSetInformationToken( token, tokeninfoclass, tokeninfo, tokeninfolength ));
804 /*************************************************************************
805 * SetThreadToken [ADVAPI32.@]
807 * Assigns an 'impersonation token' to a thread so it can assume the
808 * security privileges of another thread or process. Can also remove
809 * a previously assigned token.
811 * PARAMS
812 * thread [O] Handle to thread to set the token for
813 * token [I] Token to set
815 * RETURNS
816 * Success: TRUE. The threads access token is set to token
817 * Failure: FALSE.
819 * NOTES
820 * Only supported on NT or higher. On Win9X this function does nothing.
821 * See SetTokenInformation.
823 BOOL WINAPI SetThreadToken(PHANDLE thread, HANDLE token)
825 return set_ntstatus( NtSetInformationThread( thread ? *thread : GetCurrentThread(),
826 ThreadImpersonationToken, &token, sizeof token ));
829 /*************************************************************************
830 * CreateRestrictedToken [ADVAPI32.@]
832 * Create a new more restricted token from an existing token.
834 * PARAMS
835 * baseToken [I] Token to base the new restricted token on
836 * flags [I] Options
837 * nDisableSids [I] Length of disableSids array
838 * disableSids [I] Array of SIDs to disable in the new token
839 * nDeletePrivs [I] Length of deletePrivs array
840 * deletePrivs [I] Array of privileges to delete in the new token
841 * nRestrictSids [I] Length of restrictSids array
842 * restrictSids [I] Array of SIDs to restrict in the new token
843 * newToken [O] Address where the new token is stored
845 * RETURNS
846 * Success: TRUE
847 * Failure: FALSE
849 BOOL WINAPI CreateRestrictedToken(
850 HANDLE baseToken,
851 DWORD flags,
852 DWORD nDisableSids,
853 PSID_AND_ATTRIBUTES disableSids,
854 DWORD nDeletePrivs,
855 PLUID_AND_ATTRIBUTES deletePrivs,
856 DWORD nRestrictSids,
857 PSID_AND_ATTRIBUTES restrictSids,
858 PHANDLE newToken)
860 TOKEN_TYPE type;
861 SECURITY_IMPERSONATION_LEVEL level = TokenImpersonationLevel;
862 DWORD size;
864 FIXME("(%p, 0x%x, %u, %p, %u, %p, %u, %p, %p): stub\n",
865 baseToken, flags, nDisableSids, disableSids,
866 nDeletePrivs, deletePrivs,
867 nRestrictSids, restrictSids,
868 newToken);
870 size = sizeof(type);
871 if (!GetTokenInformation( baseToken, TokenType, &type, size, &size )) return FALSE;
872 if (type == TokenImpersonation)
874 size = sizeof(level);
875 if (!GetTokenInformation( baseToken, TokenImpersonationLevel, &level, size, &size ))
876 return FALSE;
878 return DuplicateTokenEx( baseToken, MAXIMUM_ALLOWED, NULL, level, type, newToken );
881 /* ##############################
882 ###### SID FUNCTIONS ######
883 ##############################
886 /******************************************************************************
887 * AllocateAndInitializeSid [ADVAPI32.@]
889 * PARAMS
890 * pIdentifierAuthority []
891 * nSubAuthorityCount []
892 * nSubAuthority0 []
893 * nSubAuthority1 []
894 * nSubAuthority2 []
895 * nSubAuthority3 []
896 * nSubAuthority4 []
897 * nSubAuthority5 []
898 * nSubAuthority6 []
899 * nSubAuthority7 []
900 * pSid []
902 BOOL WINAPI
903 AllocateAndInitializeSid( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
904 BYTE nSubAuthorityCount,
905 DWORD nSubAuthority0, DWORD nSubAuthority1,
906 DWORD nSubAuthority2, DWORD nSubAuthority3,
907 DWORD nSubAuthority4, DWORD nSubAuthority5,
908 DWORD nSubAuthority6, DWORD nSubAuthority7,
909 PSID *pSid )
911 return set_ntstatus( RtlAllocateAndInitializeSid(
912 pIdentifierAuthority, nSubAuthorityCount,
913 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
914 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7,
915 pSid ));
918 /******************************************************************************
919 * FreeSid [ADVAPI32.@]
921 * PARAMS
922 * pSid []
924 PVOID WINAPI
925 FreeSid( PSID pSid )
927 RtlFreeSid(pSid);
928 return NULL; /* is documented like this */
931 /******************************************************************************
932 * CopySid [ADVAPI32.@]
934 * PARAMS
935 * nDestinationSidLength []
936 * pDestinationSid []
937 * pSourceSid []
939 BOOL WINAPI
940 CopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
942 return RtlCopySid(nDestinationSidLength, pDestinationSid, pSourceSid);
945 /******************************************************************************
946 * CreateWellKnownSid [ADVAPI32.@]
948 BOOL WINAPI
949 CreateWellKnownSid( WELL_KNOWN_SID_TYPE WellKnownSidType,
950 PSID DomainSid,
951 PSID pSid,
952 DWORD* cbSid)
954 unsigned int i;
955 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
957 if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
959 SetLastError(ERROR_INVALID_PARAMETER);
960 return FALSE;
963 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
964 if (WellKnownSids[i].Type == WellKnownSidType) {
965 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
967 if (*cbSid < length)
969 *cbSid = length;
970 SetLastError(ERROR_INSUFFICIENT_BUFFER);
971 return FALSE;
973 if (!pSid)
975 SetLastError(ERROR_INVALID_PARAMETER);
976 return FALSE;
978 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
979 *cbSid = length;
980 return TRUE;
984 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
986 SetLastError(ERROR_INVALID_PARAMETER);
987 return FALSE;
990 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
991 if (WellKnownRids[i].Type == WellKnownSidType) {
992 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
993 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
994 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
996 if (*cbSid < output_sid_length)
998 *cbSid = output_sid_length;
999 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1000 return FALSE;
1002 if (!pSid)
1004 SetLastError(ERROR_INVALID_PARAMETER);
1005 return FALSE;
1007 CopyMemory(pSid, DomainSid, domain_sid_length);
1008 (*GetSidSubAuthorityCount(pSid))++;
1009 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
1010 *cbSid = output_sid_length;
1011 return TRUE;
1014 SetLastError(ERROR_INVALID_PARAMETER);
1015 return FALSE;
1018 /******************************************************************************
1019 * IsWellKnownSid [ADVAPI32.@]
1021 BOOL WINAPI
1022 IsWellKnownSid( PSID pSid, WELL_KNOWN_SID_TYPE WellKnownSidType )
1024 unsigned int i;
1025 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
1027 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
1028 if (WellKnownSids[i].Type == WellKnownSidType)
1029 if (EqualSid(pSid, (PSID)&(WellKnownSids[i].Sid.Revision)))
1030 return TRUE;
1032 return FALSE;
1035 BOOL WINAPI
1036 IsTokenRestricted( HANDLE TokenHandle )
1038 TOKEN_GROUPS *groups;
1039 DWORD size;
1040 NTSTATUS status;
1041 BOOL restricted;
1043 TRACE("(%p)\n", TokenHandle);
1045 status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, NULL, 0, &size);
1046 if (status != STATUS_BUFFER_TOO_SMALL)
1047 return FALSE;
1049 groups = heap_alloc(size);
1050 if (!groups)
1052 SetLastError(ERROR_OUTOFMEMORY);
1053 return FALSE;
1056 status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, groups, size, &size);
1057 if (status != STATUS_SUCCESS)
1059 heap_free(groups);
1060 return set_ntstatus(status);
1063 restricted = groups->GroupCount > 0;
1064 heap_free(groups);
1066 return restricted;
1069 /******************************************************************************
1070 * IsValidSid [ADVAPI32.@]
1072 * PARAMS
1073 * pSid []
1075 BOOL WINAPI
1076 IsValidSid( PSID pSid )
1078 return RtlValidSid( pSid );
1081 /******************************************************************************
1082 * EqualSid [ADVAPI32.@]
1084 * PARAMS
1085 * pSid1 []
1086 * pSid2 []
1088 BOOL WINAPI
1089 EqualSid( PSID pSid1, PSID pSid2 )
1091 BOOL ret = RtlEqualSid( pSid1, pSid2 );
1092 SetLastError(ERROR_SUCCESS);
1093 return ret;
1096 /******************************************************************************
1097 * EqualPrefixSid [ADVAPI32.@]
1099 BOOL WINAPI EqualPrefixSid (PSID pSid1, PSID pSid2)
1101 return RtlEqualPrefixSid(pSid1, pSid2);
1104 /******************************************************************************
1105 * GetSidLengthRequired [ADVAPI32.@]
1107 * PARAMS
1108 * nSubAuthorityCount []
1110 DWORD WINAPI
1111 GetSidLengthRequired( BYTE nSubAuthorityCount )
1113 return RtlLengthRequiredSid(nSubAuthorityCount);
1116 /******************************************************************************
1117 * InitializeSid [ADVAPI32.@]
1119 * PARAMS
1120 * pIdentifierAuthority []
1122 BOOL WINAPI
1123 InitializeSid (
1124 PSID pSid,
1125 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
1126 BYTE nSubAuthorityCount)
1128 return RtlInitializeSid(pSid, pIdentifierAuthority, nSubAuthorityCount);
1131 DWORD WINAPI
1132 GetEffectiveRightsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pAccessRights )
1134 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1136 *pAccessRights = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
1137 return 0;
1140 DWORD WINAPI
1141 GetEffectiveRightsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pAccessRights )
1143 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1145 return 1;
1148 /******************************************************************************
1149 * GetSidIdentifierAuthority [ADVAPI32.@]
1151 * PARAMS
1152 * pSid []
1154 PSID_IDENTIFIER_AUTHORITY WINAPI
1155 GetSidIdentifierAuthority( PSID pSid )
1157 return RtlIdentifierAuthoritySid(pSid);
1160 /******************************************************************************
1161 * GetSidSubAuthority [ADVAPI32.@]
1163 * PARAMS
1164 * pSid []
1165 * nSubAuthority []
1167 PDWORD WINAPI
1168 GetSidSubAuthority( PSID pSid, DWORD nSubAuthority )
1170 SetLastError(ERROR_SUCCESS);
1171 return RtlSubAuthoritySid(pSid, nSubAuthority);
1174 /******************************************************************************
1175 * GetSidSubAuthorityCount [ADVAPI32.@]
1177 * PARAMS
1178 * pSid []
1180 PUCHAR WINAPI
1181 GetSidSubAuthorityCount (PSID pSid)
1183 SetLastError(ERROR_SUCCESS);
1184 return RtlSubAuthorityCountSid(pSid);
1187 /******************************************************************************
1188 * GetLengthSid [ADVAPI32.@]
1190 * PARAMS
1191 * pSid []
1193 DWORD WINAPI
1194 GetLengthSid (PSID pSid)
1196 return RtlLengthSid(pSid);
1199 /* ##############################################
1200 ###### SECURITY DESCRIPTOR FUNCTIONS ######
1201 ##############################################
1204 /******************************************************************************
1205 * BuildSecurityDescriptorA [ADVAPI32.@]
1207 * Builds a SD from
1209 * PARAMS
1210 * pOwner [I]
1211 * pGroup [I]
1212 * cCountOfAccessEntries [I]
1213 * pListOfAccessEntries [I]
1214 * cCountOfAuditEntries [I]
1215 * pListofAuditEntries [I]
1216 * pOldSD [I]
1217 * lpdwBufferLength [I/O]
1218 * pNewSD [O]
1220 * RETURNS
1221 * Success: ERROR_SUCCESS
1222 * Failure: nonzero error code from Winerror.h
1224 DWORD WINAPI BuildSecurityDescriptorA(
1225 IN PTRUSTEEA pOwner,
1226 IN PTRUSTEEA pGroup,
1227 IN ULONG cCountOfAccessEntries,
1228 IN PEXPLICIT_ACCESSA pListOfAccessEntries,
1229 IN ULONG cCountOfAuditEntries,
1230 IN PEXPLICIT_ACCESSA pListofAuditEntries,
1231 IN PSECURITY_DESCRIPTOR pOldSD,
1232 IN OUT PULONG lpdwBufferLength,
1233 OUT PSECURITY_DESCRIPTOR* pNewSD)
1235 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1236 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1237 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1239 return ERROR_CALL_NOT_IMPLEMENTED;
1242 /******************************************************************************
1243 * BuildSecurityDescriptorW [ADVAPI32.@]
1245 * See BuildSecurityDescriptorA.
1247 DWORD WINAPI BuildSecurityDescriptorW(
1248 IN PTRUSTEEW pOwner,
1249 IN PTRUSTEEW pGroup,
1250 IN ULONG cCountOfAccessEntries,
1251 IN PEXPLICIT_ACCESSW pListOfAccessEntries,
1252 IN ULONG cCountOfAuditEntries,
1253 IN PEXPLICIT_ACCESSW pListofAuditEntries,
1254 IN PSECURITY_DESCRIPTOR pOldSD,
1255 IN OUT PULONG lpdwBufferLength,
1256 OUT PSECURITY_DESCRIPTOR* pNewSD)
1258 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1259 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1260 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1262 return ERROR_CALL_NOT_IMPLEMENTED;
1265 /******************************************************************************
1266 * InitializeSecurityDescriptor [ADVAPI32.@]
1268 * PARAMS
1269 * pDescr []
1270 * revision []
1272 BOOL WINAPI
1273 InitializeSecurityDescriptor( PSECURITY_DESCRIPTOR pDescr, DWORD revision )
1275 return set_ntstatus( RtlCreateSecurityDescriptor(pDescr, revision ));
1279 /******************************************************************************
1280 * MakeAbsoluteSD [ADVAPI32.@]
1282 BOOL WINAPI MakeAbsoluteSD (
1283 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1284 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1285 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
1286 OUT PACL pDacl,
1287 OUT LPDWORD lpdwDaclSize,
1288 OUT PACL pSacl,
1289 OUT LPDWORD lpdwSaclSize,
1290 OUT PSID pOwner,
1291 OUT LPDWORD lpdwOwnerSize,
1292 OUT PSID pPrimaryGroup,
1293 OUT LPDWORD lpdwPrimaryGroupSize)
1295 return set_ntstatus( RtlSelfRelativeToAbsoluteSD(pSelfRelativeSecurityDescriptor,
1296 pAbsoluteSecurityDescriptor,
1297 lpdwAbsoluteSecurityDescriptorSize,
1298 pDacl, lpdwDaclSize, pSacl, lpdwSaclSize,
1299 pOwner, lpdwOwnerSize,
1300 pPrimaryGroup, lpdwPrimaryGroupSize));
1303 /******************************************************************************
1304 * GetKernelObjectSecurity [ADVAPI32.@]
1306 BOOL WINAPI GetKernelObjectSecurity(
1307 HANDLE Handle,
1308 SECURITY_INFORMATION RequestedInformation,
1309 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1310 DWORD nLength,
1311 LPDWORD lpnLengthNeeded )
1313 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", Handle, RequestedInformation,
1314 pSecurityDescriptor, nLength, lpnLengthNeeded);
1316 return set_ntstatus( NtQuerySecurityObject(Handle, RequestedInformation, pSecurityDescriptor,
1317 nLength, lpnLengthNeeded ));
1320 /******************************************************************************
1321 * GetPrivateObjectSecurity [ADVAPI32.@]
1323 BOOL WINAPI GetPrivateObjectSecurity(
1324 PSECURITY_DESCRIPTOR ObjectDescriptor,
1325 SECURITY_INFORMATION SecurityInformation,
1326 PSECURITY_DESCRIPTOR ResultantDescriptor,
1327 DWORD DescriptorLength,
1328 PDWORD ReturnLength )
1330 SECURITY_DESCRIPTOR desc;
1331 BOOL defaulted, present;
1332 PACL pacl;
1333 PSID psid;
1335 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", ObjectDescriptor, SecurityInformation,
1336 ResultantDescriptor, DescriptorLength, ReturnLength);
1338 if (!InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION))
1339 return FALSE;
1341 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1343 if (!GetSecurityDescriptorOwner(ObjectDescriptor, &psid, &defaulted))
1344 return FALSE;
1345 SetSecurityDescriptorOwner(&desc, psid, defaulted);
1348 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1350 if (!GetSecurityDescriptorGroup(ObjectDescriptor, &psid, &defaulted))
1351 return FALSE;
1352 SetSecurityDescriptorGroup(&desc, psid, defaulted);
1355 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1357 if (!GetSecurityDescriptorDacl(ObjectDescriptor, &present, &pacl, &defaulted))
1358 return FALSE;
1359 SetSecurityDescriptorDacl(&desc, present, pacl, defaulted);
1362 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1364 if (!GetSecurityDescriptorSacl(ObjectDescriptor, &present, &pacl, &defaulted))
1365 return FALSE;
1366 SetSecurityDescriptorSacl(&desc, present, pacl, defaulted);
1369 *ReturnLength = DescriptorLength;
1370 return MakeSelfRelativeSD(&desc, ResultantDescriptor, ReturnLength);
1373 /******************************************************************************
1374 * GetSecurityDescriptorLength [ADVAPI32.@]
1376 DWORD WINAPI GetSecurityDescriptorLength( PSECURITY_DESCRIPTOR pDescr)
1378 return RtlLengthSecurityDescriptor(pDescr);
1381 /******************************************************************************
1382 * GetSecurityDescriptorOwner [ADVAPI32.@]
1384 * PARAMS
1385 * pOwner []
1386 * lpbOwnerDefaulted []
1388 BOOL WINAPI
1389 GetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pDescr, PSID *pOwner,
1390 LPBOOL lpbOwnerDefaulted )
1392 BOOLEAN defaulted;
1393 BOOL ret = set_ntstatus( RtlGetOwnerSecurityDescriptor( pDescr, pOwner, &defaulted ));
1394 *lpbOwnerDefaulted = defaulted;
1395 return ret;
1398 /******************************************************************************
1399 * SetSecurityDescriptorOwner [ADVAPI32.@]
1401 * PARAMS
1403 BOOL WINAPI SetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1404 PSID pOwner, BOOL bOwnerDefaulted)
1406 return set_ntstatus( RtlSetOwnerSecurityDescriptor(pSecurityDescriptor, pOwner, bOwnerDefaulted));
1408 /******************************************************************************
1409 * GetSecurityDescriptorGroup [ADVAPI32.@]
1411 BOOL WINAPI GetSecurityDescriptorGroup(
1412 PSECURITY_DESCRIPTOR SecurityDescriptor,
1413 PSID *Group,
1414 LPBOOL GroupDefaulted)
1416 BOOLEAN defaulted;
1417 BOOL ret = set_ntstatus( RtlGetGroupSecurityDescriptor(SecurityDescriptor, Group, &defaulted ));
1418 *GroupDefaulted = defaulted;
1419 return ret;
1421 /******************************************************************************
1422 * SetSecurityDescriptorGroup [ADVAPI32.@]
1424 BOOL WINAPI SetSecurityDescriptorGroup ( PSECURITY_DESCRIPTOR SecurityDescriptor,
1425 PSID Group, BOOL GroupDefaulted)
1427 return set_ntstatus( RtlSetGroupSecurityDescriptor( SecurityDescriptor, Group, GroupDefaulted));
1430 /******************************************************************************
1431 * IsValidSecurityDescriptor [ADVAPI32.@]
1433 * PARAMS
1434 * lpsecdesc []
1436 BOOL WINAPI
1437 IsValidSecurityDescriptor( PSECURITY_DESCRIPTOR SecurityDescriptor )
1439 return set_ntstatus( RtlValidSecurityDescriptor(SecurityDescriptor));
1442 /******************************************************************************
1443 * GetSecurityDescriptorDacl [ADVAPI32.@]
1445 BOOL WINAPI GetSecurityDescriptorDacl(
1446 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1447 OUT LPBOOL lpbDaclPresent,
1448 OUT PACL *pDacl,
1449 OUT LPBOOL lpbDaclDefaulted)
1451 BOOLEAN present, defaulted;
1452 BOOL ret = set_ntstatus( RtlGetDaclSecurityDescriptor(pSecurityDescriptor, &present, pDacl, &defaulted));
1453 *lpbDaclPresent = present;
1454 *lpbDaclDefaulted = defaulted;
1455 return ret;
1458 /******************************************************************************
1459 * SetSecurityDescriptorDacl [ADVAPI32.@]
1461 BOOL WINAPI
1462 SetSecurityDescriptorDacl (
1463 PSECURITY_DESCRIPTOR lpsd,
1464 BOOL daclpresent,
1465 PACL dacl,
1466 BOOL dacldefaulted )
1468 return set_ntstatus( RtlSetDaclSecurityDescriptor (lpsd, daclpresent, dacl, dacldefaulted ) );
1470 /******************************************************************************
1471 * GetSecurityDescriptorSacl [ADVAPI32.@]
1473 BOOL WINAPI GetSecurityDescriptorSacl(
1474 IN PSECURITY_DESCRIPTOR lpsd,
1475 OUT LPBOOL lpbSaclPresent,
1476 OUT PACL *pSacl,
1477 OUT LPBOOL lpbSaclDefaulted)
1479 BOOLEAN present, defaulted;
1480 BOOL ret = set_ntstatus( RtlGetSaclSecurityDescriptor(lpsd, &present, pSacl, &defaulted) );
1481 *lpbSaclPresent = present;
1482 *lpbSaclDefaulted = defaulted;
1483 return ret;
1486 /**************************************************************************
1487 * SetSecurityDescriptorSacl [ADVAPI32.@]
1489 BOOL WINAPI SetSecurityDescriptorSacl (
1490 PSECURITY_DESCRIPTOR lpsd,
1491 BOOL saclpresent,
1492 PACL lpsacl,
1493 BOOL sacldefaulted)
1495 return set_ntstatus (RtlSetSaclSecurityDescriptor(lpsd, saclpresent, lpsacl, sacldefaulted));
1497 /******************************************************************************
1498 * MakeSelfRelativeSD [ADVAPI32.@]
1500 * PARAMS
1501 * lpabssecdesc []
1502 * lpselfsecdesc []
1503 * lpbuflen []
1505 BOOL WINAPI
1506 MakeSelfRelativeSD(
1507 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1508 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1509 IN OUT LPDWORD lpdwBufferLength)
1511 return set_ntstatus( RtlMakeSelfRelativeSD( pAbsoluteSecurityDescriptor,
1512 pSelfRelativeSecurityDescriptor, lpdwBufferLength));
1515 /******************************************************************************
1516 * GetSecurityDescriptorControl [ADVAPI32.@]
1519 BOOL WINAPI GetSecurityDescriptorControl ( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1520 PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD lpdwRevision)
1522 return set_ntstatus( RtlGetControlSecurityDescriptor(pSecurityDescriptor,pControl,lpdwRevision));
1525 /******************************************************************************
1526 * SetSecurityDescriptorControl [ADVAPI32.@]
1528 BOOL WINAPI SetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1529 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1530 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet )
1532 return set_ntstatus( RtlSetControlSecurityDescriptor(
1533 pSecurityDescriptor, ControlBitsOfInterest, ControlBitsToSet ) );
1536 /* ##############################
1537 ###### ACL FUNCTIONS ######
1538 ##############################
1541 /*************************************************************************
1542 * InitializeAcl [ADVAPI32.@]
1544 BOOL WINAPI InitializeAcl(PACL acl, DWORD size, DWORD rev)
1546 return set_ntstatus( RtlCreateAcl(acl, size, rev));
1549 BOOL WINAPI ImpersonateNamedPipeClient( HANDLE hNamedPipe )
1551 IO_STATUS_BLOCK io_block;
1553 TRACE("(%p)\n", hNamedPipe);
1555 return set_ntstatus( NtFsControlFile(hNamedPipe, NULL, NULL, NULL,
1556 &io_block, FSCTL_PIPE_IMPERSONATE, NULL, 0, NULL, 0) );
1559 /******************************************************************************
1560 * AddAccessAllowedAce [ADVAPI32.@]
1562 BOOL WINAPI AddAccessAllowedAce(
1563 IN OUT PACL pAcl,
1564 IN DWORD dwAceRevision,
1565 IN DWORD AccessMask,
1566 IN PSID pSid)
1568 return set_ntstatus(RtlAddAccessAllowedAce(pAcl, dwAceRevision, AccessMask, pSid));
1571 /******************************************************************************
1572 * AddAccessAllowedAceEx [ADVAPI32.@]
1574 BOOL WINAPI AddAccessAllowedAceEx(
1575 IN OUT PACL pAcl,
1576 IN DWORD dwAceRevision,
1577 IN DWORD AceFlags,
1578 IN DWORD AccessMask,
1579 IN PSID pSid)
1581 return set_ntstatus(RtlAddAccessAllowedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1584 /******************************************************************************
1585 * AddAccessDeniedAce [ADVAPI32.@]
1587 BOOL WINAPI AddAccessDeniedAce(
1588 IN OUT PACL pAcl,
1589 IN DWORD dwAceRevision,
1590 IN DWORD AccessMask,
1591 IN PSID pSid)
1593 return set_ntstatus(RtlAddAccessDeniedAce(pAcl, dwAceRevision, AccessMask, pSid));
1596 /******************************************************************************
1597 * AddAccessDeniedAceEx [ADVAPI32.@]
1599 BOOL WINAPI AddAccessDeniedAceEx(
1600 IN OUT PACL pAcl,
1601 IN DWORD dwAceRevision,
1602 IN DWORD AceFlags,
1603 IN DWORD AccessMask,
1604 IN PSID pSid)
1606 return set_ntstatus(RtlAddAccessDeniedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1609 /******************************************************************************
1610 * AddAce [ADVAPI32.@]
1612 BOOL WINAPI AddAce(
1613 IN OUT PACL pAcl,
1614 IN DWORD dwAceRevision,
1615 IN DWORD dwStartingAceIndex,
1616 LPVOID pAceList,
1617 DWORD nAceListLength)
1619 return set_ntstatus(RtlAddAce(pAcl, dwAceRevision, dwStartingAceIndex, pAceList, nAceListLength));
1622 BOOL WINAPI AddMandatoryAce(ACL *acl, DWORD ace_revision, DWORD ace_flags, DWORD mandatory_policy, PSID label_sid)
1624 FIXME("%p %x %x %x %p - stub\n", acl, ace_revision, ace_flags, mandatory_policy, label_sid);
1625 return FALSE;
1628 /******************************************************************************
1629 * DeleteAce [ADVAPI32.@]
1631 BOOL WINAPI DeleteAce(PACL pAcl, DWORD dwAceIndex)
1633 return set_ntstatus(RtlDeleteAce(pAcl, dwAceIndex));
1636 /******************************************************************************
1637 * FindFirstFreeAce [ADVAPI32.@]
1639 BOOL WINAPI FindFirstFreeAce(IN PACL pAcl, LPVOID * pAce)
1641 return RtlFirstFreeAce(pAcl, (PACE_HEADER *)pAce);
1644 /******************************************************************************
1645 * GetAce [ADVAPI32.@]
1647 BOOL WINAPI GetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1649 return set_ntstatus(RtlGetAce(pAcl, dwAceIndex, pAce));
1652 /******************************************************************************
1653 * GetAclInformation [ADVAPI32.@]
1655 BOOL WINAPI GetAclInformation(
1656 PACL pAcl,
1657 LPVOID pAclInformation,
1658 DWORD nAclInformationLength,
1659 ACL_INFORMATION_CLASS dwAclInformationClass)
1661 return set_ntstatus(RtlQueryInformationAcl(pAcl, pAclInformation,
1662 nAclInformationLength, dwAclInformationClass));
1665 /******************************************************************************
1666 * IsValidAcl [ADVAPI32.@]
1668 BOOL WINAPI IsValidAcl(IN PACL pAcl)
1670 return RtlValidAcl(pAcl);
1673 /* ##############################
1674 ###### MISC FUNCTIONS ######
1675 ##############################
1678 /******************************************************************************
1679 * AllocateLocallyUniqueId [ADVAPI32.@]
1681 * PARAMS
1682 * lpLuid []
1684 BOOL WINAPI AllocateLocallyUniqueId( PLUID lpLuid )
1686 return set_ntstatus(NtAllocateLocallyUniqueId(lpLuid));
1689 static const WCHAR SE_CREATE_TOKEN_NAME_W[] =
1690 { 'S','e','C','r','e','a','t','e','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 };
1691 static const WCHAR SE_ASSIGNPRIMARYTOKEN_NAME_W[] =
1692 { '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 };
1693 static const WCHAR SE_LOCK_MEMORY_NAME_W[] =
1694 { 'S','e','L','o','c','k','M','e','m','o','r','y','P','r','i','v','i','l','e','g','e',0 };
1695 static const WCHAR SE_INCREASE_QUOTA_NAME_W[] =
1696 { '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 };
1697 static const WCHAR SE_MACHINE_ACCOUNT_NAME_W[] =
1698 { '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 };
1699 static const WCHAR SE_TCB_NAME_W[] =
1700 { 'S','e','T','c','b','P','r','i','v','i','l','e','g','e',0 };
1701 static const WCHAR SE_SECURITY_NAME_W[] =
1702 { 'S','e','S','e','c','u','r','i','t','y','P','r','i','v','i','l','e','g','e',0 };
1703 static const WCHAR SE_TAKE_OWNERSHIP_NAME_W[] =
1704 { '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 };
1705 static const WCHAR SE_LOAD_DRIVER_NAME_W[] =
1706 { 'S','e','L','o','a','d','D','r','i','v','e','r','P','r','i','v','i','l','e','g','e',0 };
1707 static const WCHAR SE_SYSTEM_PROFILE_NAME_W[] =
1708 { '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 };
1709 static const WCHAR SE_SYSTEMTIME_NAME_W[] =
1710 { 'S','e','S','y','s','t','e','m','t','i','m','e','P','r','i','v','i','l','e','g','e',0 };
1711 static const WCHAR SE_PROF_SINGLE_PROCESS_NAME_W[] =
1712 { '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 };
1713 static const WCHAR SE_INC_BASE_PRIORITY_NAME_W[] =
1714 { '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 };
1715 static const WCHAR SE_CREATE_PAGEFILE_NAME_W[] =
1716 { '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 };
1717 static const WCHAR SE_CREATE_PERMANENT_NAME_W[] =
1718 { '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 };
1719 static const WCHAR SE_BACKUP_NAME_W[] =
1720 { 'S','e','B','a','c','k','u','p','P','r','i','v','i','l','e','g','e',0 };
1721 static const WCHAR SE_RESTORE_NAME_W[] =
1722 { 'S','e','R','e','s','t','o','r','e','P','r','i','v','i','l','e','g','e',0 };
1723 static const WCHAR SE_SHUTDOWN_NAME_W[] =
1724 { 'S','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 };
1725 static const WCHAR SE_DEBUG_NAME_W[] =
1726 { 'S','e','D','e','b','u','g','P','r','i','v','i','l','e','g','e',0 };
1727 static const WCHAR SE_AUDIT_NAME_W[] =
1728 { 'S','e','A','u','d','i','t','P','r','i','v','i','l','e','g','e',0 };
1729 static const WCHAR SE_SYSTEM_ENVIRONMENT_NAME_W[] =
1730 { '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 };
1731 static const WCHAR SE_CHANGE_NOTIFY_NAME_W[] =
1732 { 'S','e','C','h','a','n','g','e','N','o','t','i','f','y','P','r','i','v','i','l','e','g','e',0 };
1733 static const WCHAR SE_REMOTE_SHUTDOWN_NAME_W[] =
1734 { '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 };
1735 static const WCHAR SE_UNDOCK_NAME_W[] =
1736 { 'S','e','U','n','d','o','c','k','P','r','i','v','i','l','e','g','e',0 };
1737 static const WCHAR SE_SYNC_AGENT_NAME_W[] =
1738 { 'S','e','S','y','n','c','A','g','e','n','t','P','r','i','v','i','l','e','g','e',0 };
1739 static const WCHAR SE_ENABLE_DELEGATION_NAME_W[] =
1740 { '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 };
1741 static const WCHAR SE_MANAGE_VOLUME_NAME_W[] =
1742 { 'S','e','M','a','n','a','g','e','V','o','l','u','m','e','P','r','i','v','i','l','e','g','e',0 };
1743 static const WCHAR SE_IMPERSONATE_NAME_W[] =
1744 { 'S','e','I','m','p','e','r','s','o','n','a','t','e','P','r','i','v','i','l','e','g','e',0 };
1745 static const WCHAR SE_CREATE_GLOBAL_NAME_W[] =
1746 { 'S','e','C','r','e','a','t','e','G','l','o','b','a','l','P','r','i','v','i','l','e','g','e',0 };
1748 static const WCHAR * const WellKnownPrivNames[SE_MAX_WELL_KNOWN_PRIVILEGE + 1] =
1750 NULL,
1751 NULL,
1752 SE_CREATE_TOKEN_NAME_W,
1753 SE_ASSIGNPRIMARYTOKEN_NAME_W,
1754 SE_LOCK_MEMORY_NAME_W,
1755 SE_INCREASE_QUOTA_NAME_W,
1756 SE_MACHINE_ACCOUNT_NAME_W,
1757 SE_TCB_NAME_W,
1758 SE_SECURITY_NAME_W,
1759 SE_TAKE_OWNERSHIP_NAME_W,
1760 SE_LOAD_DRIVER_NAME_W,
1761 SE_SYSTEM_PROFILE_NAME_W,
1762 SE_SYSTEMTIME_NAME_W,
1763 SE_PROF_SINGLE_PROCESS_NAME_W,
1764 SE_INC_BASE_PRIORITY_NAME_W,
1765 SE_CREATE_PAGEFILE_NAME_W,
1766 SE_CREATE_PERMANENT_NAME_W,
1767 SE_BACKUP_NAME_W,
1768 SE_RESTORE_NAME_W,
1769 SE_SHUTDOWN_NAME_W,
1770 SE_DEBUG_NAME_W,
1771 SE_AUDIT_NAME_W,
1772 SE_SYSTEM_ENVIRONMENT_NAME_W,
1773 SE_CHANGE_NOTIFY_NAME_W,
1774 SE_REMOTE_SHUTDOWN_NAME_W,
1775 SE_UNDOCK_NAME_W,
1776 SE_SYNC_AGENT_NAME_W,
1777 SE_ENABLE_DELEGATION_NAME_W,
1778 SE_MANAGE_VOLUME_NAME_W,
1779 SE_IMPERSONATE_NAME_W,
1780 SE_CREATE_GLOBAL_NAME_W,
1783 /******************************************************************************
1784 * LookupPrivilegeValueW [ADVAPI32.@]
1786 * See LookupPrivilegeValueA.
1788 BOOL WINAPI
1789 LookupPrivilegeValueW( LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid )
1791 UINT i;
1793 TRACE("%s,%s,%p\n",debugstr_w(lpSystemName), debugstr_w(lpName), lpLuid);
1795 if (!ADVAPI_IsLocalComputer(lpSystemName))
1797 SetLastError(RPC_S_SERVER_UNAVAILABLE);
1798 return FALSE;
1800 if (!lpName)
1802 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1803 return FALSE;
1805 for( i=SE_MIN_WELL_KNOWN_PRIVILEGE; i<=SE_MAX_WELL_KNOWN_PRIVILEGE; i++ )
1807 if( !WellKnownPrivNames[i] )
1808 continue;
1809 if( strcmpiW( WellKnownPrivNames[i], lpName) )
1810 continue;
1811 lpLuid->LowPart = i;
1812 lpLuid->HighPart = 0;
1813 TRACE( "%s -> %08x-%08x\n",debugstr_w( lpSystemName ),
1814 lpLuid->HighPart, lpLuid->LowPart );
1815 return TRUE;
1817 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1818 return FALSE;
1821 /******************************************************************************
1822 * LookupPrivilegeValueA [ADVAPI32.@]
1824 * Retrieves LUID used on a system to represent the privilege name.
1826 * PARAMS
1827 * lpSystemName [I] Name of the system
1828 * lpName [I] Name of the privilege
1829 * lpLuid [O] Destination for the resulting LUID
1831 * RETURNS
1832 * Success: TRUE. lpLuid contains the requested LUID.
1833 * Failure: FALSE.
1835 BOOL WINAPI
1836 LookupPrivilegeValueA( LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid )
1838 UNICODE_STRING lpSystemNameW;
1839 UNICODE_STRING lpNameW;
1840 BOOL ret;
1842 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1843 RtlCreateUnicodeStringFromAsciiz(&lpNameW,lpName);
1844 ret = LookupPrivilegeValueW(lpSystemNameW.Buffer, lpNameW.Buffer, lpLuid);
1845 RtlFreeUnicodeString(&lpNameW);
1846 RtlFreeUnicodeString(&lpSystemNameW);
1847 return ret;
1850 BOOL WINAPI LookupPrivilegeDisplayNameA( LPCSTR lpSystemName, LPCSTR lpName, LPSTR lpDisplayName,
1851 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1853 FIXME("%s %s %s %p %p - stub\n", debugstr_a(lpSystemName), debugstr_a(lpName),
1854 debugstr_a(lpDisplayName), cchDisplayName, lpLanguageId);
1856 return FALSE;
1859 BOOL WINAPI LookupPrivilegeDisplayNameW( LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName,
1860 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1862 FIXME("%s %s %s %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpName),
1863 debugstr_w(lpDisplayName), cchDisplayName, lpLanguageId);
1865 return FALSE;
1868 /******************************************************************************
1869 * LookupPrivilegeNameA [ADVAPI32.@]
1871 * See LookupPrivilegeNameW.
1873 BOOL WINAPI
1874 LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName,
1875 LPDWORD cchName)
1877 UNICODE_STRING lpSystemNameW;
1878 BOOL ret;
1879 DWORD wLen = 0;
1881 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
1883 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1884 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
1885 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1887 LPWSTR lpNameW = heap_alloc(wLen * sizeof(WCHAR));
1889 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
1890 &wLen);
1891 if (ret)
1893 /* Windows crashes if cchName is NULL, so will I */
1894 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
1895 *cchName, NULL, NULL);
1897 if (len == 0)
1899 /* WideCharToMultiByte failed */
1900 ret = FALSE;
1902 else if (len > *cchName)
1904 *cchName = len;
1905 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1906 ret = FALSE;
1908 else
1910 /* WideCharToMultiByte succeeded, output length needs to be
1911 * length not including NULL terminator
1913 *cchName = len - 1;
1916 heap_free(lpNameW);
1918 RtlFreeUnicodeString(&lpSystemNameW);
1919 return ret;
1922 /******************************************************************************
1923 * LookupPrivilegeNameW [ADVAPI32.@]
1925 * Retrieves the privilege name referred to by the LUID lpLuid.
1927 * PARAMS
1928 * lpSystemName [I] Name of the system
1929 * lpLuid [I] Privilege value
1930 * lpName [O] Name of the privilege
1931 * cchName [I/O] Number of characters in lpName.
1933 * RETURNS
1934 * Success: TRUE. lpName contains the name of the privilege whose value is
1935 * *lpLuid.
1936 * Failure: FALSE.
1938 * REMARKS
1939 * Only well-known privilege names (those defined in winnt.h) can be retrieved
1940 * using this function.
1941 * If the length of lpName is too small, on return *cchName will contain the
1942 * number of WCHARs needed to contain the privilege, including the NULL
1943 * terminator, and GetLastError will return ERROR_INSUFFICIENT_BUFFER.
1944 * On success, *cchName will contain the number of characters stored in
1945 * lpName, NOT including the NULL terminator.
1947 BOOL WINAPI
1948 LookupPrivilegeNameW( LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName,
1949 LPDWORD cchName)
1951 size_t privNameLen;
1953 TRACE("%s,%p,%p,%p\n",debugstr_w(lpSystemName), lpLuid, lpName, cchName);
1955 if (!ADVAPI_IsLocalComputer(lpSystemName))
1957 SetLastError(RPC_S_SERVER_UNAVAILABLE);
1958 return FALSE;
1960 if (lpLuid->HighPart || (lpLuid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
1961 lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
1963 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1964 return FALSE;
1966 privNameLen = strlenW(WellKnownPrivNames[lpLuid->LowPart]);
1967 /* Windows crashes if cchName is NULL, so will I */
1968 if (*cchName <= privNameLen)
1970 *cchName = privNameLen + 1;
1971 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1972 return FALSE;
1974 else
1976 strcpyW(lpName, WellKnownPrivNames[lpLuid->LowPart]);
1977 *cchName = privNameLen;
1978 return TRUE;
1982 /******************************************************************************
1983 * GetFileSecurityA [ADVAPI32.@]
1985 * Obtains Specified information about the security of a file or directory.
1987 * PARAMS
1988 * lpFileName [I] Name of the file to get info for
1989 * RequestedInformation [I] SE_ flags from "winnt.h"
1990 * pSecurityDescriptor [O] Destination for security information
1991 * nLength [I] Length of pSecurityDescriptor
1992 * lpnLengthNeeded [O] Destination for length of returned security information
1994 * RETURNS
1995 * Success: TRUE. pSecurityDescriptor contains the requested information.
1996 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
1998 * NOTES
1999 * The information returned is constrained by the callers access rights and
2000 * privileges.
2002 BOOL WINAPI
2003 GetFileSecurityA( LPCSTR lpFileName,
2004 SECURITY_INFORMATION RequestedInformation,
2005 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2006 DWORD nLength, LPDWORD lpnLengthNeeded )
2008 BOOL r;
2009 LPWSTR name;
2011 name = SERV_dup(lpFileName);
2012 r = GetFileSecurityW( name, RequestedInformation, pSecurityDescriptor,
2013 nLength, lpnLengthNeeded );
2014 heap_free( name );
2016 return r;
2019 /******************************************************************************
2020 * GetFileSecurityW [ADVAPI32.@]
2022 * See GetFileSecurityA.
2024 BOOL WINAPI
2025 GetFileSecurityW( LPCWSTR lpFileName,
2026 SECURITY_INFORMATION RequestedInformation,
2027 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2028 DWORD nLength, LPDWORD lpnLengthNeeded )
2030 HANDLE hfile;
2031 NTSTATUS status;
2032 DWORD access = 0, err;
2034 TRACE("(%s,%d,%p,%d,%p)\n", debugstr_w(lpFileName),
2035 RequestedInformation, pSecurityDescriptor,
2036 nLength, lpnLengthNeeded);
2038 if (RequestedInformation & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|
2039 DACL_SECURITY_INFORMATION))
2040 access |= READ_CONTROL;
2041 if (RequestedInformation & SACL_SECURITY_INFORMATION)
2042 access |= ACCESS_SYSTEM_SECURITY;
2044 err = get_security_file( lpFileName, access, &hfile);
2045 if (err)
2047 SetLastError(err);
2048 return FALSE;
2051 status = NtQuerySecurityObject( hfile, RequestedInformation, pSecurityDescriptor,
2052 nLength, lpnLengthNeeded );
2053 CloseHandle( hfile );
2054 return set_ntstatus( status );
2058 /******************************************************************************
2059 * LookupAccountSidA [ADVAPI32.@]
2061 BOOL WINAPI
2062 LookupAccountSidA(
2063 IN LPCSTR system,
2064 IN PSID sid,
2065 OUT LPSTR account,
2066 IN OUT LPDWORD accountSize,
2067 OUT LPSTR domain,
2068 IN OUT LPDWORD domainSize,
2069 OUT PSID_NAME_USE name_use )
2071 DWORD len;
2072 BOOL r;
2073 LPWSTR systemW;
2074 LPWSTR accountW = NULL;
2075 LPWSTR domainW = NULL;
2076 DWORD accountSizeW = *accountSize;
2077 DWORD domainSizeW = *domainSize;
2079 systemW = SERV_dup(system);
2080 if (account)
2081 accountW = heap_alloc( accountSizeW * sizeof(WCHAR) );
2082 if (domain)
2083 domainW = heap_alloc( domainSizeW * sizeof(WCHAR) );
2085 r = LookupAccountSidW( systemW, sid, accountW, &accountSizeW, domainW, &domainSizeW, name_use );
2087 if (r) {
2088 if (accountW && *accountSize) {
2089 len = WideCharToMultiByte( CP_ACP, 0, accountW, -1, NULL, 0, NULL, NULL );
2090 WideCharToMultiByte( CP_ACP, 0, accountW, -1, account, len, NULL, NULL );
2091 *accountSize = len;
2092 } else
2093 *accountSize = accountSizeW + 1;
2095 if (domainW && *domainSize) {
2096 len = WideCharToMultiByte( CP_ACP, 0, domainW, -1, NULL, 0, NULL, NULL );
2097 WideCharToMultiByte( CP_ACP, 0, domainW, -1, domain, len, NULL, NULL );
2098 *domainSize = len;
2099 } else
2100 *domainSize = domainSizeW + 1;
2102 else
2104 *accountSize = accountSizeW + 1;
2105 *domainSize = domainSizeW + 1;
2108 heap_free( systemW );
2109 heap_free( accountW );
2110 heap_free( domainW );
2112 return r;
2115 /******************************************************************************
2116 * LookupAccountSidW [ADVAPI32.@]
2118 * PARAMS
2119 * system []
2120 * sid []
2121 * account []
2122 * accountSize []
2123 * domain []
2124 * domainSize []
2125 * name_use []
2128 BOOL WINAPI
2129 LookupAccountSidW(
2130 IN LPCWSTR system,
2131 IN PSID sid,
2132 OUT LPWSTR account,
2133 IN OUT LPDWORD accountSize,
2134 OUT LPWSTR domain,
2135 IN OUT LPDWORD domainSize,
2136 OUT PSID_NAME_USE name_use )
2138 unsigned int i, j;
2139 const WCHAR * ac = NULL;
2140 const WCHAR * dm = NULL;
2141 SID_NAME_USE use = 0;
2142 LPWSTR computer_name = NULL;
2143 LPWSTR account_name = NULL;
2145 TRACE("(%s,sid=%s,%p,%p(%u),%p,%p(%u),%p)\n",
2146 debugstr_w(system),debugstr_sid(sid),
2147 account,accountSize,accountSize?*accountSize:0,
2148 domain,domainSize,domainSize?*domainSize:0,
2149 name_use);
2151 if (!ADVAPI_IsLocalComputer(system)) {
2152 FIXME("Only local computer supported!\n");
2153 SetLastError(RPC_S_SERVER_UNAVAILABLE);
2154 return FALSE;
2157 /* check the well known SIDs first */
2158 for (i = 0; i <= 60; i++) {
2159 if (IsWellKnownSid(sid, i)) {
2160 for (j = 0; j < (sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0])); j++) {
2161 if (ACCOUNT_SIDS[j].type == i) {
2162 ac = ACCOUNT_SIDS[j].account;
2163 dm = ACCOUNT_SIDS[j].domain;
2164 use = ACCOUNT_SIDS[j].name_use;
2167 break;
2171 if (dm == NULL) {
2172 MAX_SID local;
2174 /* check for the local computer next */
2175 if (ADVAPI_GetComputerSid(&local)) {
2176 DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
2177 BOOL result;
2179 computer_name = heap_alloc(size * sizeof(WCHAR));
2180 result = GetComputerNameW(computer_name, &size);
2182 if (result) {
2183 if (EqualSid(sid, &local)) {
2184 dm = computer_name;
2185 ac = Blank;
2186 use = 3;
2187 } else {
2188 local.SubAuthorityCount++;
2190 if (EqualPrefixSid(sid, &local)) {
2191 dm = computer_name;
2192 use = 1;
2193 switch (((MAX_SID *)sid)->SubAuthority[4]) {
2194 case DOMAIN_USER_RID_ADMIN:
2195 ac = Administrator;
2196 break;
2197 case DOMAIN_USER_RID_GUEST:
2198 ac = Guest;
2199 break;
2200 case DOMAIN_GROUP_RID_ADMINS:
2201 ac = Domain_Admins;
2202 break;
2203 case DOMAIN_GROUP_RID_USERS:
2204 ac = Domain_Users;
2205 break;
2206 case DOMAIN_GROUP_RID_GUESTS:
2207 ac = Domain_Guests;
2208 break;
2209 case DOMAIN_GROUP_RID_COMPUTERS:
2210 ac = Domain_Computers;
2211 break;
2212 case DOMAIN_GROUP_RID_CONTROLLERS:
2213 ac = Domain_Controllers;
2214 break;
2215 case DOMAIN_GROUP_RID_CERT_ADMINS:
2216 ac = Cert_Publishers;
2217 break;
2218 case DOMAIN_GROUP_RID_SCHEMA_ADMINS:
2219 ac = Schema_Admins;
2220 break;
2221 case DOMAIN_GROUP_RID_ENTERPRISE_ADMINS:
2222 ac = Enterprise_Admins;
2223 break;
2224 case DOMAIN_GROUP_RID_POLICY_ADMINS:
2225 ac = Group_Policy_Creator_Owners;
2226 break;
2227 case DOMAIN_ALIAS_RID_RAS_SERVERS:
2228 ac = RAS_and_IAS_Servers;
2229 break;
2230 case 1000: /* first user account */
2231 size = UNLEN + 1;
2232 account_name = heap_alloc(size * sizeof(WCHAR));
2233 if (GetUserNameW(account_name, &size))
2234 ac = account_name;
2235 else
2236 dm = NULL;
2238 break;
2239 default:
2240 dm = NULL;
2241 break;
2249 if (dm) {
2250 DWORD ac_len = lstrlenW(ac);
2251 DWORD dm_len = lstrlenW(dm);
2252 BOOL status = TRUE;
2254 if (*accountSize > ac_len) {
2255 if (account)
2256 lstrcpyW(account, ac);
2258 if (*domainSize > dm_len) {
2259 if (domain)
2260 lstrcpyW(domain, dm);
2262 if ((*accountSize && *accountSize < ac_len) ||
2263 (!account && !*accountSize && ac_len) ||
2264 (*domainSize && *domainSize < dm_len) ||
2265 (!domain && !*domainSize && dm_len))
2267 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2268 status = FALSE;
2270 if (*domainSize)
2271 *domainSize = dm_len;
2272 else
2273 *domainSize = dm_len + 1;
2274 if (*accountSize)
2275 *accountSize = ac_len;
2276 else
2277 *accountSize = ac_len + 1;
2279 heap_free(account_name);
2280 heap_free(computer_name);
2281 if (status) *name_use = use;
2282 return status;
2285 heap_free(account_name);
2286 heap_free(computer_name);
2287 SetLastError(ERROR_NONE_MAPPED);
2288 return FALSE;
2291 /******************************************************************************
2292 * SetFileSecurityA [ADVAPI32.@]
2294 * See SetFileSecurityW.
2296 BOOL WINAPI SetFileSecurityA( LPCSTR lpFileName,
2297 SECURITY_INFORMATION RequestedInformation,
2298 PSECURITY_DESCRIPTOR pSecurityDescriptor)
2300 BOOL r;
2301 LPWSTR name;
2303 name = SERV_dup(lpFileName);
2304 r = SetFileSecurityW( name, RequestedInformation, pSecurityDescriptor );
2305 heap_free( name );
2307 return r;
2310 /******************************************************************************
2311 * SetFileSecurityW [ADVAPI32.@]
2313 * Sets the security of a file or directory.
2315 * PARAMS
2316 * lpFileName []
2317 * RequestedInformation []
2318 * pSecurityDescriptor []
2320 * RETURNS
2321 * Success: TRUE.
2322 * Failure: FALSE.
2324 BOOL WINAPI
2325 SetFileSecurityW( LPCWSTR lpFileName,
2326 SECURITY_INFORMATION RequestedInformation,
2327 PSECURITY_DESCRIPTOR pSecurityDescriptor )
2329 HANDLE file;
2330 DWORD access = 0, err;
2331 NTSTATUS status;
2333 TRACE("(%s, 0x%x, %p)\n", debugstr_w(lpFileName), RequestedInformation,
2334 pSecurityDescriptor );
2336 if (RequestedInformation & OWNER_SECURITY_INFORMATION ||
2337 RequestedInformation & GROUP_SECURITY_INFORMATION)
2338 access |= WRITE_OWNER;
2339 if (RequestedInformation & SACL_SECURITY_INFORMATION)
2340 access |= ACCESS_SYSTEM_SECURITY;
2341 if (RequestedInformation & DACL_SECURITY_INFORMATION)
2342 access |= WRITE_DAC;
2344 err = get_security_file( lpFileName, access, &file);
2345 if (err)
2347 SetLastError(err);
2348 return FALSE;
2351 status = NtSetSecurityObject( file, RequestedInformation, pSecurityDescriptor );
2352 CloseHandle( file );
2353 return set_ntstatus( status );
2356 /******************************************************************************
2357 * QueryWindows31FilesMigration [ADVAPI32.@]
2359 * PARAMS
2360 * x1 []
2362 BOOL WINAPI
2363 QueryWindows31FilesMigration( DWORD x1 )
2365 FIXME("(%d):stub\n",x1);
2366 return TRUE;
2369 /******************************************************************************
2370 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
2372 * PARAMS
2373 * x1 []
2374 * x2 []
2375 * x3 []
2376 * x4 []
2378 BOOL WINAPI
2379 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
2380 DWORD x4 )
2382 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
2383 return TRUE;
2386 /******************************************************************************
2387 * NotifyBootConfigStatus [ADVAPI32.@]
2389 * PARAMS
2390 * x1 []
2392 BOOL WINAPI
2393 NotifyBootConfigStatus( BOOL x1 )
2395 FIXME("(0x%08d):stub\n",x1);
2396 return TRUE;
2399 /******************************************************************************
2400 * RevertToSelf [ADVAPI32.@]
2402 * Ends the impersonation of a user.
2404 * PARAMS
2405 * void []
2407 * RETURNS
2408 * Success: TRUE.
2409 * Failure: FALSE.
2411 BOOL WINAPI
2412 RevertToSelf( void )
2414 HANDLE Token = NULL;
2415 return set_ntstatus( NtSetInformationThread( GetCurrentThread(),
2416 ThreadImpersonationToken, &Token, sizeof(Token) ) );
2419 /******************************************************************************
2420 * ImpersonateSelf [ADVAPI32.@]
2422 * Makes an impersonation token that represents the process user and assigns
2423 * to the current thread.
2425 * PARAMS
2426 * ImpersonationLevel [I] Level at which to impersonate.
2428 * RETURNS
2429 * Success: TRUE.
2430 * Failure: FALSE.
2432 BOOL WINAPI
2433 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
2435 return set_ntstatus( RtlImpersonateSelf( ImpersonationLevel ) );
2438 /******************************************************************************
2439 * ImpersonateLoggedOnUser [ADVAPI32.@]
2441 BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken)
2443 DWORD size;
2444 NTSTATUS Status;
2445 HANDLE ImpersonationToken;
2446 TOKEN_TYPE Type;
2447 static BOOL warn = TRUE;
2449 if (warn)
2451 FIXME( "(%p)\n", hToken );
2452 warn = FALSE;
2454 if (!GetTokenInformation( hToken, TokenType, &Type,
2455 sizeof(TOKEN_TYPE), &size ))
2456 return FALSE;
2458 if (Type == TokenPrimary)
2460 OBJECT_ATTRIBUTES ObjectAttributes;
2462 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
2464 Status = NtDuplicateToken( hToken,
2465 TOKEN_IMPERSONATE | TOKEN_QUERY,
2466 &ObjectAttributes,
2467 SecurityImpersonation,
2468 TokenImpersonation,
2469 &ImpersonationToken );
2470 if (Status != STATUS_SUCCESS)
2472 ERR( "NtDuplicateToken failed with error 0x%08x\n", Status );
2473 SetLastError( RtlNtStatusToDosError( Status ) );
2474 return FALSE;
2477 else
2478 ImpersonationToken = hToken;
2480 Status = NtSetInformationThread( GetCurrentThread(),
2481 ThreadImpersonationToken,
2482 &ImpersonationToken,
2483 sizeof(ImpersonationToken) );
2485 if (Type == TokenPrimary)
2486 NtClose( ImpersonationToken );
2488 if (Status != STATUS_SUCCESS)
2490 ERR( "NtSetInformationThread failed with error 0x%08x\n", Status );
2491 SetLastError( RtlNtStatusToDosError( Status ) );
2492 return FALSE;
2495 return TRUE;
2498 /******************************************************************************
2499 * AccessCheck [ADVAPI32.@]
2501 BOOL WINAPI
2502 AccessCheck(
2503 PSECURITY_DESCRIPTOR SecurityDescriptor,
2504 HANDLE ClientToken,
2505 DWORD DesiredAccess,
2506 PGENERIC_MAPPING GenericMapping,
2507 PPRIVILEGE_SET PrivilegeSet,
2508 LPDWORD PrivilegeSetLength,
2509 LPDWORD GrantedAccess,
2510 LPBOOL AccessStatus)
2512 NTSTATUS access_status;
2513 BOOL ret = set_ntstatus( NtAccessCheck(SecurityDescriptor, ClientToken, DesiredAccess,
2514 GenericMapping, PrivilegeSet, PrivilegeSetLength,
2515 GrantedAccess, &access_status) );
2516 if (ret) *AccessStatus = set_ntstatus( access_status );
2517 return ret;
2521 /******************************************************************************
2522 * AccessCheckByType [ADVAPI32.@]
2524 BOOL WINAPI AccessCheckByType(
2525 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2526 PSID PrincipalSelfSid,
2527 HANDLE ClientToken,
2528 DWORD DesiredAccess,
2529 POBJECT_TYPE_LIST ObjectTypeList,
2530 DWORD ObjectTypeListLength,
2531 PGENERIC_MAPPING GenericMapping,
2532 PPRIVILEGE_SET PrivilegeSet,
2533 LPDWORD PrivilegeSetLength,
2534 LPDWORD GrantedAccess,
2535 LPBOOL AccessStatus)
2537 FIXME("stub\n");
2539 *AccessStatus = TRUE;
2541 return !*AccessStatus;
2544 /******************************************************************************
2545 * MapGenericMask [ADVAPI32.@]
2547 * Maps generic access rights into specific access rights according to the
2548 * supplied mapping.
2550 * PARAMS
2551 * AccessMask [I/O] Access rights.
2552 * GenericMapping [I] The mapping between generic and specific rights.
2554 * RETURNS
2555 * Nothing.
2557 VOID WINAPI MapGenericMask( PDWORD AccessMask, PGENERIC_MAPPING GenericMapping )
2559 RtlMapGenericMask( AccessMask, GenericMapping );
2562 /*************************************************************************
2563 * SetKernelObjectSecurity [ADVAPI32.@]
2565 BOOL WINAPI SetKernelObjectSecurity (
2566 IN HANDLE Handle,
2567 IN SECURITY_INFORMATION SecurityInformation,
2568 IN PSECURITY_DESCRIPTOR SecurityDescriptor )
2570 return set_ntstatus (NtSetSecurityObject (Handle, SecurityInformation, SecurityDescriptor));
2574 /******************************************************************************
2575 * AddAuditAccessAce [ADVAPI32.@]
2577 BOOL WINAPI AddAuditAccessAce(
2578 IN OUT PACL pAcl,
2579 IN DWORD dwAceRevision,
2580 IN DWORD dwAccessMask,
2581 IN PSID pSid,
2582 IN BOOL bAuditSuccess,
2583 IN BOOL bAuditFailure)
2585 return set_ntstatus( RtlAddAuditAccessAce(pAcl, dwAceRevision, dwAccessMask, pSid,
2586 bAuditSuccess, bAuditFailure) );
2589 /******************************************************************************
2590 * AddAuditAccessAce [ADVAPI32.@]
2592 BOOL WINAPI AddAuditAccessAceEx(
2593 IN OUT PACL pAcl,
2594 IN DWORD dwAceRevision,
2595 IN DWORD dwAceFlags,
2596 IN DWORD dwAccessMask,
2597 IN PSID pSid,
2598 IN BOOL bAuditSuccess,
2599 IN BOOL bAuditFailure)
2601 return set_ntstatus( RtlAddAuditAccessAceEx(pAcl, dwAceRevision, dwAceFlags, dwAccessMask, pSid,
2602 bAuditSuccess, bAuditFailure) );
2605 /******************************************************************************
2606 * LookupAccountNameA [ADVAPI32.@]
2608 BOOL WINAPI
2609 LookupAccountNameA(
2610 IN LPCSTR system,
2611 IN LPCSTR account,
2612 OUT PSID sid,
2613 OUT LPDWORD cbSid,
2614 LPSTR ReferencedDomainName,
2615 IN OUT LPDWORD cbReferencedDomainName,
2616 OUT PSID_NAME_USE name_use )
2618 BOOL ret;
2619 UNICODE_STRING lpSystemW;
2620 UNICODE_STRING lpAccountW;
2621 LPWSTR lpReferencedDomainNameW = NULL;
2623 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, system);
2624 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, account);
2626 if (ReferencedDomainName)
2627 lpReferencedDomainNameW = heap_alloc(*cbReferencedDomainName * sizeof(WCHAR));
2629 ret = LookupAccountNameW(lpSystemW.Buffer, lpAccountW.Buffer, sid, cbSid, lpReferencedDomainNameW,
2630 cbReferencedDomainName, name_use);
2632 if (ret && lpReferencedDomainNameW)
2634 WideCharToMultiByte(CP_ACP, 0, lpReferencedDomainNameW, -1,
2635 ReferencedDomainName, *cbReferencedDomainName+1, NULL, NULL);
2638 RtlFreeUnicodeString(&lpSystemW);
2639 RtlFreeUnicodeString(&lpAccountW);
2640 heap_free(lpReferencedDomainNameW);
2642 return ret;
2645 /******************************************************************************
2646 * lookup_user_account_name
2648 static BOOL lookup_user_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2649 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2651 char buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
2652 DWORD len = sizeof(buffer);
2653 HANDLE token;
2654 BOOL ret;
2655 PSID pSid;
2656 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
2657 DWORD nameLen;
2659 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
2661 if (GetLastError() != ERROR_NO_TOKEN) return FALSE;
2662 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) return FALSE;
2665 ret = GetTokenInformation(token, TokenUser, buffer, len, &len);
2666 CloseHandle( token );
2668 if (!ret) return FALSE;
2670 pSid = ((TOKEN_USER *)buffer)->User.Sid;
2672 if (Sid != NULL && (*cbSid >= GetLengthSid(pSid)))
2673 CopySid(*cbSid, Sid, pSid);
2674 if (*cbSid < GetLengthSid(pSid))
2676 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2677 ret = FALSE;
2679 *cbSid = GetLengthSid(pSid);
2681 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
2682 if (!GetComputerNameW(domainName, &nameLen))
2684 domainName[0] = 0;
2685 nameLen = 0;
2687 if (*cchReferencedDomainName <= nameLen || !ret)
2689 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2690 nameLen += 1;
2691 ret = FALSE;
2693 else if (ReferencedDomainName)
2694 strcpyW(ReferencedDomainName, domainName);
2696 *cchReferencedDomainName = nameLen;
2698 if (ret)
2699 *peUse = SidTypeUser;
2701 return ret;
2704 /******************************************************************************
2705 * lookup_computer_account_name
2707 static BOOL lookup_computer_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2708 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2710 MAX_SID local;
2711 BOOL ret;
2712 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
2713 DWORD nameLen;
2715 if ((ret = ADVAPI_GetComputerSid(&local)))
2717 if (Sid != NULL && (*cbSid >= GetLengthSid(&local)))
2718 CopySid(*cbSid, Sid, &local);
2719 if (*cbSid < GetLengthSid(&local))
2721 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2722 ret = FALSE;
2724 *cbSid = GetLengthSid(&local);
2727 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
2728 if (!GetComputerNameW(domainName, &nameLen))
2730 domainName[0] = 0;
2731 nameLen = 0;
2733 if (*cchReferencedDomainName <= nameLen || !ret)
2735 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2736 nameLen += 1;
2737 ret = FALSE;
2739 else if (ReferencedDomainName)
2740 strcpyW(ReferencedDomainName, domainName);
2742 *cchReferencedDomainName = nameLen;
2744 if (ret)
2745 *peUse = SidTypeDomain;
2747 return ret;
2750 static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STRING *account,
2751 LSA_UNICODE_STRING *domain )
2753 WCHAR *p = str->Buffer + str->Length / sizeof(WCHAR) - 1;
2755 while (p > str->Buffer && *p != '\\') p--;
2757 if (*p == '\\')
2759 domain->Buffer = str->Buffer;
2760 domain->Length = (p - str->Buffer) * sizeof(WCHAR);
2762 account->Buffer = p + 1;
2763 account->Length = str->Length - ((p - str->Buffer + 1) * sizeof(WCHAR));
2765 else
2767 domain->Buffer = NULL;
2768 domain->Length = 0;
2770 account->Buffer = str->Buffer;
2771 account->Length = str->Length;
2775 static BOOL match_domain( ULONG idx, const LSA_UNICODE_STRING *domain )
2777 ULONG len = strlenW( ACCOUNT_SIDS[idx].domain );
2779 if (len == domain->Length / sizeof(WCHAR) && !strncmpiW( domain->Buffer, ACCOUNT_SIDS[idx].domain, len ))
2780 return TRUE;
2782 return FALSE;
2785 static BOOL match_account( ULONG idx, const LSA_UNICODE_STRING *account )
2787 ULONG len = strlenW( ACCOUNT_SIDS[idx].account );
2789 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].account, len ))
2790 return TRUE;
2792 if (ACCOUNT_SIDS[idx].alias)
2794 len = strlenW( ACCOUNT_SIDS[idx].alias );
2795 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].alias, len ))
2796 return TRUE;
2798 return FALSE;
2802 * Helper function for LookupAccountNameW
2804 BOOL lookup_local_wellknown_name( const LSA_UNICODE_STRING *account_and_domain,
2805 PSID Sid, LPDWORD cbSid,
2806 LPWSTR ReferencedDomainName,
2807 LPDWORD cchReferencedDomainName,
2808 PSID_NAME_USE peUse, BOOL *handled )
2810 PSID pSid;
2811 LSA_UNICODE_STRING account, domain;
2812 BOOL ret = TRUE;
2813 ULONG i;
2815 *handled = FALSE;
2816 split_domain_account( account_and_domain, &account, &domain );
2818 for (i = 0; i < sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0]); i++)
2820 /* check domain first */
2821 if (domain.Buffer && !match_domain( i, &domain )) continue;
2823 if (match_account( i, &account ))
2825 DWORD len, sidLen = SECURITY_MAX_SID_SIZE;
2827 if (!(pSid = heap_alloc( sidLen ))) return FALSE;
2829 if ((ret = CreateWellKnownSid( ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen )))
2831 if (*cbSid < sidLen)
2833 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2834 ret = FALSE;
2836 else if (Sid)
2838 CopySid(*cbSid, Sid, pSid);
2840 *cbSid = sidLen;
2843 len = strlenW( ACCOUNT_SIDS[i].domain );
2844 if (*cchReferencedDomainName <= len || !ret)
2846 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2847 len++;
2848 ret = FALSE;
2850 else if (ReferencedDomainName)
2852 strcpyW( ReferencedDomainName, ACCOUNT_SIDS[i].domain );
2855 *cchReferencedDomainName = len;
2856 if (ret)
2857 *peUse = ACCOUNT_SIDS[i].name_use;
2859 heap_free(pSid);
2860 *handled = TRUE;
2861 return ret;
2864 return ret;
2867 BOOL lookup_local_user_name( const LSA_UNICODE_STRING *account_and_domain,
2868 PSID Sid, LPDWORD cbSid,
2869 LPWSTR ReferencedDomainName,
2870 LPDWORD cchReferencedDomainName,
2871 PSID_NAME_USE peUse, BOOL *handled )
2873 DWORD nameLen;
2874 LPWSTR userName = NULL;
2875 LSA_UNICODE_STRING account, domain;
2876 BOOL ret = TRUE;
2878 *handled = FALSE;
2879 split_domain_account( account_and_domain, &account, &domain );
2881 /* Let the current Unix user id masquerade as first Windows user account */
2883 nameLen = UNLEN + 1;
2884 if (!(userName = heap_alloc( nameLen * sizeof(WCHAR) ))) return FALSE;
2886 if (domain.Buffer)
2888 /* check to make sure this account is on this computer */
2889 if (GetComputerNameW( userName, &nameLen ) &&
2890 (domain.Length / sizeof(WCHAR) != nameLen || strncmpW( domain.Buffer, userName, nameLen )))
2892 SetLastError(ERROR_NONE_MAPPED);
2893 ret = FALSE;
2895 nameLen = UNLEN + 1;
2898 if (GetUserNameW( userName, &nameLen ) &&
2899 account.Length / sizeof(WCHAR) == nameLen - 1 && !strncmpW( account.Buffer, userName, nameLen - 1 ))
2901 ret = lookup_user_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2902 *handled = TRUE;
2904 else
2906 nameLen = UNLEN + 1;
2907 if (GetComputerNameW( userName, &nameLen ) &&
2908 account.Length / sizeof(WCHAR) == nameLen && !strncmpW( account.Buffer, userName , nameLen ))
2910 ret = lookup_computer_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2911 *handled = TRUE;
2915 heap_free(userName);
2916 return ret;
2919 /******************************************************************************
2920 * LookupAccountNameW [ADVAPI32.@]
2922 BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
2923 LPDWORD cbSid, LPWSTR ReferencedDomainName,
2924 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2926 BOOL ret, handled;
2927 LSA_UNICODE_STRING account;
2929 TRACE("%s %s %p %p %p %p %p\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
2930 Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
2932 if (!ADVAPI_IsLocalComputer( lpSystemName ))
2934 FIXME("remote computer not supported\n");
2935 SetLastError( RPC_S_SERVER_UNAVAILABLE );
2936 return FALSE;
2939 if (!lpAccountName || !strcmpW( lpAccountName, Blank ))
2941 lpAccountName = BUILTIN;
2944 RtlInitUnicodeString( &account, lpAccountName );
2946 /* Check well known SIDs first */
2947 ret = lookup_local_wellknown_name( &account, Sid, cbSid, ReferencedDomainName,
2948 cchReferencedDomainName, peUse, &handled );
2949 if (handled)
2950 return ret;
2952 /* Check user names */
2953 ret = lookup_local_user_name( &account, Sid, cbSid, ReferencedDomainName,
2954 cchReferencedDomainName, peUse, &handled);
2955 if (handled)
2956 return ret;
2958 SetLastError( ERROR_NONE_MAPPED );
2959 return FALSE;
2962 /******************************************************************************
2963 * PrivilegeCheck [ADVAPI32.@]
2965 BOOL WINAPI PrivilegeCheck( HANDLE ClientToken, PPRIVILEGE_SET RequiredPrivileges, LPBOOL pfResult)
2967 BOOL ret;
2968 BOOLEAN Result;
2970 TRACE("%p %p %p\n", ClientToken, RequiredPrivileges, pfResult);
2972 ret = set_ntstatus (NtPrivilegeCheck (ClientToken, RequiredPrivileges, &Result));
2973 if (ret)
2974 *pfResult = Result;
2975 return ret;
2978 /******************************************************************************
2979 * AccessCheckAndAuditAlarmA [ADVAPI32.@]
2981 BOOL WINAPI AccessCheckAndAuditAlarmA(LPCSTR Subsystem, LPVOID HandleId, LPSTR ObjectTypeName,
2982 LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
2983 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
2984 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
2986 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_a(Subsystem),
2987 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName),
2988 SecurityDescriptor, DesiredAccess, GenericMapping,
2989 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
2990 return TRUE;
2993 /******************************************************************************
2994 * AccessCheckAndAuditAlarmW [ADVAPI32.@]
2996 BOOL WINAPI AccessCheckAndAuditAlarmW(LPCWSTR Subsystem, LPVOID HandleId, LPWSTR ObjectTypeName,
2997 LPWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
2998 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
2999 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
3001 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_w(Subsystem),
3002 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName),
3003 SecurityDescriptor, DesiredAccess, GenericMapping,
3004 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
3005 return TRUE;
3008 BOOL WINAPI ObjectCloseAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3010 FIXME("stub (%s,%p,%x)\n", debugstr_a(SubsystemName), HandleId, GenerateOnClose);
3012 return TRUE;
3015 BOOL WINAPI ObjectCloseAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3017 FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
3019 return TRUE;
3022 BOOL WINAPI ObjectDeleteAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3024 FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
3026 return TRUE;
3029 BOOL WINAPI ObjectOpenAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName,
3030 LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3031 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3032 LPBOOL GenerateOnClose)
3034 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_a(SubsystemName),
3035 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName), pSecurityDescriptor,
3036 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3037 GenerateOnClose);
3039 return TRUE;
3042 BOOL WINAPI ObjectOpenAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName,
3043 LPWSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3044 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3045 LPBOOL GenerateOnClose)
3047 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_w(SubsystemName),
3048 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName), pSecurityDescriptor,
3049 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3050 GenerateOnClose);
3052 return TRUE;
3055 BOOL WINAPI ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3056 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3058 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_a(SubsystemName), HandleId, ClientToken,
3059 DesiredAccess, Privileges, AccessGranted);
3061 return TRUE;
3064 BOOL WINAPI ObjectPrivilegeAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3065 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3067 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_w(SubsystemName), HandleId, ClientToken,
3068 DesiredAccess, Privileges, AccessGranted);
3070 return TRUE;
3073 BOOL WINAPI PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken,
3074 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3076 FIXME("stub (%s,%s,%p,%p,%x)\n", debugstr_a(SubsystemName), debugstr_a(ServiceName),
3077 ClientToken, Privileges, AccessGranted);
3079 return TRUE;
3082 BOOL WINAPI PrivilegedServiceAuditAlarmW( LPCWSTR SubsystemName, LPCWSTR ServiceName, HANDLE ClientToken,
3083 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3085 FIXME("stub %s,%s,%p,%p,%x)\n", debugstr_w(SubsystemName), debugstr_w(ServiceName),
3086 ClientToken, Privileges, AccessGranted);
3088 return TRUE;
3091 /******************************************************************************
3092 * GetSecurityInfo [ADVAPI32.@]
3094 * Retrieves a copy of the security descriptor associated with an object.
3096 * PARAMS
3097 * hObject [I] A handle for the object.
3098 * ObjectType [I] The type of object.
3099 * SecurityInfo [I] A bitmask indicating what info to retrieve.
3100 * ppsidOwner [O] If non-null, receives a pointer to the owner SID.
3101 * ppsidGroup [O] If non-null, receives a pointer to the group SID.
3102 * ppDacl [O] If non-null, receives a pointer to the DACL.
3103 * ppSacl [O] If non-null, receives a pointer to the SACL.
3104 * ppSecurityDescriptor [O] Receives a pointer to the security descriptor,
3105 * which must be freed with LocalFree.
3107 * RETURNS
3108 * ERROR_SUCCESS if all's well, and a WIN32 error code otherwise.
3110 DWORD WINAPI GetSecurityInfo(
3111 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3112 SECURITY_INFORMATION SecurityInfo, PSID *ppsidOwner,
3113 PSID *ppsidGroup, PACL *ppDacl, PACL *ppSacl,
3114 PSECURITY_DESCRIPTOR *ppSecurityDescriptor
3117 PSECURITY_DESCRIPTOR sd;
3118 NTSTATUS status;
3119 ULONG n1, n2;
3120 BOOL present, defaulted;
3122 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
3123 if (!(ppsidOwner||ppsidGroup||ppDacl||ppSacl||ppSecurityDescriptor)) return ERROR_INVALID_PARAMETER;
3125 /* If no descriptor, we have to check that there's a pointer for the requested information */
3126 if( !ppSecurityDescriptor && (
3127 ((SecurityInfo & OWNER_SECURITY_INFORMATION) && !ppsidOwner)
3128 || ((SecurityInfo & GROUP_SECURITY_INFORMATION) && !ppsidGroup)
3129 || ((SecurityInfo & DACL_SECURITY_INFORMATION) && !ppDacl)
3130 || ((SecurityInfo & SACL_SECURITY_INFORMATION) && !ppSacl) ))
3131 return ERROR_INVALID_PARAMETER;
3133 switch (ObjectType)
3135 case SE_SERVICE:
3136 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, NULL, 0, &n1);
3137 break;
3138 default:
3139 status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1);
3140 break;
3142 if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS)
3143 return RtlNtStatusToDosError(status);
3145 sd = LocalAlloc(0, n1);
3146 if (!sd)
3147 return ERROR_NOT_ENOUGH_MEMORY;
3149 switch (ObjectType)
3151 case SE_SERVICE:
3152 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, sd, n1, &n2);
3153 break;
3154 default:
3155 status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2);
3156 break;
3158 if (status != STATUS_SUCCESS)
3160 LocalFree(sd);
3161 return RtlNtStatusToDosError(status);
3164 if (ppsidOwner)
3166 *ppsidOwner = NULL;
3167 GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted);
3169 if (ppsidGroup)
3171 *ppsidGroup = NULL;
3172 GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted);
3174 if (ppDacl)
3176 *ppDacl = NULL;
3177 GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted);
3179 if (ppSacl)
3181 *ppSacl = NULL;
3182 GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted);
3184 if (ppSecurityDescriptor)
3185 *ppSecurityDescriptor = sd;
3187 /* The security descriptor (sd) cannot be freed if ppSecurityDescriptor is
3188 * NULL, because native happily returns the SIDs and ACLs that are requested
3189 * in this case.
3192 return ERROR_SUCCESS;
3195 /******************************************************************************
3196 * GetSecurityInfoExA [ADVAPI32.@]
3198 DWORD WINAPI GetSecurityInfoExA(
3199 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3200 SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
3201 LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
3202 PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
3205 FIXME("stub!\n");
3206 return ERROR_BAD_PROVIDER;
3209 /******************************************************************************
3210 * GetSecurityInfoExW [ADVAPI32.@]
3212 DWORD WINAPI GetSecurityInfoExW(
3213 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3214 SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
3215 LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList,
3216 PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
3219 FIXME("stub!\n");
3220 return ERROR_BAD_PROVIDER;
3223 /******************************************************************************
3224 * BuildExplicitAccessWithNameA [ADVAPI32.@]
3226 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
3227 LPSTR pTrusteeName, DWORD AccessPermissions,
3228 ACCESS_MODE AccessMode, DWORD Inheritance )
3230 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_a(pTrusteeName),
3231 AccessPermissions, AccessMode, Inheritance);
3233 pExplicitAccess->grfAccessPermissions = AccessPermissions;
3234 pExplicitAccess->grfAccessMode = AccessMode;
3235 pExplicitAccess->grfInheritance = Inheritance;
3237 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3238 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3239 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3240 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3241 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3244 /******************************************************************************
3245 * BuildExplicitAccessWithNameW [ADVAPI32.@]
3247 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
3248 LPWSTR pTrusteeName, DWORD AccessPermissions,
3249 ACCESS_MODE AccessMode, DWORD Inheritance )
3251 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_w(pTrusteeName),
3252 AccessPermissions, AccessMode, Inheritance);
3254 pExplicitAccess->grfAccessPermissions = AccessPermissions;
3255 pExplicitAccess->grfAccessMode = AccessMode;
3256 pExplicitAccess->grfInheritance = Inheritance;
3258 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3259 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3260 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3261 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3262 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3265 /******************************************************************************
3266 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
3268 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
3269 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
3270 LPSTR InheritedObjectTypeName, LPSTR Name )
3272 DWORD ObjectsPresent = 0;
3274 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3275 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
3277 /* Fill the OBJECTS_AND_NAME structure */
3278 pObjName->ObjectType = ObjectType;
3279 if (ObjectTypeName != NULL)
3281 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3284 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3285 if (InheritedObjectTypeName != NULL)
3287 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3290 pObjName->ObjectsPresent = ObjectsPresent;
3291 pObjName->ptstrName = Name;
3293 /* Fill the TRUSTEE structure */
3294 pTrustee->pMultipleTrustee = NULL;
3295 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3296 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3297 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3298 pTrustee->ptstrName = (LPSTR)pObjName;
3301 /******************************************************************************
3302 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
3304 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
3305 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
3306 LPWSTR InheritedObjectTypeName, LPWSTR Name )
3308 DWORD ObjectsPresent = 0;
3310 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3311 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
3313 /* Fill the OBJECTS_AND_NAME structure */
3314 pObjName->ObjectType = ObjectType;
3315 if (ObjectTypeName != NULL)
3317 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3320 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3321 if (InheritedObjectTypeName != NULL)
3323 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3326 pObjName->ObjectsPresent = ObjectsPresent;
3327 pObjName->ptstrName = Name;
3329 /* Fill the TRUSTEE structure */
3330 pTrustee->pMultipleTrustee = NULL;
3331 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3332 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3333 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3334 pTrustee->ptstrName = (LPWSTR)pObjName;
3337 /******************************************************************************
3338 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
3340 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
3341 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3343 DWORD ObjectsPresent = 0;
3345 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3347 /* Fill the OBJECTS_AND_SID structure */
3348 if (pObjectGuid != NULL)
3350 pObjSid->ObjectTypeGuid = *pObjectGuid;
3351 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3353 else
3355 ZeroMemory(&pObjSid->ObjectTypeGuid,
3356 sizeof(GUID));
3359 if (pInheritedObjectGuid != NULL)
3361 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3362 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3364 else
3366 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3367 sizeof(GUID));
3370 pObjSid->ObjectsPresent = ObjectsPresent;
3371 pObjSid->pSid = pSid;
3373 /* Fill the TRUSTEE structure */
3374 pTrustee->pMultipleTrustee = NULL;
3375 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3376 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3377 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3378 pTrustee->ptstrName = (LPSTR) pObjSid;
3381 /******************************************************************************
3382 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
3384 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
3385 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3387 DWORD ObjectsPresent = 0;
3389 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3391 /* Fill the OBJECTS_AND_SID structure */
3392 if (pObjectGuid != NULL)
3394 pObjSid->ObjectTypeGuid = *pObjectGuid;
3395 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3397 else
3399 ZeroMemory(&pObjSid->ObjectTypeGuid,
3400 sizeof(GUID));
3403 if (pInheritedObjectGuid != NULL)
3405 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3406 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3408 else
3410 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3411 sizeof(GUID));
3414 pObjSid->ObjectsPresent = ObjectsPresent;
3415 pObjSid->pSid = pSid;
3417 /* Fill the TRUSTEE structure */
3418 pTrustee->pMultipleTrustee = NULL;
3419 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3420 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3421 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3422 pTrustee->ptstrName = (LPWSTR) pObjSid;
3425 /******************************************************************************
3426 * BuildTrusteeWithSidA [ADVAPI32.@]
3428 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid)
3430 TRACE("%p %p\n", pTrustee, pSid);
3432 pTrustee->pMultipleTrustee = NULL;
3433 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3434 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3435 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3436 pTrustee->ptstrName = pSid;
3439 /******************************************************************************
3440 * BuildTrusteeWithSidW [ADVAPI32.@]
3442 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
3444 TRACE("%p %p\n", pTrustee, pSid);
3446 pTrustee->pMultipleTrustee = NULL;
3447 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3448 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3449 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3450 pTrustee->ptstrName = pSid;
3453 /******************************************************************************
3454 * BuildTrusteeWithNameA [ADVAPI32.@]
3456 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
3458 TRACE("%p %s\n", pTrustee, debugstr_a(name) );
3460 pTrustee->pMultipleTrustee = NULL;
3461 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3462 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3463 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3464 pTrustee->ptstrName = name;
3467 /******************************************************************************
3468 * BuildTrusteeWithNameW [ADVAPI32.@]
3470 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
3472 TRACE("%p %s\n", pTrustee, debugstr_w(name) );
3474 pTrustee->pMultipleTrustee = NULL;
3475 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3476 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3477 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3478 pTrustee->ptstrName = name;
3481 /******************************************************************************
3482 * GetTrusteeFormA [ADVAPI32.@]
3484 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee)
3486 TRACE("(%p)\n", pTrustee);
3488 if (!pTrustee)
3489 return TRUSTEE_BAD_FORM;
3491 return pTrustee->TrusteeForm;
3494 /******************************************************************************
3495 * GetTrusteeFormW [ADVAPI32.@]
3497 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee)
3499 TRACE("(%p)\n", pTrustee);
3501 if (!pTrustee)
3502 return TRUSTEE_BAD_FORM;
3504 return pTrustee->TrusteeForm;
3507 /******************************************************************************
3508 * GetTrusteeNameA [ADVAPI32.@]
3510 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee)
3512 TRACE("(%p)\n", pTrustee);
3514 if (!pTrustee)
3515 return NULL;
3517 return pTrustee->ptstrName;
3520 /******************************************************************************
3521 * GetTrusteeNameW [ADVAPI32.@]
3523 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee)
3525 TRACE("(%p)\n", pTrustee);
3527 if (!pTrustee)
3528 return NULL;
3530 return pTrustee->ptstrName;
3533 /******************************************************************************
3534 * GetTrusteeTypeA [ADVAPI32.@]
3536 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee)
3538 TRACE("(%p)\n", pTrustee);
3540 if (!pTrustee)
3541 return TRUSTEE_IS_UNKNOWN;
3543 return pTrustee->TrusteeType;
3546 /******************************************************************************
3547 * GetTrusteeTypeW [ADVAPI32.@]
3549 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee)
3551 TRACE("(%p)\n", pTrustee);
3553 if (!pTrustee)
3554 return TRUSTEE_IS_UNKNOWN;
3556 return pTrustee->TrusteeType;
3559 BOOL WINAPI SetAclInformation( PACL pAcl, LPVOID pAclInformation,
3560 DWORD nAclInformationLength,
3561 ACL_INFORMATION_CLASS dwAclInformationClass )
3563 FIXME("%p %p 0x%08x 0x%08x - stub\n", pAcl, pAclInformation,
3564 nAclInformationLength, dwAclInformationClass);
3566 return TRUE;
3569 static DWORD trustee_name_A_to_W(TRUSTEE_FORM form, char *trustee_nameA, WCHAR **ptrustee_nameW)
3571 switch (form)
3573 case TRUSTEE_IS_NAME:
3575 *ptrustee_nameW = SERV_dup(trustee_nameA);
3576 return ERROR_SUCCESS;
3578 case TRUSTEE_IS_OBJECTS_AND_NAME:
3580 OBJECTS_AND_NAME_A *objA = (OBJECTS_AND_NAME_A *)trustee_nameA;
3581 OBJECTS_AND_NAME_W *objW = NULL;
3583 if (objA)
3585 if (!(objW = heap_alloc( sizeof(OBJECTS_AND_NAME_W) )))
3586 return ERROR_NOT_ENOUGH_MEMORY;
3588 objW->ObjectsPresent = objA->ObjectsPresent;
3589 objW->ObjectType = objA->ObjectType;
3590 objW->ObjectTypeName = SERV_dup(objA->ObjectTypeName);
3591 objW->InheritedObjectTypeName = SERV_dup(objA->InheritedObjectTypeName);
3592 objW->ptstrName = SERV_dup(objA->ptstrName);
3595 *ptrustee_nameW = (WCHAR *)objW;
3596 return ERROR_SUCCESS;
3598 /* These forms do not require conversion. */
3599 case TRUSTEE_IS_SID:
3600 case TRUSTEE_IS_OBJECTS_AND_SID:
3601 *ptrustee_nameW = (WCHAR *)trustee_nameA;
3602 return ERROR_SUCCESS;
3603 default:
3604 return ERROR_INVALID_PARAMETER;
3608 static void free_trustee_name(TRUSTEE_FORM form, WCHAR *trustee_nameW)
3610 switch (form)
3612 case TRUSTEE_IS_NAME:
3613 heap_free( trustee_nameW );
3614 break;
3615 case TRUSTEE_IS_OBJECTS_AND_NAME:
3617 OBJECTS_AND_NAME_W *objW = (OBJECTS_AND_NAME_W *)trustee_nameW;
3619 if (objW)
3621 heap_free( objW->ptstrName );
3622 heap_free( objW->InheritedObjectTypeName );
3623 heap_free( objW->ObjectTypeName );
3624 heap_free( objW );
3627 break;
3629 /* Other forms did not require allocation, so no freeing is necessary. */
3630 default:
3631 break;
3635 /******************************************************************************
3636 * SetEntriesInAclA [ADVAPI32.@]
3638 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
3639 PACL OldAcl, PACL* NewAcl )
3641 DWORD err = ERROR_SUCCESS;
3642 EXPLICIT_ACCESSW *pEntriesW;
3643 UINT alloc_index, free_index;
3645 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3647 if (NewAcl)
3648 *NewAcl = NULL;
3650 if (!count && !OldAcl)
3651 return ERROR_SUCCESS;
3653 pEntriesW = heap_alloc( count * sizeof(EXPLICIT_ACCESSW) );
3654 if (!pEntriesW)
3655 return ERROR_NOT_ENOUGH_MEMORY;
3657 for (alloc_index = 0; alloc_index < count; ++alloc_index)
3659 pEntriesW[alloc_index].grfAccessPermissions = pEntries[alloc_index].grfAccessPermissions;
3660 pEntriesW[alloc_index].grfAccessMode = pEntries[alloc_index].grfAccessMode;
3661 pEntriesW[alloc_index].grfInheritance = pEntries[alloc_index].grfInheritance;
3662 pEntriesW[alloc_index].Trustee.pMultipleTrustee = NULL; /* currently not supported */
3663 pEntriesW[alloc_index].Trustee.MultipleTrusteeOperation = pEntries[alloc_index].Trustee.MultipleTrusteeOperation;
3664 pEntriesW[alloc_index].Trustee.TrusteeForm = pEntries[alloc_index].Trustee.TrusteeForm;
3665 pEntriesW[alloc_index].Trustee.TrusteeType = pEntries[alloc_index].Trustee.TrusteeType;
3667 err = trustee_name_A_to_W( pEntries[alloc_index].Trustee.TrusteeForm,
3668 pEntries[alloc_index].Trustee.ptstrName,
3669 &pEntriesW[alloc_index].Trustee.ptstrName );
3670 if (err != ERROR_SUCCESS)
3672 if (err == ERROR_INVALID_PARAMETER)
3673 WARN("bad trustee form %d for trustee %d\n",
3674 pEntries[alloc_index].Trustee.TrusteeForm, alloc_index);
3676 goto cleanup;
3680 err = SetEntriesInAclW( count, pEntriesW, OldAcl, NewAcl );
3682 cleanup:
3683 /* Free any previously allocated trustee name buffers, taking into account
3684 * a possible out-of-memory condition while building the EXPLICIT_ACCESSW
3685 * list. */
3686 for (free_index = 0; free_index < alloc_index; ++free_index)
3687 free_trustee_name( pEntriesW[free_index].Trustee.TrusteeForm, pEntriesW[free_index].Trustee.ptstrName );
3689 heap_free( pEntriesW );
3690 return err;
3693 /******************************************************************************
3694 * SetEntriesInAclW [ADVAPI32.@]
3696 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
3697 PACL OldAcl, PACL* NewAcl )
3699 ULONG i;
3700 PSID *ppsid;
3701 DWORD ret = ERROR_SUCCESS;
3702 DWORD acl_size = sizeof(ACL);
3703 NTSTATUS status;
3705 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3707 if (NewAcl)
3708 *NewAcl = NULL;
3710 if (!count && !OldAcl)
3711 return ERROR_SUCCESS;
3713 /* allocate array of maximum sized sids allowed */
3714 ppsid = heap_alloc(count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
3715 if (!ppsid)
3716 return ERROR_OUTOFMEMORY;
3718 for (i = 0; i < count; i++)
3720 ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3722 TRACE("[%d]:\n\tgrfAccessPermissions = 0x%x\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%x\n\t"
3723 "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
3724 "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
3725 pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
3726 pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
3727 pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
3728 pEntries[i].Trustee.ptstrName);
3730 if (pEntries[i].Trustee.MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
3732 WARN("bad multiple trustee operation %d for trustee %d\n", pEntries[i].Trustee.MultipleTrusteeOperation, i);
3733 ret = ERROR_INVALID_PARAMETER;
3734 goto exit;
3737 switch (pEntries[i].Trustee.TrusteeForm)
3739 case TRUSTEE_IS_SID:
3740 if (!CopySid(FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]),
3741 ppsid[i], pEntries[i].Trustee.ptstrName))
3743 WARN("bad sid %p for trustee %d\n", pEntries[i].Trustee.ptstrName, i);
3744 ret = ERROR_INVALID_PARAMETER;
3745 goto exit;
3747 break;
3748 case TRUSTEE_IS_NAME:
3750 DWORD sid_size = FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3751 DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
3752 SID_NAME_USE use;
3753 if (!strcmpW( pEntries[i].Trustee.ptstrName, CURRENT_USER ))
3755 if (!lookup_user_account_name( ppsid[i], &sid_size, NULL, &domain_size, &use ))
3757 ret = GetLastError();
3758 goto exit;
3761 else if (!LookupAccountNameW(NULL, pEntries[i].Trustee.ptstrName, ppsid[i], &sid_size, NULL, &domain_size, &use))
3763 WARN("bad user name %s for trustee %d\n", debugstr_w(pEntries[i].Trustee.ptstrName), i);
3764 ret = ERROR_INVALID_PARAMETER;
3765 goto exit;
3767 break;
3769 case TRUSTEE_IS_OBJECTS_AND_SID:
3770 FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
3771 break;
3772 case TRUSTEE_IS_OBJECTS_AND_NAME:
3773 FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
3774 break;
3775 default:
3776 WARN("bad trustee form %d for trustee %d\n", pEntries[i].Trustee.TrusteeForm, i);
3777 ret = ERROR_INVALID_PARAMETER;
3778 goto exit;
3781 /* Note: we overestimate the ACL size here as a tradeoff between
3782 * instructions (simplicity) and memory */
3783 switch (pEntries[i].grfAccessMode)
3785 case GRANT_ACCESS:
3786 case SET_ACCESS:
3787 acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3788 break;
3789 case DENY_ACCESS:
3790 acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3791 break;
3792 case SET_AUDIT_SUCCESS:
3793 case SET_AUDIT_FAILURE:
3794 acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
3795 break;
3796 case REVOKE_ACCESS:
3797 break;
3798 default:
3799 WARN("bad access mode %d for trustee %d\n", pEntries[i].grfAccessMode, i);
3800 ret = ERROR_INVALID_PARAMETER;
3801 goto exit;
3805 if (OldAcl)
3807 ACL_SIZE_INFORMATION size_info;
3809 status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
3810 if (status != STATUS_SUCCESS)
3812 ret = RtlNtStatusToDosError(status);
3813 goto exit;
3815 acl_size += size_info.AclBytesInUse - sizeof(ACL);
3818 *NewAcl = LocalAlloc(0, acl_size);
3819 if (!*NewAcl)
3821 ret = ERROR_OUTOFMEMORY;
3822 goto exit;
3825 status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
3826 if (status != STATUS_SUCCESS)
3828 ret = RtlNtStatusToDosError(status);
3829 goto exit;
3832 for (i = 0; i < count; i++)
3834 switch (pEntries[i].grfAccessMode)
3836 case GRANT_ACCESS:
3837 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3838 pEntries[i].grfInheritance,
3839 pEntries[i].grfAccessPermissions,
3840 ppsid[i]);
3841 break;
3842 case SET_ACCESS:
3844 ULONG j;
3845 BOOL add = TRUE;
3846 if (OldAcl)
3848 for (j = 0; ; j++)
3850 const ACE_HEADER *existing_ace_header;
3851 status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
3852 if (status != STATUS_SUCCESS)
3853 break;
3854 if (pEntries[i].grfAccessMode == SET_ACCESS &&
3855 existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3856 EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
3858 add = FALSE;
3859 break;
3863 if (add)
3864 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3865 pEntries[i].grfInheritance,
3866 pEntries[i].grfAccessPermissions,
3867 ppsid[i]);
3868 break;
3870 case DENY_ACCESS:
3871 status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
3872 pEntries[i].grfInheritance,
3873 pEntries[i].grfAccessPermissions,
3874 ppsid[i]);
3875 break;
3876 case SET_AUDIT_SUCCESS:
3877 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3878 pEntries[i].grfInheritance,
3879 pEntries[i].grfAccessPermissions,
3880 ppsid[i], TRUE, FALSE);
3881 break;
3882 case SET_AUDIT_FAILURE:
3883 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3884 pEntries[i].grfInheritance,
3885 pEntries[i].grfAccessPermissions,
3886 ppsid[i], FALSE, TRUE);
3887 break;
3888 default:
3889 FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
3893 if (OldAcl)
3895 for (i = 0; ; i++)
3897 BOOL add = TRUE;
3898 ULONG j;
3899 const ACE_HEADER *old_ace_header;
3900 status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
3901 if (status != STATUS_SUCCESS) break;
3902 for (j = 0; j < count; j++)
3904 if (pEntries[j].grfAccessMode == SET_ACCESS &&
3905 old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3906 EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3908 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
3909 add = FALSE;
3910 break;
3912 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
3914 switch (old_ace_header->AceType)
3916 case ACCESS_ALLOWED_ACE_TYPE:
3917 if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3918 add = FALSE;
3919 break;
3920 case ACCESS_DENIED_ACE_TYPE:
3921 if (EqualSid(ppsid[j], &((ACCESS_DENIED_ACE *)old_ace_header)->SidStart))
3922 add = FALSE;
3923 break;
3924 case SYSTEM_AUDIT_ACE_TYPE:
3925 if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
3926 add = FALSE;
3927 break;
3928 case SYSTEM_ALARM_ACE_TYPE:
3929 if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
3930 add = FALSE;
3931 break;
3932 default:
3933 FIXME("unhandled ace type %d\n", old_ace_header->AceType);
3936 if (!add)
3937 break;
3940 if (add)
3941 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
3942 if (status != STATUS_SUCCESS)
3944 WARN("RtlAddAce failed with error 0x%08x\n", status);
3945 ret = RtlNtStatusToDosError(status);
3946 break;
3951 exit:
3952 heap_free(ppsid);
3953 return ret;
3956 /******************************************************************************
3957 * SetNamedSecurityInfoA [ADVAPI32.@]
3959 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
3960 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
3961 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
3963 LPWSTR wstr;
3964 DWORD r;
3966 TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
3967 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
3969 wstr = SERV_dup(pObjectName);
3970 r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
3971 psidGroup, pDacl, pSacl );
3973 heap_free( wstr );
3975 return r;
3978 BOOL WINAPI SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation,
3979 PSECURITY_DESCRIPTOR ModificationDescriptor,
3980 PSECURITY_DESCRIPTOR* ObjectsSecurityDescriptor,
3981 PGENERIC_MAPPING GenericMapping,
3982 HANDLE Token )
3984 FIXME("0x%08x %p %p %p %p - stub\n", SecurityInformation, ModificationDescriptor,
3985 ObjectsSecurityDescriptor, GenericMapping, Token);
3987 return TRUE;
3990 BOOL WINAPI AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
3992 return RtlAreAllAccessesGranted( GrantedAccess, DesiredAccess );
3995 /******************************************************************************
3996 * AreAnyAccessesGranted [ADVAPI32.@]
3998 * Determines whether or not any of a set of specified access permissions have
3999 * been granted or not.
4001 * PARAMS
4002 * GrantedAccess [I] The permissions that have been granted.
4003 * DesiredAccess [I] The permissions that you want to have.
4005 * RETURNS
4006 * Nonzero if any of the permissions have been granted, zero if none of the
4007 * permissions have been granted.
4010 BOOL WINAPI AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
4012 return RtlAreAnyAccessesGranted( GrantedAccess, DesiredAccess );
4015 /******************************************************************************
4016 * SetNamedSecurityInfoW [ADVAPI32.@]
4018 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
4019 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
4020 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
4022 DWORD access = 0;
4023 HANDLE handle;
4024 DWORD err;
4026 TRACE( "%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
4027 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
4029 if (!pObjectName) return ERROR_INVALID_PARAMETER;
4031 if (SecurityInfo & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION))
4032 access |= WRITE_OWNER;
4033 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4034 access |= WRITE_DAC;
4035 if (SecurityInfo & SACL_SECURITY_INFORMATION)
4036 access |= ACCESS_SYSTEM_SECURITY;
4038 switch (ObjectType)
4040 case SE_SERVICE:
4041 if (!(err = get_security_service( pObjectName, access, &handle )))
4043 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4044 CloseServiceHandle( handle );
4046 break;
4047 case SE_REGISTRY_KEY:
4048 if (!(err = get_security_regkey( pObjectName, access, &handle )))
4050 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4051 RegCloseKey( handle );
4053 break;
4054 case SE_FILE_OBJECT:
4055 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4056 access |= READ_CONTROL;
4057 if (!(err = get_security_file( pObjectName, access, &handle )))
4059 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4060 CloseHandle( handle );
4062 break;
4063 default:
4064 FIXME( "Object type %d is not currently supported.\n", ObjectType );
4065 return ERROR_SUCCESS;
4067 return err;
4070 /******************************************************************************
4071 * GetExplicitEntriesFromAclA [ADVAPI32.@]
4073 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
4074 PEXPLICIT_ACCESSA* pListOfExplicitEntries)
4076 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
4077 return ERROR_CALL_NOT_IMPLEMENTED;
4080 /******************************************************************************
4081 * GetExplicitEntriesFromAclW [ADVAPI32.@]
4083 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
4084 PEXPLICIT_ACCESSW* pListOfExplicitEntries)
4086 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
4087 return ERROR_CALL_NOT_IMPLEMENTED;
4090 /******************************************************************************
4091 * GetAuditedPermissionsFromAclA [ADVAPI32.@]
4093 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
4094 PACCESS_MASK pFailedAuditRights)
4096 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
4097 return ERROR_CALL_NOT_IMPLEMENTED;
4101 /******************************************************************************
4102 * GetAuditedPermissionsFromAclW [ADVAPI32.@]
4104 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
4105 PACCESS_MASK pFailedAuditRights)
4107 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
4108 return ERROR_CALL_NOT_IMPLEMENTED;
4112 /******************************************************************************
4113 * ParseAclStringFlags
4115 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
4117 DWORD flags = 0;
4118 LPCWSTR szAcl = *StringAcl;
4120 while (*szAcl != '(')
4122 if (*szAcl == 'P')
4124 flags |= SE_DACL_PROTECTED;
4126 else if (*szAcl == 'A')
4128 szAcl++;
4129 if (*szAcl == 'R')
4130 flags |= SE_DACL_AUTO_INHERIT_REQ;
4131 else if (*szAcl == 'I')
4132 flags |= SE_DACL_AUTO_INHERITED;
4134 szAcl++;
4137 *StringAcl = szAcl;
4138 return flags;
4141 /******************************************************************************
4142 * ParseAceStringType
4144 static const ACEFLAG AceType[] =
4146 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
4147 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
4148 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
4149 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
4151 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
4152 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
4153 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
4154 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
4156 { NULL, 0 },
4159 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
4161 UINT len = 0;
4162 LPCWSTR szAcl = *StringAcl;
4163 const ACEFLAG *lpaf = AceType;
4165 while (*szAcl == ' ')
4166 szAcl++;
4168 while (lpaf->wstr &&
4169 (len = strlenW(lpaf->wstr)) &&
4170 strncmpW(lpaf->wstr, szAcl, len))
4171 lpaf++;
4173 if (!lpaf->wstr)
4174 return 0;
4176 *StringAcl = szAcl + len;
4177 return lpaf->value;
4181 /******************************************************************************
4182 * ParseAceStringFlags
4184 static const ACEFLAG AceFlags[] =
4186 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
4187 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
4188 { SDDL_INHERITED, INHERITED_ACE },
4189 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
4190 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
4191 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
4192 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
4193 { NULL, 0 },
4196 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
4198 UINT len = 0;
4199 BYTE flags = 0;
4200 LPCWSTR szAcl = *StringAcl;
4202 while (*szAcl == ' ')
4203 szAcl++;
4205 while (*szAcl != ';')
4207 const ACEFLAG *lpaf = AceFlags;
4209 while (lpaf->wstr &&
4210 (len = strlenW(lpaf->wstr)) &&
4211 strncmpW(lpaf->wstr, szAcl, len))
4212 lpaf++;
4214 if (!lpaf->wstr)
4215 return 0;
4217 flags |= lpaf->value;
4218 szAcl += len;
4221 *StringAcl = szAcl;
4222 return flags;
4226 /******************************************************************************
4227 * ParseAceStringRights
4229 static const ACEFLAG AceRights[] =
4231 { SDDL_GENERIC_ALL, GENERIC_ALL },
4232 { SDDL_GENERIC_READ, GENERIC_READ },
4233 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
4234 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
4236 { SDDL_READ_CONTROL, READ_CONTROL },
4237 { SDDL_STANDARD_DELETE, DELETE },
4238 { SDDL_WRITE_DAC, WRITE_DAC },
4239 { SDDL_WRITE_OWNER, WRITE_OWNER },
4241 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
4242 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
4243 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
4244 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
4245 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
4246 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
4247 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
4248 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
4249 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
4251 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
4252 { SDDL_FILE_READ, FILE_GENERIC_READ },
4253 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
4254 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
4256 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
4257 { SDDL_KEY_READ, KEY_READ },
4258 { SDDL_KEY_WRITE, KEY_WRITE },
4259 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
4260 { NULL, 0 },
4263 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
4265 UINT len = 0;
4266 DWORD rights = 0;
4267 LPCWSTR szAcl = *StringAcl;
4269 while (*szAcl == ' ')
4270 szAcl++;
4272 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
4274 LPCWSTR p = szAcl;
4276 while (*p && *p != ';')
4277 p++;
4279 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
4281 rights = strtoulW(szAcl, NULL, 16);
4282 szAcl = p;
4284 else
4285 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
4287 else
4289 while (*szAcl != ';')
4291 const ACEFLAG *lpaf = AceRights;
4293 while (lpaf->wstr &&
4294 (len = strlenW(lpaf->wstr)) &&
4295 strncmpW(lpaf->wstr, szAcl, len))
4297 lpaf++;
4300 if (!lpaf->wstr)
4301 return 0;
4303 rights |= lpaf->value;
4304 szAcl += len;
4308 *StringAcl = szAcl;
4309 return rights;
4313 /******************************************************************************
4314 * ParseStringAclToAcl
4316 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
4318 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
4319 PACL pAcl, LPDWORD cBytes)
4321 DWORD val;
4322 DWORD sidlen;
4323 DWORD length = sizeof(ACL);
4324 DWORD acesize = 0;
4325 DWORD acecount = 0;
4326 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
4327 DWORD error = ERROR_INVALID_ACL;
4329 TRACE("%s\n", debugstr_w(StringAcl));
4331 if (!StringAcl)
4332 return FALSE;
4334 if (pAcl) /* pAce is only useful if we're setting values */
4335 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
4337 /* Parse ACL flags */
4338 *lpdwFlags = ParseAclStringFlags(&StringAcl);
4340 /* Parse ACE */
4341 while (*StringAcl == '(')
4343 StringAcl++;
4345 /* Parse ACE type */
4346 val = ParseAceStringType(&StringAcl);
4347 if (pAce)
4348 pAce->Header.AceType = (BYTE) val;
4349 if (*StringAcl != ';')
4351 error = RPC_S_INVALID_STRING_UUID;
4352 goto lerr;
4354 StringAcl++;
4356 /* Parse ACE flags */
4357 val = ParseAceStringFlags(&StringAcl);
4358 if (pAce)
4359 pAce->Header.AceFlags = (BYTE) val;
4360 if (*StringAcl != ';')
4361 goto lerr;
4362 StringAcl++;
4364 /* Parse ACE rights */
4365 val = ParseAceStringRights(&StringAcl);
4366 if (pAce)
4367 pAce->Mask = val;
4368 if (*StringAcl != ';')
4369 goto lerr;
4370 StringAcl++;
4372 /* Parse ACE object guid */
4373 while (*StringAcl == ' ')
4374 StringAcl++;
4375 if (*StringAcl != ';')
4377 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4378 goto lerr;
4380 StringAcl++;
4382 /* Parse ACE inherit object guid */
4383 while (*StringAcl == ' ')
4384 StringAcl++;
4385 if (*StringAcl != ';')
4387 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4388 goto lerr;
4390 StringAcl++;
4392 /* Parse ACE account sid */
4393 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
4395 while (*StringAcl && *StringAcl != ')')
4396 StringAcl++;
4399 if (*StringAcl != ')')
4400 goto lerr;
4401 StringAcl++;
4403 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
4404 length += acesize;
4405 if (pAce)
4407 pAce->Header.AceSize = acesize;
4408 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
4410 acecount++;
4413 *cBytes = length;
4415 if (length > 0xffff)
4417 ERR("ACL too large\n");
4418 goto lerr;
4421 if (pAcl)
4423 pAcl->AclRevision = ACL_REVISION;
4424 pAcl->Sbz1 = 0;
4425 pAcl->AclSize = length;
4426 pAcl->AceCount = acecount++;
4427 pAcl->Sbz2 = 0;
4429 return TRUE;
4431 lerr:
4432 SetLastError(error);
4433 WARN("Invalid ACE string format\n");
4434 return FALSE;
4438 /******************************************************************************
4439 * ParseStringSecurityDescriptorToSecurityDescriptor
4441 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
4442 LPCWSTR StringSecurityDescriptor,
4443 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
4444 LPDWORD cBytes)
4446 BOOL bret = FALSE;
4447 WCHAR toktype;
4448 WCHAR tok[MAX_PATH];
4449 LPCWSTR lptoken;
4450 LPBYTE lpNext = NULL;
4451 DWORD len;
4453 *cBytes = sizeof(SECURITY_DESCRIPTOR);
4455 if (SecurityDescriptor)
4456 lpNext = (LPBYTE)(SecurityDescriptor + 1);
4458 while (*StringSecurityDescriptor == ' ')
4459 StringSecurityDescriptor++;
4461 while (*StringSecurityDescriptor)
4463 toktype = *StringSecurityDescriptor;
4465 /* Expect char identifier followed by ':' */
4466 StringSecurityDescriptor++;
4467 if (*StringSecurityDescriptor != ':')
4469 SetLastError(ERROR_INVALID_PARAMETER);
4470 goto lend;
4472 StringSecurityDescriptor++;
4474 /* Extract token */
4475 lptoken = StringSecurityDescriptor;
4476 while (*lptoken && *lptoken != ':')
4477 lptoken++;
4479 if (*lptoken)
4480 lptoken--;
4482 len = lptoken - StringSecurityDescriptor;
4483 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
4484 tok[len] = 0;
4486 switch (toktype)
4488 case 'O':
4490 DWORD bytes;
4492 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4493 goto lend;
4495 if (SecurityDescriptor)
4497 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
4498 lpNext += bytes; /* Advance to next token */
4501 *cBytes += bytes;
4503 break;
4506 case 'G':
4508 DWORD bytes;
4510 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4511 goto lend;
4513 if (SecurityDescriptor)
4515 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
4516 lpNext += bytes; /* Advance to next token */
4519 *cBytes += bytes;
4521 break;
4524 case 'D':
4526 DWORD flags;
4527 DWORD bytes;
4529 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4530 goto lend;
4532 if (SecurityDescriptor)
4534 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
4535 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
4536 lpNext += bytes; /* Advance to next token */
4539 *cBytes += bytes;
4541 break;
4544 case 'S':
4546 DWORD flags;
4547 DWORD bytes;
4549 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4550 goto lend;
4552 if (SecurityDescriptor)
4554 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
4555 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
4556 lpNext += bytes; /* Advance to next token */
4559 *cBytes += bytes;
4561 break;
4564 default:
4565 FIXME("Unknown token\n");
4566 SetLastError(ERROR_INVALID_PARAMETER);
4567 goto lend;
4570 StringSecurityDescriptor = lptoken;
4573 bret = TRUE;
4575 lend:
4576 return bret;
4579 /******************************************************************************
4580 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
4582 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
4583 LPCSTR StringSecurityDescriptor,
4584 DWORD StringSDRevision,
4585 PSECURITY_DESCRIPTOR* SecurityDescriptor,
4586 PULONG SecurityDescriptorSize)
4588 BOOL ret;
4589 LPWSTR StringSecurityDescriptorW;
4591 if(!StringSecurityDescriptor)
4592 return FALSE;
4594 StringSecurityDescriptorW = SERV_dup(StringSecurityDescriptor);
4595 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
4596 StringSDRevision, SecurityDescriptor,
4597 SecurityDescriptorSize);
4598 heap_free(StringSecurityDescriptorW);
4600 return ret;
4603 /******************************************************************************
4604 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
4606 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
4607 LPCWSTR StringSecurityDescriptor,
4608 DWORD StringSDRevision,
4609 PSECURITY_DESCRIPTOR* SecurityDescriptor,
4610 PULONG SecurityDescriptorSize)
4612 DWORD cBytes;
4613 SECURITY_DESCRIPTOR* psd;
4614 BOOL bret = FALSE;
4616 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
4618 if (GetVersion() & 0x80000000)
4620 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4621 goto lend;
4623 else if (!StringSecurityDescriptor || !SecurityDescriptor)
4625 SetLastError(ERROR_INVALID_PARAMETER);
4626 goto lend;
4628 else if (StringSDRevision != SID_REVISION)
4630 SetLastError(ERROR_UNKNOWN_REVISION);
4631 goto lend;
4634 /* Compute security descriptor length */
4635 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4636 NULL, &cBytes))
4637 goto lend;
4639 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
4640 if (!psd) goto lend;
4642 psd->Revision = SID_REVISION;
4643 psd->Control |= SE_SELF_RELATIVE;
4645 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4646 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
4648 LocalFree(psd);
4649 goto lend;
4652 if (SecurityDescriptorSize)
4653 *SecurityDescriptorSize = cBytes;
4655 bret = TRUE;
4657 lend:
4658 TRACE(" ret=%d\n", bret);
4659 return bret;
4662 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
4664 if (cch == -1)
4665 cch = strlenW(string);
4667 if (plen)
4668 *plen += cch;
4670 if (pwptr)
4672 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
4673 *pwptr += cch;
4677 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
4679 DWORD i;
4680 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
4681 WCHAR subauthfmt[] = { '-','%','u',0 };
4682 WCHAR buf[26];
4683 SID *pisid = psid;
4685 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
4687 SetLastError(ERROR_INVALID_SID);
4688 return FALSE;
4691 if (pisid->IdentifierAuthority.Value[0] ||
4692 pisid->IdentifierAuthority.Value[1])
4694 FIXME("not matching MS' bugs\n");
4695 SetLastError(ERROR_INVALID_SID);
4696 return FALSE;
4699 sprintfW( buf, fmt, pisid->Revision,
4700 MAKELONG(
4701 MAKEWORD( pisid->IdentifierAuthority.Value[5],
4702 pisid->IdentifierAuthority.Value[4] ),
4703 MAKEWORD( pisid->IdentifierAuthority.Value[3],
4704 pisid->IdentifierAuthority.Value[2] )
4705 ) );
4706 DumpString(buf, -1, pwptr, plen);
4708 for( i=0; i<pisid->SubAuthorityCount; i++ )
4710 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
4711 DumpString(buf, -1, pwptr, plen);
4713 return TRUE;
4716 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
4718 size_t i;
4719 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
4721 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
4723 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
4724 return TRUE;
4728 return DumpSidNumeric(psid, pwptr, plen);
4731 static const LPCWSTR AceRightBitNames[32] = {
4732 SDDL_CREATE_CHILD, /* 0 */
4733 SDDL_DELETE_CHILD,
4734 SDDL_LIST_CHILDREN,
4735 SDDL_SELF_WRITE,
4736 SDDL_READ_PROPERTY, /* 4 */
4737 SDDL_WRITE_PROPERTY,
4738 SDDL_DELETE_TREE,
4739 SDDL_LIST_OBJECT,
4740 SDDL_CONTROL_ACCESS, /* 8 */
4741 NULL,
4742 NULL,
4743 NULL,
4744 NULL, /* 12 */
4745 NULL,
4746 NULL,
4747 NULL,
4748 SDDL_STANDARD_DELETE, /* 16 */
4749 SDDL_READ_CONTROL,
4750 SDDL_WRITE_DAC,
4751 SDDL_WRITE_OWNER,
4752 NULL, /* 20 */
4753 NULL,
4754 NULL,
4755 NULL,
4756 NULL, /* 24 */
4757 NULL,
4758 NULL,
4759 NULL,
4760 SDDL_GENERIC_ALL, /* 28 */
4761 SDDL_GENERIC_EXECUTE,
4762 SDDL_GENERIC_WRITE,
4763 SDDL_GENERIC_READ
4766 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
4768 static const WCHAR fmtW[] = {'0','x','%','x',0};
4769 WCHAR buf[15];
4770 size_t i;
4772 if (mask == 0)
4773 return;
4775 /* first check if the right have name */
4776 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
4778 if (AceRights[i].wstr == NULL)
4779 break;
4780 if (mask == AceRights[i].value)
4782 DumpString(AceRights[i].wstr, -1, pwptr, plen);
4783 return;
4787 /* then check if it can be built from bit names */
4788 for (i = 0; i < 32; i++)
4790 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
4792 /* can't be built from bit names */
4793 sprintfW(buf, fmtW, mask);
4794 DumpString(buf, -1, pwptr, plen);
4795 return;
4799 /* build from bit names */
4800 for (i = 0; i < 32; i++)
4801 if (mask & (1 << i))
4802 DumpString(AceRightBitNames[i], -1, pwptr, plen);
4805 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
4807 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
4808 static const WCHAR openbr = '(';
4809 static const WCHAR closebr = ')';
4810 static const WCHAR semicolon = ';';
4812 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
4814 SetLastError(ERROR_INVALID_ACL);
4815 return FALSE;
4818 piace = pace;
4819 DumpString(&openbr, 1, pwptr, plen);
4820 switch (piace->Header.AceType)
4822 case ACCESS_ALLOWED_ACE_TYPE:
4823 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
4824 break;
4825 case ACCESS_DENIED_ACE_TYPE:
4826 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
4827 break;
4828 case SYSTEM_AUDIT_ACE_TYPE:
4829 DumpString(SDDL_AUDIT, -1, pwptr, plen);
4830 break;
4831 case SYSTEM_ALARM_ACE_TYPE:
4832 DumpString(SDDL_ALARM, -1, pwptr, plen);
4833 break;
4835 DumpString(&semicolon, 1, pwptr, plen);
4837 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
4838 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
4839 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
4840 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
4841 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
4842 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
4843 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
4844 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
4845 if (piace->Header.AceFlags & INHERITED_ACE)
4846 DumpString(SDDL_INHERITED, -1, pwptr, plen);
4847 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
4848 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
4849 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
4850 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
4851 DumpString(&semicolon, 1, pwptr, plen);
4852 DumpRights(piace->Mask, pwptr, plen);
4853 DumpString(&semicolon, 1, pwptr, plen);
4854 /* objects not supported */
4855 DumpString(&semicolon, 1, pwptr, plen);
4856 /* objects not supported */
4857 DumpString(&semicolon, 1, pwptr, plen);
4858 if (!DumpSid(&piace->SidStart, pwptr, plen))
4859 return FALSE;
4860 DumpString(&closebr, 1, pwptr, plen);
4861 return TRUE;
4864 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
4866 WORD count;
4867 UINT i;
4869 if (protected)
4870 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
4871 if (autoInheritReq)
4872 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
4873 if (autoInherited)
4874 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
4876 if (pacl == NULL)
4877 return TRUE;
4879 if (!IsValidAcl(pacl))
4880 return FALSE;
4882 count = pacl->AceCount;
4883 for (i = 0; i < count; i++)
4885 LPVOID ace;
4886 if (!GetAce(pacl, i, &ace))
4887 return FALSE;
4888 if (!DumpAce(ace, pwptr, plen))
4889 return FALSE;
4892 return TRUE;
4895 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4897 static const WCHAR prefix[] = {'O',':',0};
4898 BOOL bDefaulted;
4899 PSID psid;
4901 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
4902 return FALSE;
4904 if (psid == NULL)
4905 return TRUE;
4907 DumpString(prefix, -1, pwptr, plen);
4908 if (!DumpSid(psid, pwptr, plen))
4909 return FALSE;
4910 return TRUE;
4913 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4915 static const WCHAR prefix[] = {'G',':',0};
4916 BOOL bDefaulted;
4917 PSID psid;
4919 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
4920 return FALSE;
4922 if (psid == NULL)
4923 return TRUE;
4925 DumpString(prefix, -1, pwptr, plen);
4926 if (!DumpSid(psid, pwptr, plen))
4927 return FALSE;
4928 return TRUE;
4931 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4933 static const WCHAR dacl[] = {'D',':',0};
4934 SECURITY_DESCRIPTOR_CONTROL control;
4935 BOOL present, defaulted;
4936 DWORD revision;
4937 PACL pacl;
4939 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
4940 return FALSE;
4942 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4943 return FALSE;
4945 if (!present)
4946 return TRUE;
4948 DumpString(dacl, 2, pwptr, plen);
4949 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
4950 return FALSE;
4951 return TRUE;
4954 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4956 static const WCHAR sacl[] = {'S',':',0};
4957 SECURITY_DESCRIPTOR_CONTROL control;
4958 BOOL present, defaulted;
4959 DWORD revision;
4960 PACL pacl;
4962 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
4963 return FALSE;
4965 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4966 return FALSE;
4968 if (!present)
4969 return TRUE;
4971 DumpString(sacl, 2, pwptr, plen);
4972 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
4973 return FALSE;
4974 return TRUE;
4977 /******************************************************************************
4978 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
4980 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
4982 ULONG len;
4983 WCHAR *wptr, *wstr;
4985 if (SDRevision != SDDL_REVISION_1)
4987 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
4988 SetLastError(ERROR_UNKNOWN_REVISION);
4989 return FALSE;
4992 len = 0;
4993 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
4994 if (!DumpOwner(SecurityDescriptor, NULL, &len))
4995 return FALSE;
4996 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
4997 if (!DumpGroup(SecurityDescriptor, NULL, &len))
4998 return FALSE;
4999 if (RequestedInformation & DACL_SECURITY_INFORMATION)
5000 if (!DumpDacl(SecurityDescriptor, NULL, &len))
5001 return FALSE;
5002 if (RequestedInformation & SACL_SECURITY_INFORMATION)
5003 if (!DumpSacl(SecurityDescriptor, NULL, &len))
5004 return FALSE;
5006 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
5007 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
5008 if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) {
5009 LocalFree (wstr);
5010 return FALSE;
5012 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
5013 if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) {
5014 LocalFree (wstr);
5015 return FALSE;
5017 if (RequestedInformation & DACL_SECURITY_INFORMATION)
5018 if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) {
5019 LocalFree (wstr);
5020 return FALSE;
5022 if (RequestedInformation & SACL_SECURITY_INFORMATION)
5023 if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) {
5024 LocalFree (wstr);
5025 return FALSE;
5027 *wptr = 0;
5029 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
5030 *OutputString = wstr;
5031 if (OutputLen)
5032 *OutputLen = strlenW(*OutputString)+1;
5033 return TRUE;
5036 /******************************************************************************
5037 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
5039 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
5041 LPWSTR wstr;
5042 ULONG len;
5043 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
5045 int lenA;
5047 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
5048 *OutputString = heap_alloc(lenA);
5049 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
5050 LocalFree(wstr);
5052 if (OutputLen != NULL)
5053 *OutputLen = lenA;
5054 return TRUE;
5056 else
5058 *OutputString = NULL;
5059 if (OutputLen)
5060 *OutputLen = 0;
5061 return FALSE;
5065 /******************************************************************************
5066 * ConvertStringSidToSidW [ADVAPI32.@]
5068 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
5070 BOOL bret = FALSE;
5071 DWORD cBytes;
5073 TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
5074 if (GetVersion() & 0x80000000)
5075 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5076 else if (!StringSid || !Sid)
5077 SetLastError(ERROR_INVALID_PARAMETER);
5078 else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
5080 PSID pSid = *Sid = LocalAlloc(0, cBytes);
5082 bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
5083 if (!bret)
5084 LocalFree(*Sid);
5086 return bret;
5089 /******************************************************************************
5090 * ConvertStringSidToSidA [ADVAPI32.@]
5092 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
5094 BOOL bret = FALSE;
5096 TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
5097 if (GetVersion() & 0x80000000)
5098 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5099 else if (!StringSid || !Sid)
5100 SetLastError(ERROR_INVALID_PARAMETER);
5101 else
5103 WCHAR *wStringSid = SERV_dup(StringSid);
5104 bret = ConvertStringSidToSidW(wStringSid, Sid);
5105 heap_free(wStringSid);
5107 return bret;
5110 /******************************************************************************
5111 * ConvertSidToStringSidW [ADVAPI32.@]
5113 * format of SID string is:
5114 * S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
5115 * where
5116 * <rev> is the revision of the SID encoded as decimal
5117 * <auth> is the identifier authority encoded as hex
5118 * <subauthN> is the subauthority id encoded as decimal
5120 BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
5122 DWORD len = 0;
5123 LPWSTR wstr, wptr;
5125 TRACE("%p %p\n", pSid, pstr );
5127 len = 0;
5128 if (!DumpSidNumeric(pSid, NULL, &len))
5129 return FALSE;
5130 wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
5131 DumpSidNumeric(pSid, &wptr, NULL);
5132 *wptr = 0;
5134 *pstr = wstr;
5135 return TRUE;
5138 /******************************************************************************
5139 * ConvertSidToStringSidA [ADVAPI32.@]
5141 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
5143 LPWSTR wstr = NULL;
5144 LPSTR str;
5145 UINT len;
5147 TRACE("%p %p\n", pSid, pstr );
5149 if( !ConvertSidToStringSidW( pSid, &wstr ) )
5150 return FALSE;
5152 len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
5153 str = LocalAlloc( 0, len );
5154 WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
5155 LocalFree( wstr );
5157 *pstr = str;
5159 return TRUE;
5162 BOOL WINAPI ConvertToAutoInheritPrivateObjectSecurity(
5163 PSECURITY_DESCRIPTOR pdesc,
5164 PSECURITY_DESCRIPTOR cdesc,
5165 PSECURITY_DESCRIPTOR* ndesc,
5166 GUID* objtype,
5167 BOOL isdir,
5168 PGENERIC_MAPPING genmap )
5170 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
5172 return FALSE;
5175 BOOL WINAPI CreatePrivateObjectSecurity(
5176 PSECURITY_DESCRIPTOR ParentDescriptor,
5177 PSECURITY_DESCRIPTOR CreatorDescriptor,
5178 PSECURITY_DESCRIPTOR* NewDescriptor,
5179 BOOL IsDirectoryObject,
5180 HANDLE Token,
5181 PGENERIC_MAPPING GenericMapping )
5183 SECURITY_DESCRIPTOR_RELATIVE *relative;
5184 DWORD needed, offset;
5185 BYTE *buffer;
5187 FIXME("%p %p %p %d %p %p - returns fake SECURITY_DESCRIPTOR\n", ParentDescriptor,
5188 CreatorDescriptor, NewDescriptor, IsDirectoryObject, Token, GenericMapping);
5190 needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5191 needed += sizeof(sidWorld);
5192 needed += sizeof(sidWorld);
5193 needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5194 needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5196 if (!(buffer = heap_alloc( needed ))) return FALSE;
5197 relative = (SECURITY_DESCRIPTOR_RELATIVE *)buffer;
5198 if (!InitializeSecurityDescriptor( relative, SECURITY_DESCRIPTOR_REVISION ))
5200 heap_free( buffer );
5201 return FALSE;
5203 relative->Control |= SE_SELF_RELATIVE;
5204 offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5206 memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5207 relative->Owner = offset;
5208 offset += sizeof(sidWorld);
5210 memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5211 relative->Group = offset;
5212 offset += sizeof(sidWorld);
5214 GetWorldAccessACL( (ACL *)(buffer + offset) );
5215 relative->Dacl = offset;
5216 offset += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5218 GetWorldAccessACL( (ACL *)(buffer + offset) );
5219 relative->Sacl = offset;
5221 *NewDescriptor = relative;
5222 return TRUE;
5225 BOOL WINAPI DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR* ObjectDescriptor )
5227 FIXME("%p - stub\n", ObjectDescriptor);
5229 heap_free( *ObjectDescriptor );
5230 return TRUE;
5233 BOOL WINAPI CreateProcessAsUserA(
5234 HANDLE hToken,
5235 LPCSTR lpApplicationName,
5236 LPSTR lpCommandLine,
5237 LPSECURITY_ATTRIBUTES lpProcessAttributes,
5238 LPSECURITY_ATTRIBUTES lpThreadAttributes,
5239 BOOL bInheritHandles,
5240 DWORD dwCreationFlags,
5241 LPVOID lpEnvironment,
5242 LPCSTR lpCurrentDirectory,
5243 LPSTARTUPINFOA lpStartupInfo,
5244 LPPROCESS_INFORMATION lpProcessInformation )
5246 BOOL ret;
5247 WCHAR *appW, *cmdlnW, *cwdW;
5248 STARTUPINFOW sinfo;
5250 TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_a(lpApplicationName),
5251 debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
5252 dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5254 appW = SERV_dup(lpApplicationName);
5255 cmdlnW = SERV_dup(lpCommandLine);
5256 cwdW = SERV_dup(lpCurrentDirectory);
5257 sinfo.cb = sizeof(sinfo);
5258 sinfo.lpReserved = SERV_dup(lpStartupInfo->lpReserved);
5259 sinfo.lpDesktop = SERV_dup(lpStartupInfo->lpDesktop);
5260 sinfo.lpTitle = SERV_dup(lpStartupInfo->lpTitle);
5261 sinfo.dwX = lpStartupInfo->dwX;
5262 sinfo.dwY = lpStartupInfo->dwY;
5263 sinfo.dwXSize = lpStartupInfo->dwXSize;
5264 sinfo.dwYSize = lpStartupInfo->dwYSize;
5265 sinfo.dwXCountChars = lpStartupInfo->dwXCountChars;
5266 sinfo.dwYCountChars = lpStartupInfo->dwYCountChars;
5267 sinfo.dwFillAttribute = lpStartupInfo->dwFillAttribute;
5268 sinfo.dwFlags = lpStartupInfo->dwFlags;
5269 sinfo.wShowWindow = lpStartupInfo->wShowWindow;
5270 sinfo.cbReserved2 = lpStartupInfo->cbReserved2;
5271 sinfo.lpReserved2 = lpStartupInfo->lpReserved2;
5272 sinfo.hStdInput = lpStartupInfo->hStdInput;
5273 sinfo.hStdOutput = lpStartupInfo->hStdOutput;
5274 sinfo.hStdError = lpStartupInfo->hStdError;
5275 ret = CreateProcessAsUserW(hToken, appW, cmdlnW, lpProcessAttributes,
5276 lpThreadAttributes, bInheritHandles, dwCreationFlags,
5277 lpEnvironment, cwdW, &sinfo, lpProcessInformation);
5278 heap_free(appW);
5279 heap_free(cmdlnW);
5280 heap_free(cwdW);
5281 heap_free(sinfo.lpReserved);
5282 heap_free(sinfo.lpDesktop);
5283 heap_free(sinfo.lpTitle);
5285 return ret;
5288 BOOL WINAPI CreateProcessAsUserW(
5289 HANDLE hToken,
5290 LPCWSTR lpApplicationName,
5291 LPWSTR lpCommandLine,
5292 LPSECURITY_ATTRIBUTES lpProcessAttributes,
5293 LPSECURITY_ATTRIBUTES lpThreadAttributes,
5294 BOOL bInheritHandles,
5295 DWORD dwCreationFlags,
5296 LPVOID lpEnvironment,
5297 LPCWSTR lpCurrentDirectory,
5298 LPSTARTUPINFOW lpStartupInfo,
5299 LPPROCESS_INFORMATION lpProcessInformation )
5301 FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - semi-stub\n", hToken,
5302 debugstr_w(lpApplicationName), debugstr_w(lpCommandLine), lpProcessAttributes,
5303 lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
5304 debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5306 /* We should create the process with a suspended main thread */
5307 if (!CreateProcessW (lpApplicationName,
5308 lpCommandLine,
5309 lpProcessAttributes,
5310 lpThreadAttributes,
5311 bInheritHandles,
5312 dwCreationFlags, /* CREATE_SUSPENDED */
5313 lpEnvironment,
5314 lpCurrentDirectory,
5315 lpStartupInfo,
5316 lpProcessInformation))
5318 return FALSE;
5321 return TRUE;
5324 /******************************************************************************
5325 * CreateProcessWithLogonW
5327 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
5328 LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
5329 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
5331 FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
5332 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
5333 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
5334 lpStartupInfo, lpProcessInformation);
5336 return FALSE;
5339 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line,
5340 DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info,
5341 PROCESS_INFORMATION *process_information )
5343 FIXME("%p 0x%08x %s %s 0x%08x %p %s %p %p - semi-stub\n", token,
5344 logon_flags, debugstr_w(application_name), debugstr_w(command_line),
5345 creation_flags, environment, debugstr_w(current_directory),
5346 startup_info, process_information);
5348 /* FIXME: check if handles should be inherited */
5349 return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment,
5350 current_directory, startup_info, process_information );
5353 /******************************************************************************
5354 * DuplicateTokenEx [ADVAPI32.@]
5356 BOOL WINAPI DuplicateTokenEx(
5357 HANDLE ExistingTokenHandle, DWORD dwDesiredAccess,
5358 LPSECURITY_ATTRIBUTES lpTokenAttributes,
5359 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5360 TOKEN_TYPE TokenType,
5361 PHANDLE DuplicateTokenHandle )
5363 OBJECT_ATTRIBUTES ObjectAttributes;
5365 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
5366 ImpersonationLevel, TokenType, DuplicateTokenHandle);
5368 InitializeObjectAttributes(
5369 &ObjectAttributes,
5370 NULL,
5371 (lpTokenAttributes && lpTokenAttributes->bInheritHandle) ? OBJ_INHERIT : 0,
5372 NULL,
5373 lpTokenAttributes ? lpTokenAttributes->lpSecurityDescriptor : NULL );
5375 return set_ntstatus( NtDuplicateToken( ExistingTokenHandle,
5376 dwDesiredAccess,
5377 &ObjectAttributes,
5378 ImpersonationLevel,
5379 TokenType,
5380 DuplicateTokenHandle ) );
5383 BOOL WINAPI DuplicateToken(
5384 HANDLE ExistingTokenHandle,
5385 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5386 PHANDLE DuplicateTokenHandle )
5388 return DuplicateTokenEx( ExistingTokenHandle, TOKEN_IMPERSONATE | TOKEN_QUERY,
5389 NULL, ImpersonationLevel, TokenImpersonation,
5390 DuplicateTokenHandle );
5393 /******************************************************************************
5394 * ComputeStringSidSize
5396 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
5398 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
5400 int ctok = 0;
5401 while (*StringSid)
5403 if (*StringSid == '-')
5404 ctok++;
5405 StringSid++;
5408 if (ctok >= 3)
5409 return GetSidLengthRequired(ctok - 2);
5411 else /* String constant format - Only available in winxp and above */
5413 unsigned int i;
5415 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5416 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5417 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
5419 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
5420 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
5422 MAX_SID local;
5423 ADVAPI_GetComputerSid(&local);
5424 return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1);
5429 return GetSidLengthRequired(0);
5432 /******************************************************************************
5433 * ParseStringSidToSid
5435 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
5437 BOOL bret = FALSE;
5438 SID* pisid=pSid;
5440 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
5441 if (!StringSid)
5443 SetLastError(ERROR_INVALID_PARAMETER);
5444 TRACE("StringSid is NULL, returning FALSE\n");
5445 return FALSE;
5448 while (*StringSid == ' ')
5449 StringSid++;
5451 *cBytes = ComputeStringSidSize(StringSid);
5452 if (!pisid) /* Simply compute the size */
5454 TRACE("only size requested, returning TRUE with %d\n", *cBytes);
5455 return TRUE;
5458 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
5460 DWORD i = 0, identAuth;
5461 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
5463 StringSid += 2; /* Advance to Revision */
5464 pisid->Revision = atoiW(StringSid);
5466 if (pisid->Revision != SDDL_REVISION)
5468 TRACE("Revision %d is unknown\n", pisid->Revision);
5469 goto lend; /* ERROR_INVALID_SID */
5471 if (csubauth == 0)
5473 TRACE("SubAuthorityCount is 0\n");
5474 goto lend; /* ERROR_INVALID_SID */
5477 pisid->SubAuthorityCount = csubauth;
5479 /* Advance to identifier authority */
5480 while (*StringSid && *StringSid != '-')
5481 StringSid++;
5482 if (*StringSid == '-')
5483 StringSid++;
5485 /* MS' implementation can't handle values greater than 2^32 - 1, so
5486 * we don't either; assume most significant bytes are always 0
5488 pisid->IdentifierAuthority.Value[0] = 0;
5489 pisid->IdentifierAuthority.Value[1] = 0;
5490 identAuth = atoiW(StringSid);
5491 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
5492 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
5493 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
5494 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
5496 /* Advance to first sub authority */
5497 while (*StringSid && *StringSid != '-')
5498 StringSid++;
5499 if (*StringSid == '-')
5500 StringSid++;
5502 while (*StringSid)
5504 pisid->SubAuthority[i++] = atoiW(StringSid);
5506 while (*StringSid && *StringSid != '-')
5507 StringSid++;
5508 if (*StringSid == '-')
5509 StringSid++;
5512 if (i != pisid->SubAuthorityCount)
5513 goto lend; /* ERROR_INVALID_SID */
5515 bret = TRUE;
5517 else /* String constant format - Only available in winxp and above */
5519 unsigned int i;
5520 pisid->Revision = SDDL_REVISION;
5522 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5523 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5525 DWORD j;
5526 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
5527 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
5528 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
5529 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
5530 bret = TRUE;
5533 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
5534 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
5536 ADVAPI_GetComputerSid(pisid);
5537 pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid;
5538 pisid->SubAuthorityCount++;
5539 bret = TRUE;
5542 if (!bret)
5543 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
5546 lend:
5547 if (!bret)
5548 SetLastError(ERROR_INVALID_SID);
5550 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
5551 return bret;
5554 /******************************************************************************
5555 * GetNamedSecurityInfoA [ADVAPI32.@]
5557 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
5558 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5559 PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
5560 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
5562 LPWSTR wstr;
5563 DWORD r;
5565 TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
5566 ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
5568 wstr = SERV_dup(pObjectName);
5569 r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
5570 ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
5572 heap_free( wstr );
5574 return r;
5577 /******************************************************************************
5578 * GetNamedSecurityInfoW [ADVAPI32.@]
5580 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
5581 SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
5582 PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
5584 DWORD access = 0;
5585 HANDLE handle;
5586 DWORD err;
5588 TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
5589 group, dacl, sacl, descriptor );
5591 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
5592 if (!name || !(owner||group||dacl||sacl||descriptor) ) return ERROR_INVALID_PARAMETER;
5594 /* If no descriptor, we have to check that there's a pointer for the requested information */
5595 if( !descriptor && (
5596 ((info & OWNER_SECURITY_INFORMATION) && !owner)
5597 || ((info & GROUP_SECURITY_INFORMATION) && !group)
5598 || ((info & DACL_SECURITY_INFORMATION) && !dacl)
5599 || ((info & SACL_SECURITY_INFORMATION) && !sacl) ))
5600 return ERROR_INVALID_PARAMETER;
5602 if (info & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION))
5603 access |= READ_CONTROL;
5604 if (info & SACL_SECURITY_INFORMATION)
5605 access |= ACCESS_SYSTEM_SECURITY;
5607 switch (type)
5609 case SE_SERVICE:
5610 if (!(err = get_security_service( name, access, &handle )))
5612 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5613 CloseServiceHandle( handle );
5615 break;
5616 case SE_REGISTRY_KEY:
5617 if (!(err = get_security_regkey( name, access, &handle )))
5619 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5620 RegCloseKey( handle );
5622 break;
5623 case SE_FILE_OBJECT:
5624 if (!(err = get_security_file( name, access, &handle )))
5626 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5627 CloseHandle( handle );
5629 break;
5630 default:
5631 FIXME( "Object type %d is not currently supported.\n", type );
5632 if (owner) *owner = NULL;
5633 if (group) *group = NULL;
5634 if (dacl) *dacl = NULL;
5635 if (sacl) *sacl = NULL;
5636 if (descriptor) *descriptor = NULL;
5637 return ERROR_SUCCESS;
5639 return err;
5642 /******************************************************************************
5643 * GetNamedSecurityInfoExW [ADVAPI32.@]
5645 DWORD WINAPI GetNamedSecurityInfoExW( LPCWSTR object, SE_OBJECT_TYPE type,
5646 SECURITY_INFORMATION info, LPCWSTR provider, LPCWSTR property,
5647 PACTRL_ACCESSW* access_list, PACTRL_AUDITW* audit_list, LPWSTR* owner, LPWSTR* group )
5649 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_w(object), type, info,
5650 debugstr_w(provider), debugstr_w(property), access_list, audit_list, owner, group);
5651 return ERROR_CALL_NOT_IMPLEMENTED;
5654 /******************************************************************************
5655 * GetNamedSecurityInfoExA [ADVAPI32.@]
5657 DWORD WINAPI GetNamedSecurityInfoExA( LPCSTR object, SE_OBJECT_TYPE type,
5658 SECURITY_INFORMATION info, LPCSTR provider, LPCSTR property,
5659 PACTRL_ACCESSA* access_list, PACTRL_AUDITA* audit_list, LPSTR* owner, LPSTR* group )
5661 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_a(object), type, info,
5662 debugstr_a(provider), debugstr_a(property), access_list, audit_list, owner, group);
5663 return ERROR_CALL_NOT_IMPLEMENTED;
5666 /******************************************************************************
5667 * DecryptFileW [ADVAPI32.@]
5669 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
5671 FIXME("(%s, %08x): stub\n", debugstr_w(lpFileName), dwReserved);
5672 return TRUE;
5675 /******************************************************************************
5676 * DecryptFileA [ADVAPI32.@]
5678 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
5680 FIXME("(%s, %08x): stub\n", debugstr_a(lpFileName), dwReserved);
5681 return TRUE;
5684 /******************************************************************************
5685 * EncryptFileW [ADVAPI32.@]
5687 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
5689 FIXME("(%s): stub\n", debugstr_w(lpFileName));
5690 return TRUE;
5693 /******************************************************************************
5694 * EncryptFileA [ADVAPI32.@]
5696 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
5698 FIXME("(%s): stub\n", debugstr_a(lpFileName));
5699 return TRUE;
5702 /******************************************************************************
5703 * FileEncryptionStatusW [ADVAPI32.@]
5705 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
5707 FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
5708 if (!lpStatus)
5709 return FALSE;
5710 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5711 return TRUE;
5714 /******************************************************************************
5715 * FileEncryptionStatusA [ADVAPI32.@]
5717 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
5719 FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
5720 if (!lpStatus)
5721 return FALSE;
5722 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5723 return TRUE;
5726 /******************************************************************************
5727 * SetSecurityInfo [ADVAPI32.@]
5729 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType,
5730 SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
5731 PSID psidGroup, PACL pDacl, PACL pSacl)
5733 SECURITY_DESCRIPTOR sd;
5734 PACL dacl = pDacl;
5735 NTSTATUS status;
5737 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
5738 return ERROR_INVALID_SECURITY_DESCR;
5740 if (SecurityInfo & OWNER_SECURITY_INFORMATION)
5741 SetSecurityDescriptorOwner(&sd, psidOwner, FALSE);
5742 if (SecurityInfo & GROUP_SECURITY_INFORMATION)
5743 SetSecurityDescriptorGroup(&sd, psidGroup, FALSE);
5744 if (SecurityInfo & DACL_SECURITY_INFORMATION)
5746 if (ObjectType == SE_FILE_OBJECT)
5748 SECURITY_DESCRIPTOR_CONTROL control;
5749 PSECURITY_DESCRIPTOR psd;
5750 OBJECT_NAME_INFORMATION *name_info;
5751 DWORD size, rev;
5753 status = NtQuerySecurityObject(handle, SecurityInfo, NULL, 0, &size);
5754 if (status != STATUS_BUFFER_TOO_SMALL)
5755 return RtlNtStatusToDosError(status);
5757 psd = heap_alloc(size);
5758 if (!psd)
5759 return ERROR_NOT_ENOUGH_MEMORY;
5761 status = NtQuerySecurityObject(handle, SecurityInfo, psd, size, &size);
5762 if (status)
5764 heap_free(psd);
5765 return RtlNtStatusToDosError(status);
5768 status = RtlGetControlSecurityDescriptor(psd, &control, &rev);
5769 heap_free(psd);
5770 if (status)
5771 return RtlNtStatusToDosError(status);
5772 /* TODO: copy some control flags to new sd */
5774 /* inherit parent directory DACL */
5775 if (!(control & SE_DACL_PROTECTED))
5777 status = NtQueryObject(handle, ObjectNameInformation, NULL, 0, &size);
5778 if (status != STATUS_INFO_LENGTH_MISMATCH)
5779 return RtlNtStatusToDosError(status);
5781 name_info = heap_alloc(size);
5782 if (!name_info)
5783 return ERROR_NOT_ENOUGH_MEMORY;
5785 status = NtQueryObject(handle, ObjectNameInformation, name_info, size, NULL);
5786 if (status)
5788 heap_free(name_info);
5789 return RtlNtStatusToDosError(status);
5792 for (name_info->Name.Length-=2; name_info->Name.Length>0; name_info->Name.Length-=2)
5793 if (name_info->Name.Buffer[name_info->Name.Length/2-1]=='\\' ||
5794 name_info->Name.Buffer[name_info->Name.Length/2-1]=='/')
5795 break;
5796 if (name_info->Name.Length)
5798 OBJECT_ATTRIBUTES attr;
5799 IO_STATUS_BLOCK io;
5800 HANDLE parent;
5801 PSECURITY_DESCRIPTOR parent_sd;
5802 ACL *parent_dacl;
5803 DWORD err = ERROR_ACCESS_DENIED;
5805 name_info->Name.Buffer[name_info->Name.Length/2] = 0;
5807 attr.Length = sizeof(attr);
5808 attr.RootDirectory = 0;
5809 attr.Attributes = 0;
5810 attr.ObjectName = &name_info->Name;
5811 attr.SecurityDescriptor = NULL;
5812 status = NtOpenFile(&parent, READ_CONTROL, &attr, &io,
5813 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5814 FILE_OPEN_FOR_BACKUP_INTENT);
5815 heap_free(name_info);
5816 if (!status)
5818 err = GetSecurityInfo(parent, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
5819 NULL, NULL, &parent_dacl, NULL, &parent_sd);
5820 CloseHandle(parent);
5823 if (!err)
5825 int i;
5827 dacl = heap_alloc_zero(pDacl->AclSize+parent_dacl->AclSize);
5828 if (!dacl)
5830 LocalFree(parent_sd);
5831 return ERROR_NOT_ENOUGH_MEMORY;
5833 memcpy(dacl, pDacl, pDacl->AclSize);
5834 dacl->AclSize = pDacl->AclSize+parent_dacl->AclSize;
5836 for (i=0; i<parent_dacl->AceCount; i++)
5838 ACE_HEADER *ace;
5840 if (!GetAce(parent_dacl, i, (void*)&ace))
5841 continue;
5842 if (!(ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)))
5843 continue;
5844 if ((ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) !=
5845 (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE))
5847 FIXME("unsupported flags: %x\n", ace->AceFlags);
5848 continue;
5851 if (ace->AceFlags & NO_PROPAGATE_INHERIT_ACE)
5852 ace->AceFlags &= ~(OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE|NO_PROPAGATE_INHERIT_ACE);
5853 ace->AceFlags &= ~INHERIT_ONLY_ACE;
5854 ace->AceFlags |= INHERITED_ACE;
5856 if(!AddAce(dacl, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
5857 WARN("error adding inherited ACE\n");
5859 LocalFree(parent_sd);
5862 else
5863 heap_free(name_info);
5867 SetSecurityDescriptorDacl(&sd, TRUE, dacl, FALSE);
5869 if (SecurityInfo & SACL_SECURITY_INFORMATION)
5870 SetSecurityDescriptorSacl(&sd, TRUE, pSacl, FALSE);
5872 switch (ObjectType)
5874 case SE_SERVICE:
5875 FIXME("stub: Service objects are not supported at this time.\n");
5876 status = STATUS_SUCCESS; /* Implement SetServiceObjectSecurity */
5877 break;
5878 default:
5879 status = NtSetSecurityObject(handle, SecurityInfo, &sd);
5880 break;
5882 if (dacl != pDacl)
5883 heap_free(dacl);
5884 return RtlNtStatusToDosError(status);
5887 /******************************************************************************
5888 * SaferCreateLevel [ADVAPI32.@]
5890 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
5891 SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
5893 FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
5895 *LevelHandle = (SAFER_LEVEL_HANDLE)0xdeadbeef;
5896 return TRUE;
5899 /******************************************************************************
5900 * SaferComputeTokenFromLevel [ADVAPI32.@]
5902 BOOL WINAPI SaferComputeTokenFromLevel(SAFER_LEVEL_HANDLE handle, HANDLE token, PHANDLE access_token,
5903 DWORD flags, LPVOID reserved)
5905 FIXME("(%p, %p, %p, %x, %p) stub\n", handle, token, access_token, flags, reserved);
5907 *access_token = (HANDLE)0xdeadbeef;
5908 return TRUE;
5911 /******************************************************************************
5912 * SaferCloseLevel [ADVAPI32.@]
5914 BOOL WINAPI SaferCloseLevel(SAFER_LEVEL_HANDLE handle)
5916 FIXME("(%p) stub\n", handle);
5917 return TRUE;
5920 DWORD WINAPI TreeResetNamedSecurityInfoW( LPWSTR pObjectName,
5921 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5922 PSID pOwner, PSID pGroup, PACL pDacl, PACL pSacl,
5923 BOOL KeepExplicit, FN_PROGRESS fnProgress,
5924 PROG_INVOKE_SETTING ProgressInvokeSetting, PVOID Args)
5926 FIXME("(%s, %i, %i, %p, %p, %p, %p, %i, %p, %i, %p) stub\n",
5927 debugstr_w(pObjectName), ObjectType, SecurityInfo, pOwner, pGroup,
5928 pDacl, pSacl, KeepExplicit, fnProgress, ProgressInvokeSetting, Args);
5930 return ERROR_SUCCESS;
5933 /******************************************************************************
5934 * SaferGetPolicyInformation [ADVAPI32.@]
5936 BOOL WINAPI SaferGetPolicyInformation(DWORD scope, SAFER_POLICY_INFO_CLASS class, DWORD size,
5937 PVOID buffer, PDWORD required, LPVOID lpReserved)
5939 FIXME("(%u %u %u %p %p %p) stub\n", scope, class, size, buffer, required, lpReserved);
5940 return FALSE;
5943 /******************************************************************************
5944 * SaferSetLevelInformation [ADVAPI32.@]
5946 BOOL WINAPI SaferSetLevelInformation(SAFER_LEVEL_HANDLE handle, SAFER_OBJECT_INFO_CLASS infotype,
5947 LPVOID buffer, DWORD size)
5949 FIXME("(%p %u %p %u) stub\n", handle, infotype, buffer, size);
5950 return FALSE;