msvcrt: Write directly to the console in _putwch.
[wine/multimedia.git] / dlls / advapi32 / security.c
blob028dcc6d9e354802f7f542141c56ff66a6ab4cc5
1 /*
2 * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
3 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
4 * Copyright 2006 Robert Reif
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
23 #include <string.h>
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "winreg.h"
31 #include "winsafer.h"
32 #include "winternl.h"
33 #include "winioctl.h"
34 #include "accctrl.h"
35 #include "sddl.h"
36 #include "winsvc.h"
37 #include "aclapi.h"
38 #include "objbase.h"
39 #include "iads.h"
40 #include "advapi32_misc.h"
41 #include "lmcons.h"
43 #include "wine/debug.h"
44 #include "wine/unicode.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
48 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes);
49 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
50 PACL pAcl, LPDWORD cBytes);
51 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl);
52 static BYTE ParseAceStringType(LPCWSTR* StringAcl);
53 static DWORD ParseAceStringRights(LPCWSTR* StringAcl);
54 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
55 LPCWSTR StringSecurityDescriptor,
56 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
57 LPDWORD cBytes);
58 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl);
60 typedef struct _ACEFLAG
62 LPCWSTR wstr;
63 DWORD value;
64 } ACEFLAG, *LPACEFLAG;
66 typedef struct _MAX_SID
68 /* same fields as struct _SID */
69 BYTE Revision;
70 BYTE SubAuthorityCount;
71 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
72 DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
73 } MAX_SID;
75 typedef struct WELLKNOWNSID
77 WCHAR wstr[2];
78 WELL_KNOWN_SID_TYPE Type;
79 MAX_SID Sid;
80 } WELLKNOWNSID;
82 static const WELLKNOWNSID WellKnownSids[] =
84 { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
85 { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
86 { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
87 { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
88 { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
89 { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
90 { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
91 { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
92 { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
93 { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
94 { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
95 { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
96 { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
97 { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
98 { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
99 { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
100 { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
101 { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
102 { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
103 { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
104 { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
105 { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
106 { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
107 { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
108 { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
109 { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
110 { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
111 { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
112 { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
113 { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
114 { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
115 { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
116 { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
117 { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
118 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
119 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
120 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
121 { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
122 { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
123 { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
124 { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
125 { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
126 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS } } },
127 { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
128 { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
129 { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
130 { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
131 { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
132 { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } },
133 { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } },
134 { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } },
135 { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } },
138 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */
139 typedef struct WELLKNOWNRID
141 WCHAR wstr[2];
142 WELL_KNOWN_SID_TYPE Type;
143 DWORD Rid;
144 } WELLKNOWNRID;
146 static const WELLKNOWNRID WellKnownRids[] = {
147 { {'L','A'}, WinAccountAdministratorSid, DOMAIN_USER_RID_ADMIN },
148 { {'L','G'}, WinAccountGuestSid, DOMAIN_USER_RID_GUEST },
149 { {0,0}, WinAccountKrbtgtSid, DOMAIN_USER_RID_KRBTGT },
150 { {0,0}, WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS },
151 { {0,0}, WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS },
152 { {0,0}, WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS },
153 { {0,0}, WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS },
154 { {0,0}, WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS },
155 { {0,0}, WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS },
156 { {0,0}, WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS },
157 { {0,0}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
158 { {0,0}, WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS },
159 { {0,0}, WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
163 static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
165 typedef struct _AccountSid {
166 WELL_KNOWN_SID_TYPE type;
167 LPCWSTR account;
168 LPCWSTR domain;
169 SID_NAME_USE name_use;
170 LPCWSTR alias;
171 } AccountSid;
173 static const WCHAR Account_Operators[] = { 'A','c','c','o','u','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
174 static const WCHAR Administrator[] = {'A','d','m','i','n','i','s','t','r','a','t','o','r',0 };
175 static const WCHAR Administrators[] = { 'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0 };
176 static const WCHAR ANONYMOUS_LOGON[] = { 'A','N','O','N','Y','M','O','U','S',' ','L','O','G','O','N',0 };
177 static const WCHAR Authenticated_Users[] = { 'A','u','t','h','e','n','t','i','c','a','t','e','d',' ','U','s','e','r','s',0 };
178 static const WCHAR Backup_Operators[] = { 'B','a','c','k','u','p',' ','O','p','e','r','a','t','o','r','s',0 };
179 static const WCHAR BATCH[] = { 'B','A','T','C','H',0 };
180 static const WCHAR Blank[] = { 0 };
181 static const WCHAR BUILTIN[] = { 'B','U','I','L','T','I','N',0 };
182 static const WCHAR Cert_Publishers[] = { 'C','e','r','t',' ','P','u','b','l','i','s','h','e','r','s',0 };
183 static const WCHAR CREATOR_GROUP[] = { 'C','R','E','A','T','O','R',' ','G','R','O','U','P',0 };
184 static const WCHAR CREATOR_GROUP_SERVER[] = { 'C','R','E','A','T','O','R',' ','G','R','O','U','P',' ','S','E','R','V','E','R',0 };
185 static const WCHAR CREATOR_OWNER[] = { 'C','R','E','A','T','O','R',' ','O','W','N','E','R',0 };
186 static const WCHAR CREATOR_OWNER_SERVER[] = { 'C','R','E','A','T','O','R',' ','O','W','N','E','R',' ','S','E','R','V','E','R',0 };
187 static const WCHAR CURRENT_USER[] = { 'C','U','R','R','E','N','T','_','U','S','E','R',0 };
188 static const WCHAR DIALUP[] = { 'D','I','A','L','U','P',0 };
189 static const WCHAR Digest_Authentication[] = { 'D','i','g','e','s','t',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
190 static const WCHAR Domain_Admins[] = { 'D','o','m','a','i','n',' ','A','d','m','i','n','s',0 };
191 static const WCHAR Domain_Computers[] = { 'D','o','m','a','i','n',' ','C','o','m','p','u','t','e','r','s',0 };
192 static const WCHAR Domain_Controllers[] = { 'D','o','m','a','i','n',' ','C','o','n','t','r','o','l','l','e','r','s',0 };
193 static const WCHAR Domain_Guests[] = { 'D','o','m','a','i','n',' ','G','u','e','s','t','s',0 };
194 static const WCHAR Domain_Users[] = { 'D','o','m','a','i','n',' ','U','s','e','r','s',0 };
195 static const WCHAR Enterprise_Admins[] = { 'E','n','t','e','r','p','r','i','s','e',' ','A','d','m','i','n','s',0 };
196 static const WCHAR ENTERPRISE_DOMAIN_CONTROLLERS[] = { 'E','N','T','E','R','P','R','I','S','E',' ','D','O','M','A','I','N',' ','C','O','N','T','R','O','L','L','E','R','S',0 };
197 static const WCHAR Everyone[] = { 'E','v','e','r','y','o','n','e',0 };
198 static const WCHAR Group_Policy_Creator_Owners[] = { 'G','r','o','u','p',' ','P','o','l','i','c','y',' ','C','r','e','a','t','o','r',' ','O','w','n','e','r','s',0 };
199 static const WCHAR Guest[] = { 'G','u','e','s','t',0 };
200 static const WCHAR Guests[] = { 'G','u','e','s','t','s',0 };
201 static const WCHAR INTERACTIVE[] = { 'I','N','T','E','R','A','C','T','I','V','E',0 };
202 static const WCHAR LOCAL[] = { 'L','O','C','A','L',0 };
203 static const WCHAR LOCAL_SERVICE[] = { 'L','O','C','A','L',' ','S','E','R','V','I','C','E',0 };
204 static const WCHAR LOCAL_SERVICE2[] = { 'L','O','C','A','L','S','E','R','V','I','C','E',0 };
205 static const WCHAR NETWORK[] = { 'N','E','T','W','O','R','K',0 };
206 static const WCHAR Network_Configuration_Operators[] = { 'N','e','t','w','o','r','k',' ','C','o','n','f','i','g','u','r','a','t','i','o','n',' ','O','p','e','r','a','t','o','r','s',0 };
207 static const WCHAR NETWORK_SERVICE[] = { 'N','E','T','W','O','R','K',' ','S','E','R','V','I','C','E',0 };
208 static const WCHAR NETWORK_SERVICE2[] = { 'N','E','T','W','O','R','K','S','E','R','V','I','C','E',0 };
209 static const WCHAR NT_AUTHORITY[] = { 'N','T',' ','A','U','T','H','O','R','I','T','Y',0 };
210 static const WCHAR NT_Pseudo_Domain[] = { 'N','T',' ','P','s','e','u','d','o',' ','D','o','m','a','i','n',0 };
211 static const WCHAR NTML_Authentication[] = { 'N','T','M','L',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
212 static const WCHAR NULL_SID[] = { 'N','U','L','L',' ','S','I','D',0 };
213 static const WCHAR Other_Organization[] = { 'O','t','h','e','r',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
214 static const WCHAR Performance_Log_Users[] = { 'P','e','r','f','o','r','m','a','n','c','e',' ','L','o','g',' ','U','s','e','r','s',0 };
215 static const WCHAR Performance_Monitor_Users[] = { 'P','e','r','f','o','r','m','a','n','c','e',' ','M','o','n','i','t','o','r',' ','U','s','e','r','s',0 };
216 static const WCHAR Power_Users[] = { 'P','o','w','e','r',' ','U','s','e','r','s',0 };
217 static const WCHAR Pre_Windows_2000_Compatible_Access[] = { 'P','r','e','-','W','i','n','d','o','w','s',' ','2','0','0','0',' ','C','o','m','p','a','t','i','b','l','e',' ','A','c','c','e','s','s',0 };
218 static const WCHAR Print_Operators[] = { 'P','r','i','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
219 static const WCHAR PROXY[] = { 'P','R','O','X','Y',0 };
220 static const WCHAR RAS_and_IAS_Servers[] = { 'R','A','S',' ','a','n','d',' ','I','A','S',' ','S','e','r','v','e','r','s',0 };
221 static const WCHAR Remote_Desktop_Users[] = { 'R','e','m','o','t','e',' ','D','e','s','k','t','o','p',' ','U','s','e','r','s',0 };
222 static const WCHAR REMOTE_INTERACTIVE_LOGON[] = { 'R','E','M','O','T','E',' ','I','N','T','E','R','A','C','T','I','V','E',' ','L','O','G','O','N',0 };
223 static const WCHAR Replicators[] = { 'R','e','p','l','i','c','a','t','o','r','s',0 };
224 static const WCHAR RESTRICTED[] = { 'R','E','S','T','R','I','C','T','E','D',0 };
225 static const WCHAR SChannel_Authentication[] = { 'S','C','h','a','n','n','e','l',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
226 static const WCHAR Schema_Admins[] = { 'S','c','h','e','m','a',' ','A','d','m','i','n','s',0 };
227 static const WCHAR SELF[] = { 'S','E','L','F',0 };
228 static const WCHAR Server_Operators[] = { 'S','e','r','v','e','r',' ','O','p','e','r','a','t','o','r','s',0 };
229 static const WCHAR SERVICE[] = { 'S','E','R','V','I','C','E',0 };
230 static const WCHAR SYSTEM[] = { 'S','Y','S','T','E','M',0 };
231 static const WCHAR TERMINAL_SERVER_USER[] = { 'T','E','R','M','I','N','A','L',' ','S','E','R','V','E','R',' ','U','S','E','R',0 };
232 static const WCHAR This_Organization[] = { 'T','h','i','s',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
233 static const WCHAR Users[] = { 'U','s','e','r','s',0 };
235 static const AccountSid ACCOUNT_SIDS[] = {
236 { WinNullSid, NULL_SID, Blank, SidTypeWellKnownGroup },
237 { WinWorldSid, Everyone, Blank, SidTypeWellKnownGroup },
238 { WinLocalSid, LOCAL, Blank, SidTypeWellKnownGroup },
239 { WinCreatorOwnerSid, CREATOR_OWNER, Blank, SidTypeWellKnownGroup },
240 { WinCreatorGroupSid, CREATOR_GROUP, Blank, SidTypeWellKnownGroup },
241 { WinCreatorOwnerServerSid, CREATOR_OWNER_SERVER, Blank, SidTypeWellKnownGroup },
242 { WinCreatorGroupServerSid, CREATOR_GROUP_SERVER, Blank, SidTypeWellKnownGroup },
243 { WinNtAuthoritySid, NT_Pseudo_Domain, NT_Pseudo_Domain, SidTypeDomain },
244 { WinDialupSid, DIALUP, NT_AUTHORITY, SidTypeWellKnownGroup },
245 { WinNetworkSid, NETWORK, NT_AUTHORITY, SidTypeWellKnownGroup },
246 { WinBatchSid, BATCH, NT_AUTHORITY, SidTypeWellKnownGroup },
247 { WinInteractiveSid, INTERACTIVE, NT_AUTHORITY, SidTypeWellKnownGroup },
248 { WinServiceSid, SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup },
249 { WinAnonymousSid, ANONYMOUS_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
250 { WinProxySid, PROXY, NT_AUTHORITY, SidTypeWellKnownGroup },
251 { WinEnterpriseControllersSid, ENTERPRISE_DOMAIN_CONTROLLERS, NT_AUTHORITY, SidTypeWellKnownGroup },
252 { WinSelfSid, SELF, NT_AUTHORITY, SidTypeWellKnownGroup },
253 { WinAuthenticatedUserSid, Authenticated_Users, NT_AUTHORITY, SidTypeWellKnownGroup },
254 { WinRestrictedCodeSid, RESTRICTED, NT_AUTHORITY, SidTypeWellKnownGroup },
255 { WinTerminalServerSid, TERMINAL_SERVER_USER, NT_AUTHORITY, SidTypeWellKnownGroup },
256 { WinRemoteLogonIdSid, REMOTE_INTERACTIVE_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
257 { WinLocalSystemSid, SYSTEM, NT_AUTHORITY, SidTypeWellKnownGroup },
258 { WinLocalServiceSid, LOCAL_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup, LOCAL_SERVICE2 },
259 { WinNetworkServiceSid, NETWORK_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup , NETWORK_SERVICE2},
260 { WinBuiltinDomainSid, BUILTIN, BUILTIN, SidTypeDomain },
261 { WinBuiltinAdministratorsSid, Administrators, BUILTIN, SidTypeAlias },
262 { WinBuiltinUsersSid, Users, BUILTIN, SidTypeAlias },
263 { WinBuiltinGuestsSid, Guests, BUILTIN, SidTypeAlias },
264 { WinBuiltinPowerUsersSid, Power_Users, BUILTIN, SidTypeAlias },
265 { WinBuiltinAccountOperatorsSid, Account_Operators, BUILTIN, SidTypeAlias },
266 { WinBuiltinSystemOperatorsSid, Server_Operators, BUILTIN, SidTypeAlias },
267 { WinBuiltinPrintOperatorsSid, Print_Operators, BUILTIN, SidTypeAlias },
268 { WinBuiltinBackupOperatorsSid, Backup_Operators, BUILTIN, SidTypeAlias },
269 { WinBuiltinReplicatorSid, Replicators, BUILTIN, SidTypeAlias },
270 { WinBuiltinPreWindows2000CompatibleAccessSid, Pre_Windows_2000_Compatible_Access, BUILTIN, SidTypeAlias },
271 { WinBuiltinRemoteDesktopUsersSid, Remote_Desktop_Users, BUILTIN, SidTypeAlias },
272 { WinBuiltinNetworkConfigurationOperatorsSid, Network_Configuration_Operators, BUILTIN, SidTypeAlias },
273 { WinNTLMAuthenticationSid, NTML_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
274 { WinDigestAuthenticationSid, Digest_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
275 { WinSChannelAuthenticationSid, SChannel_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
276 { WinThisOrganizationSid, This_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
277 { WinOtherOrganizationSid, Other_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
278 { WinBuiltinPerfMonitoringUsersSid, Performance_Monitor_Users, BUILTIN, SidTypeAlias },
279 { WinBuiltinPerfLoggingUsersSid, Performance_Log_Users, BUILTIN, SidTypeAlias },
282 * ACE access rights
284 static const WCHAR SDDL_READ_CONTROL[] = {'R','C',0};
285 static const WCHAR SDDL_WRITE_DAC[] = {'W','D',0};
286 static const WCHAR SDDL_WRITE_OWNER[] = {'W','O',0};
287 static const WCHAR SDDL_STANDARD_DELETE[] = {'S','D',0};
289 static const WCHAR SDDL_READ_PROPERTY[] = {'R','P',0};
290 static const WCHAR SDDL_WRITE_PROPERTY[] = {'W','P',0};
291 static const WCHAR SDDL_CREATE_CHILD[] = {'C','C',0};
292 static const WCHAR SDDL_DELETE_CHILD[] = {'D','C',0};
293 static const WCHAR SDDL_LIST_CHILDREN[] = {'L','C',0};
294 static const WCHAR SDDL_SELF_WRITE[] = {'S','W',0};
295 static const WCHAR SDDL_LIST_OBJECT[] = {'L','O',0};
296 static const WCHAR SDDL_DELETE_TREE[] = {'D','T',0};
297 static const WCHAR SDDL_CONTROL_ACCESS[] = {'C','R',0};
299 static const WCHAR SDDL_FILE_ALL[] = {'F','A',0};
300 static const WCHAR SDDL_FILE_READ[] = {'F','R',0};
301 static const WCHAR SDDL_FILE_WRITE[] = {'F','W',0};
302 static const WCHAR SDDL_FILE_EXECUTE[] = {'F','X',0};
304 static const WCHAR SDDL_KEY_ALL[] = {'K','A',0};
305 static const WCHAR SDDL_KEY_READ[] = {'K','R',0};
306 static const WCHAR SDDL_KEY_WRITE[] = {'K','W',0};
307 static const WCHAR SDDL_KEY_EXECUTE[] = {'K','X',0};
309 static const WCHAR SDDL_GENERIC_ALL[] = {'G','A',0};
310 static const WCHAR SDDL_GENERIC_READ[] = {'G','R',0};
311 static const WCHAR SDDL_GENERIC_WRITE[] = {'G','W',0};
312 static const WCHAR SDDL_GENERIC_EXECUTE[] = {'G','X',0};
314 static const WCHAR SDDL_NO_READ_UP[] = {'N','R',0};
315 static const WCHAR SDDL_NO_WRITE_UP[] = {'N','W',0};
316 static const WCHAR SDDL_NO_EXECUTE_UP[] = {'N','X',0};
319 * ACL flags
321 static const WCHAR SDDL_PROTECTED[] = {'P',0};
322 static const WCHAR SDDL_AUTO_INHERIT_REQ[] = {'A','R',0};
323 static const WCHAR SDDL_AUTO_INHERITED[] = {'A','I',0};
326 * ACE types
328 static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0};
329 static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0};
330 static const WCHAR SDDL_AUDIT[] = {'A','U',0};
331 static const WCHAR SDDL_ALARM[] = {'A','L',0};
332 static const WCHAR SDDL_MANDATORY_LABEL[] = {'M','L',0};
335 * ACE flags
337 static const WCHAR SDDL_CONTAINER_INHERIT[] = {'C','I',0};
338 static const WCHAR SDDL_OBJECT_INHERIT[] = {'O','I',0};
339 static const WCHAR SDDL_NO_PROPAGATE[] = {'N','P',0};
340 static const WCHAR SDDL_INHERIT_ONLY[] = {'I','O',0};
341 static const WCHAR SDDL_INHERITED[] = {'I','D',0};
342 static const WCHAR SDDL_AUDIT_SUCCESS[] = {'S','A',0};
343 static const WCHAR SDDL_AUDIT_FAILURE[] = {'F','A',0};
345 const char * debugstr_sid(PSID sid)
347 int auth = 0;
348 SID * psid = sid;
350 if (psid == NULL)
351 return "(null)";
353 auth = psid->IdentifierAuthority.Value[5] +
354 (psid->IdentifierAuthority.Value[4] << 8) +
355 (psid->IdentifierAuthority.Value[3] << 16) +
356 (psid->IdentifierAuthority.Value[2] << 24);
358 switch (psid->SubAuthorityCount) {
359 case 0:
360 return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
361 case 1:
362 return wine_dbg_sprintf("S-%d-%d-%u", psid->Revision, auth,
363 psid->SubAuthority[0]);
364 case 2:
365 return wine_dbg_sprintf("S-%d-%d-%u-%u", psid->Revision, auth,
366 psid->SubAuthority[0], psid->SubAuthority[1]);
367 case 3:
368 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u", psid->Revision, auth,
369 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
370 case 4:
371 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u", psid->Revision, auth,
372 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
373 psid->SubAuthority[3]);
374 case 5:
375 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u", psid->Revision, auth,
376 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
377 psid->SubAuthority[3], psid->SubAuthority[4]);
378 case 6:
379 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
380 psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
381 psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
382 case 7:
383 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
384 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
385 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
386 psid->SubAuthority[6]);
387 case 8:
388 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
389 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
390 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
391 psid->SubAuthority[6], psid->SubAuthority[7]);
393 return "(too-big)";
396 /* set last error code from NT status and get the proper boolean return value */
397 /* used for functions that are a simple wrapper around the corresponding ntdll API */
398 static inline BOOL set_ntstatus( NTSTATUS status )
400 if (status) SetLastError( RtlNtStatusToDosError( status ));
401 return !status;
404 /* helper function for SE_FILE_OBJECT objects in [Get|Set]NamedSecurityInfo */
405 static inline DWORD get_security_file( LPCWSTR full_file_name, DWORD access, HANDLE *file )
407 UNICODE_STRING file_nameW;
408 OBJECT_ATTRIBUTES attr;
409 IO_STATUS_BLOCK io;
410 NTSTATUS status;
412 if (!RtlDosPathNameToNtPathName_U( full_file_name, &file_nameW, NULL, NULL ))
413 return ERROR_PATH_NOT_FOUND;
414 attr.Length = sizeof(attr);
415 attr.RootDirectory = 0;
416 attr.Attributes = OBJ_CASE_INSENSITIVE;
417 attr.ObjectName = &file_nameW;
418 attr.SecurityDescriptor = NULL;
419 status = NtCreateFile( file, access, &attr, &io, NULL, FILE_FLAG_BACKUP_SEMANTICS,
420 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
421 FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 );
422 RtlFreeUnicodeString( &file_nameW );
423 return RtlNtStatusToDosError( status );
426 /* helper function for SE_SERVICE objects in [Get|Set]NamedSecurityInfo */
427 static inline DWORD get_security_service( LPWSTR full_service_name, DWORD access, HANDLE *service )
429 SC_HANDLE manager = 0;
430 DWORD err;
432 err = SERV_OpenSCManagerW( NULL, NULL, access, (SC_HANDLE *)&manager );
433 if (err == ERROR_SUCCESS)
434 err = SERV_OpenServiceW( manager, full_service_name, access, (SC_HANDLE *)service );
435 CloseServiceHandle( manager );
436 return err;
439 /* helper function for SE_REGISTRY_KEY objects in [Get|Set]NamedSecurityInfo */
440 static inline DWORD get_security_regkey( LPWSTR full_key_name, DWORD access, HANDLE *key )
442 WCHAR classes_rootW[] = {'C','L','A','S','S','E','S','_','R','O','O','T',0};
443 WCHAR current_userW[] = {'C','U','R','R','E','N','T','_','U','S','E','R',0};
444 WCHAR machineW[] = {'M','A','C','H','I','N','E',0};
445 WCHAR usersW[] = {'U','S','E','R','S',0};
446 LPWSTR p = strchrW(full_key_name, '\\');
447 int len = p-full_key_name;
448 HKEY hParent;
450 if (!p) return ERROR_INVALID_PARAMETER;
451 if (strncmpW( full_key_name, classes_rootW, len ) == 0)
452 hParent = HKEY_CLASSES_ROOT;
453 else if (strncmpW( full_key_name, current_userW, len ) == 0)
454 hParent = HKEY_CURRENT_USER;
455 else if (strncmpW( full_key_name, machineW, len ) == 0)
456 hParent = HKEY_LOCAL_MACHINE;
457 else if (strncmpW( full_key_name, usersW, len ) == 0)
458 hParent = HKEY_USERS;
459 else
460 return ERROR_INVALID_PARAMETER;
461 return RegOpenKeyExW( hParent, p+1, 0, access, (HKEY *)key );
464 #define WINE_SIZE_OF_WORLD_ACCESS_ACL (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD))
466 static void GetWorldAccessACL(PACL pACL)
468 PACCESS_ALLOWED_ACE pACE = (PACCESS_ALLOWED_ACE) (pACL + 1);
470 pACL->AclRevision = ACL_REVISION;
471 pACL->Sbz1 = 0;
472 pACL->AclSize = WINE_SIZE_OF_WORLD_ACCESS_ACL;
473 pACL->AceCount = 1;
474 pACL->Sbz2 = 0;
476 pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
477 pACE->Header.AceFlags = CONTAINER_INHERIT_ACE;
478 pACE->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD);
479 pACE->Mask = 0xf3ffffff; /* Everything except reserved bits */
480 memcpy(&pACE->SidStart, &sidWorld, sizeof(sidWorld));
483 /************************************************************
484 * ADVAPI_IsLocalComputer
486 * Checks whether the server name indicates local machine.
488 BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName)
490 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
491 BOOL Result;
492 LPWSTR buf;
494 if (!ServerName || !ServerName[0])
495 return TRUE;
497 buf = heap_alloc(dwSize * sizeof(WCHAR));
498 Result = GetComputerNameW(buf, &dwSize);
499 if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
500 ServerName += 2;
501 Result = Result && !lstrcmpW(ServerName, buf);
502 heap_free(buf);
504 return Result;
507 /************************************************************
508 * ADVAPI_GetComputerSid
510 BOOL ADVAPI_GetComputerSid(PSID sid)
512 static const struct /* same fields as struct SID */
514 BYTE Revision;
515 BYTE SubAuthorityCount;
516 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
517 DWORD SubAuthority[4];
518 } computer_sid =
519 { SID_REVISION, 4, { SECURITY_NT_AUTHORITY }, { SECURITY_NT_NON_UNIQUE, 0, 0, 0 } };
521 memcpy( sid, &computer_sid, sizeof(computer_sid) );
522 return TRUE;
525 /* ##############################
526 ###### TOKEN FUNCTIONS ######
527 ##############################
530 /******************************************************************************
531 * OpenProcessToken [ADVAPI32.@]
532 * Opens the access token associated with a process handle.
534 * PARAMS
535 * ProcessHandle [I] Handle to process
536 * DesiredAccess [I] Desired access to process
537 * TokenHandle [O] Pointer to handle of open access token
539 * RETURNS
540 * Success: TRUE. TokenHandle contains the access token.
541 * Failure: FALSE.
543 * NOTES
544 * See NtOpenProcessToken.
546 BOOL WINAPI
547 OpenProcessToken( HANDLE ProcessHandle, DWORD DesiredAccess,
548 HANDLE *TokenHandle )
550 return set_ntstatus(NtOpenProcessToken( ProcessHandle, DesiredAccess, TokenHandle ));
553 /******************************************************************************
554 * OpenThreadToken [ADVAPI32.@]
556 * Opens the access token associated with a thread handle.
558 * PARAMS
559 * ThreadHandle [I] Handle to process
560 * DesiredAccess [I] Desired access to the thread
561 * OpenAsSelf [I] ???
562 * TokenHandle [O] Destination for the token handle
564 * RETURNS
565 * Success: TRUE. TokenHandle contains the access token.
566 * Failure: FALSE.
568 * NOTES
569 * See NtOpenThreadToken.
571 BOOL WINAPI
572 OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess,
573 BOOL OpenAsSelf, HANDLE *TokenHandle)
575 return set_ntstatus( NtOpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle));
578 BOOL WINAPI
579 AdjustTokenGroups( HANDLE TokenHandle, BOOL ResetToDefault, PTOKEN_GROUPS NewState,
580 DWORD BufferLength, PTOKEN_GROUPS PreviousState, PDWORD ReturnLength )
582 return set_ntstatus( NtAdjustGroupsToken(TokenHandle, ResetToDefault, NewState, BufferLength,
583 PreviousState, ReturnLength));
586 /******************************************************************************
587 * AdjustTokenPrivileges [ADVAPI32.@]
589 * Adjust the privileges of an open token handle.
591 * PARAMS
592 * TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
593 * DisableAllPrivileges [I] TRUE=Remove all privileges, FALSE=Use NewState
594 * NewState [I] Desired new privileges of the token
595 * BufferLength [I] Length of NewState
596 * PreviousState [O] Destination for the previous state
597 * ReturnLength [I/O] Size of PreviousState
600 * RETURNS
601 * Success: TRUE. Privileges are set to NewState and PreviousState is updated.
602 * Failure: FALSE.
604 * NOTES
605 * See NtAdjustPrivilegesToken.
607 BOOL WINAPI
608 AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges,
609 PTOKEN_PRIVILEGES NewState, DWORD BufferLength,
610 PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength )
612 NTSTATUS status;
614 TRACE("(%p %d %p %d %p %p)\n", TokenHandle, DisableAllPrivileges, NewState, BufferLength,
615 PreviousState, ReturnLength);
617 status = NtAdjustPrivilegesToken(TokenHandle, DisableAllPrivileges,
618 NewState, BufferLength, PreviousState,
619 ReturnLength);
620 SetLastError( RtlNtStatusToDosError( status ));
621 if ((status == STATUS_SUCCESS) || (status == STATUS_NOT_ALL_ASSIGNED))
622 return TRUE;
623 else
624 return FALSE;
627 /******************************************************************************
628 * CheckTokenMembership [ADVAPI32.@]
630 * Determine if an access token is a member of a SID.
632 * PARAMS
633 * TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
634 * SidToCheck [I] SID that possibly contains the token
635 * IsMember [O] Destination for result.
637 * RETURNS
638 * Success: TRUE. IsMember is TRUE if TokenHandle is a member, FALSE otherwise.
639 * Failure: FALSE.
641 BOOL WINAPI
642 CheckTokenMembership( HANDLE token, PSID sid_to_check,
643 PBOOL is_member )
645 PTOKEN_GROUPS token_groups = NULL;
646 HANDLE thread_token = NULL;
647 DWORD size, i;
648 BOOL ret;
650 TRACE("(%p %s %p)\n", token, debugstr_sid(sid_to_check), is_member);
652 *is_member = FALSE;
654 if (!token)
656 if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &thread_token))
658 HANDLE process_token;
659 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &process_token);
660 if (!ret)
661 goto exit;
662 ret = DuplicateTokenEx(process_token, TOKEN_QUERY,
663 NULL, SecurityImpersonation, TokenImpersonation,
664 &thread_token);
665 CloseHandle(process_token);
666 if (!ret)
667 goto exit;
669 token = thread_token;
671 else
673 TOKEN_TYPE type;
675 ret = GetTokenInformation(token, TokenType, &type, sizeof(TOKEN_TYPE), &size);
676 if (!ret) goto exit;
678 if (type == TokenPrimary)
680 SetLastError(ERROR_NO_IMPERSONATION_TOKEN);
681 return FALSE;
685 ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
686 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
687 goto exit;
689 token_groups = heap_alloc(size);
690 if (!token_groups)
692 ret = FALSE;
693 goto exit;
696 ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
697 if (!ret)
698 goto exit;
700 for (i = 0; i < token_groups->GroupCount; i++)
702 TRACE("Groups[%d]: {0x%x, %s}\n", i,
703 token_groups->Groups[i].Attributes,
704 debugstr_sid(token_groups->Groups[i].Sid));
705 if ((token_groups->Groups[i].Attributes & SE_GROUP_ENABLED) &&
706 EqualSid(sid_to_check, token_groups->Groups[i].Sid))
708 *is_member = TRUE;
709 TRACE("sid enabled and found in token\n");
710 break;
714 exit:
715 heap_free(token_groups);
716 if (thread_token != NULL) CloseHandle(thread_token);
718 return ret;
721 /******************************************************************************
722 * GetTokenInformation [ADVAPI32.@]
724 * Get a type of information about an access token.
726 * PARAMS
727 * token [I] Handle from OpenProcessToken() or OpenThreadToken()
728 * tokeninfoclass [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
729 * tokeninfo [O] Destination for token information
730 * tokeninfolength [I] Length of tokeninfo
731 * retlen [O] Destination for returned token information length
733 * RETURNS
734 * Success: TRUE. tokeninfo contains retlen bytes of token information
735 * Failure: FALSE.
737 * NOTES
738 * See NtQueryInformationToken.
740 BOOL WINAPI
741 GetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
742 LPVOID tokeninfo, DWORD tokeninfolength, LPDWORD retlen )
744 TRACE("(%p, %s, %p, %d, %p):\n",
745 token,
746 (tokeninfoclass == TokenUser) ? "TokenUser" :
747 (tokeninfoclass == TokenGroups) ? "TokenGroups" :
748 (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
749 (tokeninfoclass == TokenOwner) ? "TokenOwner" :
750 (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
751 (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
752 (tokeninfoclass == TokenSource) ? "TokenSource" :
753 (tokeninfoclass == TokenType) ? "TokenType" :
754 (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
755 (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
756 (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
757 (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
758 (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
759 (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
760 (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
761 "Unknown",
762 tokeninfo, tokeninfolength, retlen);
763 return set_ntstatus( NtQueryInformationToken( token, tokeninfoclass, tokeninfo,
764 tokeninfolength, retlen));
767 /******************************************************************************
768 * SetTokenInformation [ADVAPI32.@]
770 * Set information for an access token.
772 * PARAMS
773 * token [I] Handle from OpenProcessToken() or OpenThreadToken()
774 * tokeninfoclass [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
775 * tokeninfo [I] Token information to set
776 * tokeninfolength [I] Length of tokeninfo
778 * RETURNS
779 * Success: TRUE. The information for the token is set to tokeninfo.
780 * Failure: FALSE.
782 BOOL WINAPI
783 SetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
784 LPVOID tokeninfo, DWORD tokeninfolength )
786 TRACE("(%p, %s, %p, %d): stub\n",
787 token,
788 (tokeninfoclass == TokenUser) ? "TokenUser" :
789 (tokeninfoclass == TokenGroups) ? "TokenGroups" :
790 (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
791 (tokeninfoclass == TokenOwner) ? "TokenOwner" :
792 (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
793 (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
794 (tokeninfoclass == TokenSource) ? "TokenSource" :
795 (tokeninfoclass == TokenType) ? "TokenType" :
796 (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
797 (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
798 (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
799 (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
800 (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
801 (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
802 (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
803 "Unknown",
804 tokeninfo, tokeninfolength);
806 return set_ntstatus( NtSetInformationToken( token, tokeninfoclass, tokeninfo, tokeninfolength ));
809 /*************************************************************************
810 * SetThreadToken [ADVAPI32.@]
812 * Assigns an 'impersonation token' to a thread so it can assume the
813 * security privileges of another thread or process. Can also remove
814 * a previously assigned token.
816 * PARAMS
817 * thread [O] Handle to thread to set the token for
818 * token [I] Token to set
820 * RETURNS
821 * Success: TRUE. The threads access token is set to token
822 * Failure: FALSE.
824 * NOTES
825 * Only supported on NT or higher. On Win9X this function does nothing.
826 * See SetTokenInformation.
828 BOOL WINAPI SetThreadToken(PHANDLE thread, HANDLE token)
830 return set_ntstatus( NtSetInformationThread( thread ? *thread : GetCurrentThread(),
831 ThreadImpersonationToken, &token, sizeof token ));
834 /*************************************************************************
835 * CreateRestrictedToken [ADVAPI32.@]
837 * Create a new more restricted token from an existing token.
839 * PARAMS
840 * baseToken [I] Token to base the new restricted token on
841 * flags [I] Options
842 * nDisableSids [I] Length of disableSids array
843 * disableSids [I] Array of SIDs to disable in the new token
844 * nDeletePrivs [I] Length of deletePrivs array
845 * deletePrivs [I] Array of privileges to delete in the new token
846 * nRestrictSids [I] Length of restrictSids array
847 * restrictSids [I] Array of SIDs to restrict in the new token
848 * newToken [O] Address where the new token is stored
850 * RETURNS
851 * Success: TRUE
852 * Failure: FALSE
854 BOOL WINAPI CreateRestrictedToken(
855 HANDLE baseToken,
856 DWORD flags,
857 DWORD nDisableSids,
858 PSID_AND_ATTRIBUTES disableSids,
859 DWORD nDeletePrivs,
860 PLUID_AND_ATTRIBUTES deletePrivs,
861 DWORD nRestrictSids,
862 PSID_AND_ATTRIBUTES restrictSids,
863 PHANDLE newToken)
865 TOKEN_TYPE type;
866 SECURITY_IMPERSONATION_LEVEL level = TokenImpersonationLevel;
867 DWORD size;
869 FIXME("(%p, 0x%x, %u, %p, %u, %p, %u, %p, %p): stub\n",
870 baseToken, flags, nDisableSids, disableSids,
871 nDeletePrivs, deletePrivs,
872 nRestrictSids, restrictSids,
873 newToken);
875 size = sizeof(type);
876 if (!GetTokenInformation( baseToken, TokenType, &type, size, &size )) return FALSE;
877 if (type == TokenImpersonation)
879 size = sizeof(level);
880 if (!GetTokenInformation( baseToken, TokenImpersonationLevel, &level, size, &size ))
881 return FALSE;
883 return DuplicateTokenEx( baseToken, MAXIMUM_ALLOWED, NULL, level, type, newToken );
886 /* ##############################
887 ###### SID FUNCTIONS ######
888 ##############################
891 /******************************************************************************
892 * AllocateAndInitializeSid [ADVAPI32.@]
894 * PARAMS
895 * pIdentifierAuthority []
896 * nSubAuthorityCount []
897 * nSubAuthority0 []
898 * nSubAuthority1 []
899 * nSubAuthority2 []
900 * nSubAuthority3 []
901 * nSubAuthority4 []
902 * nSubAuthority5 []
903 * nSubAuthority6 []
904 * nSubAuthority7 []
905 * pSid []
907 BOOL WINAPI
908 AllocateAndInitializeSid( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
909 BYTE nSubAuthorityCount,
910 DWORD nSubAuthority0, DWORD nSubAuthority1,
911 DWORD nSubAuthority2, DWORD nSubAuthority3,
912 DWORD nSubAuthority4, DWORD nSubAuthority5,
913 DWORD nSubAuthority6, DWORD nSubAuthority7,
914 PSID *pSid )
916 return set_ntstatus( RtlAllocateAndInitializeSid(
917 pIdentifierAuthority, nSubAuthorityCount,
918 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
919 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7,
920 pSid ));
923 /******************************************************************************
924 * FreeSid [ADVAPI32.@]
926 * PARAMS
927 * pSid []
929 PVOID WINAPI
930 FreeSid( PSID pSid )
932 RtlFreeSid(pSid);
933 return NULL; /* is documented like this */
936 /******************************************************************************
937 * CopySid [ADVAPI32.@]
939 * PARAMS
940 * nDestinationSidLength []
941 * pDestinationSid []
942 * pSourceSid []
944 BOOL WINAPI
945 CopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
947 return RtlCopySid(nDestinationSidLength, pDestinationSid, pSourceSid);
950 /******************************************************************************
951 * CreateWellKnownSid [ADVAPI32.@]
953 BOOL WINAPI
954 CreateWellKnownSid( WELL_KNOWN_SID_TYPE WellKnownSidType,
955 PSID DomainSid,
956 PSID pSid,
957 DWORD* cbSid)
959 unsigned int i;
960 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
962 if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
964 SetLastError(ERROR_INVALID_PARAMETER);
965 return FALSE;
968 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
969 if (WellKnownSids[i].Type == WellKnownSidType) {
970 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
972 if (*cbSid < length)
974 *cbSid = length;
975 SetLastError(ERROR_INSUFFICIENT_BUFFER);
976 return FALSE;
978 if (!pSid)
980 SetLastError(ERROR_INVALID_PARAMETER);
981 return FALSE;
983 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
984 *cbSid = length;
985 return TRUE;
989 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
991 SetLastError(ERROR_INVALID_PARAMETER);
992 return FALSE;
995 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
996 if (WellKnownRids[i].Type == WellKnownSidType) {
997 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
998 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
999 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
1001 if (*cbSid < output_sid_length)
1003 *cbSid = output_sid_length;
1004 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1005 return FALSE;
1007 if (!pSid)
1009 SetLastError(ERROR_INVALID_PARAMETER);
1010 return FALSE;
1012 CopyMemory(pSid, DomainSid, domain_sid_length);
1013 (*GetSidSubAuthorityCount(pSid))++;
1014 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
1015 *cbSid = output_sid_length;
1016 return TRUE;
1019 SetLastError(ERROR_INVALID_PARAMETER);
1020 return FALSE;
1023 /******************************************************************************
1024 * IsWellKnownSid [ADVAPI32.@]
1026 BOOL WINAPI
1027 IsWellKnownSid( PSID pSid, WELL_KNOWN_SID_TYPE WellKnownSidType )
1029 unsigned int i;
1030 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
1032 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
1033 if (WellKnownSids[i].Type == WellKnownSidType)
1034 if (EqualSid(pSid, (PSID)&(WellKnownSids[i].Sid.Revision)))
1035 return TRUE;
1037 return FALSE;
1040 BOOL WINAPI
1041 IsTokenRestricted( HANDLE TokenHandle )
1043 TOKEN_GROUPS *groups;
1044 DWORD size;
1045 NTSTATUS status;
1046 BOOL restricted;
1048 TRACE("(%p)\n", TokenHandle);
1050 status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, NULL, 0, &size);
1051 if (status != STATUS_BUFFER_TOO_SMALL)
1052 return FALSE;
1054 groups = heap_alloc(size);
1055 if (!groups)
1057 SetLastError(ERROR_OUTOFMEMORY);
1058 return FALSE;
1061 status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, groups, size, &size);
1062 if (status != STATUS_SUCCESS)
1064 heap_free(groups);
1065 return set_ntstatus(status);
1068 restricted = groups->GroupCount > 0;
1069 heap_free(groups);
1071 return restricted;
1074 /******************************************************************************
1075 * IsValidSid [ADVAPI32.@]
1077 * PARAMS
1078 * pSid []
1080 BOOL WINAPI
1081 IsValidSid( PSID pSid )
1083 return RtlValidSid( pSid );
1086 /******************************************************************************
1087 * EqualSid [ADVAPI32.@]
1089 * PARAMS
1090 * pSid1 []
1091 * pSid2 []
1093 BOOL WINAPI
1094 EqualSid( PSID pSid1, PSID pSid2 )
1096 BOOL ret = RtlEqualSid( pSid1, pSid2 );
1097 SetLastError(ERROR_SUCCESS);
1098 return ret;
1101 /******************************************************************************
1102 * EqualPrefixSid [ADVAPI32.@]
1104 BOOL WINAPI EqualPrefixSid (PSID pSid1, PSID pSid2)
1106 return RtlEqualPrefixSid(pSid1, pSid2);
1109 /******************************************************************************
1110 * GetSidLengthRequired [ADVAPI32.@]
1112 * PARAMS
1113 * nSubAuthorityCount []
1115 DWORD WINAPI
1116 GetSidLengthRequired( BYTE nSubAuthorityCount )
1118 return RtlLengthRequiredSid(nSubAuthorityCount);
1121 /******************************************************************************
1122 * InitializeSid [ADVAPI32.@]
1124 * PARAMS
1125 * pIdentifierAuthority []
1127 BOOL WINAPI
1128 InitializeSid (
1129 PSID pSid,
1130 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
1131 BYTE nSubAuthorityCount)
1133 return RtlInitializeSid(pSid, pIdentifierAuthority, nSubAuthorityCount);
1136 DWORD WINAPI
1137 GetEffectiveRightsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pAccessRights )
1139 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1141 *pAccessRights = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
1142 return 0;
1145 DWORD WINAPI
1146 GetEffectiveRightsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pAccessRights )
1148 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1150 return 1;
1153 /******************************************************************************
1154 * GetSidIdentifierAuthority [ADVAPI32.@]
1156 * PARAMS
1157 * pSid []
1159 PSID_IDENTIFIER_AUTHORITY WINAPI
1160 GetSidIdentifierAuthority( PSID pSid )
1162 return RtlIdentifierAuthoritySid(pSid);
1165 /******************************************************************************
1166 * GetSidSubAuthority [ADVAPI32.@]
1168 * PARAMS
1169 * pSid []
1170 * nSubAuthority []
1172 PDWORD WINAPI
1173 GetSidSubAuthority( PSID pSid, DWORD nSubAuthority )
1175 SetLastError(ERROR_SUCCESS);
1176 return RtlSubAuthoritySid(pSid, nSubAuthority);
1179 /******************************************************************************
1180 * GetSidSubAuthorityCount [ADVAPI32.@]
1182 * PARAMS
1183 * pSid []
1185 PUCHAR WINAPI
1186 GetSidSubAuthorityCount (PSID pSid)
1188 SetLastError(ERROR_SUCCESS);
1189 return RtlSubAuthorityCountSid(pSid);
1192 /******************************************************************************
1193 * GetLengthSid [ADVAPI32.@]
1195 * PARAMS
1196 * pSid []
1198 DWORD WINAPI
1199 GetLengthSid (PSID pSid)
1201 return RtlLengthSid(pSid);
1204 /* ##############################################
1205 ###### SECURITY DESCRIPTOR FUNCTIONS ######
1206 ##############################################
1209 /******************************************************************************
1210 * BuildSecurityDescriptorA [ADVAPI32.@]
1212 * Builds a SD from
1214 * PARAMS
1215 * pOwner [I]
1216 * pGroup [I]
1217 * cCountOfAccessEntries [I]
1218 * pListOfAccessEntries [I]
1219 * cCountOfAuditEntries [I]
1220 * pListofAuditEntries [I]
1221 * pOldSD [I]
1222 * lpdwBufferLength [I/O]
1223 * pNewSD [O]
1225 * RETURNS
1226 * Success: ERROR_SUCCESS
1227 * Failure: nonzero error code from Winerror.h
1229 DWORD WINAPI BuildSecurityDescriptorA(
1230 IN PTRUSTEEA pOwner,
1231 IN PTRUSTEEA pGroup,
1232 IN ULONG cCountOfAccessEntries,
1233 IN PEXPLICIT_ACCESSA pListOfAccessEntries,
1234 IN ULONG cCountOfAuditEntries,
1235 IN PEXPLICIT_ACCESSA pListofAuditEntries,
1236 IN PSECURITY_DESCRIPTOR pOldSD,
1237 IN OUT PULONG lpdwBufferLength,
1238 OUT PSECURITY_DESCRIPTOR* pNewSD)
1240 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1241 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1242 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1244 return ERROR_CALL_NOT_IMPLEMENTED;
1247 /******************************************************************************
1248 * BuildSecurityDescriptorW [ADVAPI32.@]
1250 * See BuildSecurityDescriptorA.
1252 DWORD WINAPI BuildSecurityDescriptorW(
1253 IN PTRUSTEEW pOwner,
1254 IN PTRUSTEEW pGroup,
1255 IN ULONG cCountOfAccessEntries,
1256 IN PEXPLICIT_ACCESSW pListOfAccessEntries,
1257 IN ULONG cCountOfAuditEntries,
1258 IN PEXPLICIT_ACCESSW pListofAuditEntries,
1259 IN PSECURITY_DESCRIPTOR pOldSD,
1260 IN OUT PULONG lpdwBufferLength,
1261 OUT PSECURITY_DESCRIPTOR* pNewSD)
1263 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1264 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1265 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1267 return ERROR_CALL_NOT_IMPLEMENTED;
1270 /******************************************************************************
1271 * InitializeSecurityDescriptor [ADVAPI32.@]
1273 * PARAMS
1274 * pDescr []
1275 * revision []
1277 BOOL WINAPI
1278 InitializeSecurityDescriptor( PSECURITY_DESCRIPTOR pDescr, DWORD revision )
1280 return set_ntstatus( RtlCreateSecurityDescriptor(pDescr, revision ));
1284 /******************************************************************************
1285 * MakeAbsoluteSD [ADVAPI32.@]
1287 BOOL WINAPI MakeAbsoluteSD (
1288 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1289 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1290 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
1291 OUT PACL pDacl,
1292 OUT LPDWORD lpdwDaclSize,
1293 OUT PACL pSacl,
1294 OUT LPDWORD lpdwSaclSize,
1295 OUT PSID pOwner,
1296 OUT LPDWORD lpdwOwnerSize,
1297 OUT PSID pPrimaryGroup,
1298 OUT LPDWORD lpdwPrimaryGroupSize)
1300 return set_ntstatus( RtlSelfRelativeToAbsoluteSD(pSelfRelativeSecurityDescriptor,
1301 pAbsoluteSecurityDescriptor,
1302 lpdwAbsoluteSecurityDescriptorSize,
1303 pDacl, lpdwDaclSize, pSacl, lpdwSaclSize,
1304 pOwner, lpdwOwnerSize,
1305 pPrimaryGroup, lpdwPrimaryGroupSize));
1308 /******************************************************************************
1309 * GetKernelObjectSecurity [ADVAPI32.@]
1311 BOOL WINAPI GetKernelObjectSecurity(
1312 HANDLE Handle,
1313 SECURITY_INFORMATION RequestedInformation,
1314 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1315 DWORD nLength,
1316 LPDWORD lpnLengthNeeded )
1318 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", Handle, RequestedInformation,
1319 pSecurityDescriptor, nLength, lpnLengthNeeded);
1321 return set_ntstatus( NtQuerySecurityObject(Handle, RequestedInformation, pSecurityDescriptor,
1322 nLength, lpnLengthNeeded ));
1325 /******************************************************************************
1326 * GetPrivateObjectSecurity [ADVAPI32.@]
1328 BOOL WINAPI GetPrivateObjectSecurity(
1329 PSECURITY_DESCRIPTOR ObjectDescriptor,
1330 SECURITY_INFORMATION SecurityInformation,
1331 PSECURITY_DESCRIPTOR ResultantDescriptor,
1332 DWORD DescriptorLength,
1333 PDWORD ReturnLength )
1335 SECURITY_DESCRIPTOR desc;
1336 BOOL defaulted, present;
1337 PACL pacl;
1338 PSID psid;
1340 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", ObjectDescriptor, SecurityInformation,
1341 ResultantDescriptor, DescriptorLength, ReturnLength);
1343 if (!InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION))
1344 return FALSE;
1346 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1348 if (!GetSecurityDescriptorOwner(ObjectDescriptor, &psid, &defaulted))
1349 return FALSE;
1350 SetSecurityDescriptorOwner(&desc, psid, defaulted);
1353 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1355 if (!GetSecurityDescriptorGroup(ObjectDescriptor, &psid, &defaulted))
1356 return FALSE;
1357 SetSecurityDescriptorGroup(&desc, psid, defaulted);
1360 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1362 if (!GetSecurityDescriptorDacl(ObjectDescriptor, &present, &pacl, &defaulted))
1363 return FALSE;
1364 SetSecurityDescriptorDacl(&desc, present, pacl, defaulted);
1367 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1369 if (!GetSecurityDescriptorSacl(ObjectDescriptor, &present, &pacl, &defaulted))
1370 return FALSE;
1371 SetSecurityDescriptorSacl(&desc, present, pacl, defaulted);
1374 *ReturnLength = DescriptorLength;
1375 return MakeSelfRelativeSD(&desc, ResultantDescriptor, ReturnLength);
1378 /******************************************************************************
1379 * GetSecurityDescriptorLength [ADVAPI32.@]
1381 DWORD WINAPI GetSecurityDescriptorLength( PSECURITY_DESCRIPTOR pDescr)
1383 return RtlLengthSecurityDescriptor(pDescr);
1386 /******************************************************************************
1387 * GetSecurityDescriptorOwner [ADVAPI32.@]
1389 * PARAMS
1390 * pOwner []
1391 * lpbOwnerDefaulted []
1393 BOOL WINAPI
1394 GetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pDescr, PSID *pOwner,
1395 LPBOOL lpbOwnerDefaulted )
1397 BOOLEAN defaulted;
1398 BOOL ret = set_ntstatus( RtlGetOwnerSecurityDescriptor( pDescr, pOwner, &defaulted ));
1399 *lpbOwnerDefaulted = defaulted;
1400 return ret;
1403 /******************************************************************************
1404 * SetSecurityDescriptorOwner [ADVAPI32.@]
1406 * PARAMS
1408 BOOL WINAPI SetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1409 PSID pOwner, BOOL bOwnerDefaulted)
1411 return set_ntstatus( RtlSetOwnerSecurityDescriptor(pSecurityDescriptor, pOwner, bOwnerDefaulted));
1413 /******************************************************************************
1414 * GetSecurityDescriptorGroup [ADVAPI32.@]
1416 BOOL WINAPI GetSecurityDescriptorGroup(
1417 PSECURITY_DESCRIPTOR SecurityDescriptor,
1418 PSID *Group,
1419 LPBOOL GroupDefaulted)
1421 BOOLEAN defaulted;
1422 BOOL ret = set_ntstatus( RtlGetGroupSecurityDescriptor(SecurityDescriptor, Group, &defaulted ));
1423 *GroupDefaulted = defaulted;
1424 return ret;
1426 /******************************************************************************
1427 * SetSecurityDescriptorGroup [ADVAPI32.@]
1429 BOOL WINAPI SetSecurityDescriptorGroup ( PSECURITY_DESCRIPTOR SecurityDescriptor,
1430 PSID Group, BOOL GroupDefaulted)
1432 return set_ntstatus( RtlSetGroupSecurityDescriptor( SecurityDescriptor, Group, GroupDefaulted));
1435 /******************************************************************************
1436 * IsValidSecurityDescriptor [ADVAPI32.@]
1438 * PARAMS
1439 * lpsecdesc []
1441 BOOL WINAPI
1442 IsValidSecurityDescriptor( PSECURITY_DESCRIPTOR SecurityDescriptor )
1444 return set_ntstatus( RtlValidSecurityDescriptor(SecurityDescriptor));
1447 /******************************************************************************
1448 * GetSecurityDescriptorDacl [ADVAPI32.@]
1450 BOOL WINAPI GetSecurityDescriptorDacl(
1451 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1452 OUT LPBOOL lpbDaclPresent,
1453 OUT PACL *pDacl,
1454 OUT LPBOOL lpbDaclDefaulted)
1456 BOOLEAN present, defaulted;
1457 BOOL ret = set_ntstatus( RtlGetDaclSecurityDescriptor(pSecurityDescriptor, &present, pDacl, &defaulted));
1458 *lpbDaclPresent = present;
1459 *lpbDaclDefaulted = defaulted;
1460 return ret;
1463 /******************************************************************************
1464 * SetSecurityDescriptorDacl [ADVAPI32.@]
1466 BOOL WINAPI
1467 SetSecurityDescriptorDacl (
1468 PSECURITY_DESCRIPTOR lpsd,
1469 BOOL daclpresent,
1470 PACL dacl,
1471 BOOL dacldefaulted )
1473 return set_ntstatus( RtlSetDaclSecurityDescriptor (lpsd, daclpresent, dacl, dacldefaulted ) );
1475 /******************************************************************************
1476 * GetSecurityDescriptorSacl [ADVAPI32.@]
1478 BOOL WINAPI GetSecurityDescriptorSacl(
1479 IN PSECURITY_DESCRIPTOR lpsd,
1480 OUT LPBOOL lpbSaclPresent,
1481 OUT PACL *pSacl,
1482 OUT LPBOOL lpbSaclDefaulted)
1484 BOOLEAN present, defaulted;
1485 BOOL ret = set_ntstatus( RtlGetSaclSecurityDescriptor(lpsd, &present, pSacl, &defaulted) );
1486 *lpbSaclPresent = present;
1487 *lpbSaclDefaulted = defaulted;
1488 return ret;
1491 /**************************************************************************
1492 * SetSecurityDescriptorSacl [ADVAPI32.@]
1494 BOOL WINAPI SetSecurityDescriptorSacl (
1495 PSECURITY_DESCRIPTOR lpsd,
1496 BOOL saclpresent,
1497 PACL lpsacl,
1498 BOOL sacldefaulted)
1500 return set_ntstatus (RtlSetSaclSecurityDescriptor(lpsd, saclpresent, lpsacl, sacldefaulted));
1502 /******************************************************************************
1503 * MakeSelfRelativeSD [ADVAPI32.@]
1505 * PARAMS
1506 * lpabssecdesc []
1507 * lpselfsecdesc []
1508 * lpbuflen []
1510 BOOL WINAPI
1511 MakeSelfRelativeSD(
1512 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1513 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1514 IN OUT LPDWORD lpdwBufferLength)
1516 return set_ntstatus( RtlMakeSelfRelativeSD( pAbsoluteSecurityDescriptor,
1517 pSelfRelativeSecurityDescriptor, lpdwBufferLength));
1520 /******************************************************************************
1521 * GetSecurityDescriptorControl [ADVAPI32.@]
1524 BOOL WINAPI GetSecurityDescriptorControl ( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1525 PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD lpdwRevision)
1527 return set_ntstatus( RtlGetControlSecurityDescriptor(pSecurityDescriptor,pControl,lpdwRevision));
1530 /******************************************************************************
1531 * SetSecurityDescriptorControl [ADVAPI32.@]
1533 BOOL WINAPI SetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1534 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1535 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet )
1537 return set_ntstatus( RtlSetControlSecurityDescriptor(
1538 pSecurityDescriptor, ControlBitsOfInterest, ControlBitsToSet ) );
1541 /* ##############################
1542 ###### ACL FUNCTIONS ######
1543 ##############################
1546 /*************************************************************************
1547 * InitializeAcl [ADVAPI32.@]
1549 BOOL WINAPI InitializeAcl(PACL acl, DWORD size, DWORD rev)
1551 return set_ntstatus( RtlCreateAcl(acl, size, rev));
1554 BOOL WINAPI ImpersonateNamedPipeClient( HANDLE hNamedPipe )
1556 IO_STATUS_BLOCK io_block;
1558 TRACE("(%p)\n", hNamedPipe);
1560 return set_ntstatus( NtFsControlFile(hNamedPipe, NULL, NULL, NULL,
1561 &io_block, FSCTL_PIPE_IMPERSONATE, NULL, 0, NULL, 0) );
1564 /******************************************************************************
1565 * AddAccessAllowedAce [ADVAPI32.@]
1567 BOOL WINAPI AddAccessAllowedAce(
1568 IN OUT PACL pAcl,
1569 IN DWORD dwAceRevision,
1570 IN DWORD AccessMask,
1571 IN PSID pSid)
1573 return set_ntstatus(RtlAddAccessAllowedAce(pAcl, dwAceRevision, AccessMask, pSid));
1576 /******************************************************************************
1577 * AddAccessAllowedAceEx [ADVAPI32.@]
1579 BOOL WINAPI AddAccessAllowedAceEx(
1580 IN OUT PACL pAcl,
1581 IN DWORD dwAceRevision,
1582 IN DWORD AceFlags,
1583 IN DWORD AccessMask,
1584 IN PSID pSid)
1586 return set_ntstatus(RtlAddAccessAllowedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1589 /******************************************************************************
1590 * AddAccessDeniedAce [ADVAPI32.@]
1592 BOOL WINAPI AddAccessDeniedAce(
1593 IN OUT PACL pAcl,
1594 IN DWORD dwAceRevision,
1595 IN DWORD AccessMask,
1596 IN PSID pSid)
1598 return set_ntstatus(RtlAddAccessDeniedAce(pAcl, dwAceRevision, AccessMask, pSid));
1601 /******************************************************************************
1602 * AddAccessDeniedAceEx [ADVAPI32.@]
1604 BOOL WINAPI AddAccessDeniedAceEx(
1605 IN OUT PACL pAcl,
1606 IN DWORD dwAceRevision,
1607 IN DWORD AceFlags,
1608 IN DWORD AccessMask,
1609 IN PSID pSid)
1611 return set_ntstatus(RtlAddAccessDeniedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1614 /******************************************************************************
1615 * AddAce [ADVAPI32.@]
1617 BOOL WINAPI AddAce(
1618 IN OUT PACL pAcl,
1619 IN DWORD dwAceRevision,
1620 IN DWORD dwStartingAceIndex,
1621 LPVOID pAceList,
1622 DWORD nAceListLength)
1624 return set_ntstatus(RtlAddAce(pAcl, dwAceRevision, dwStartingAceIndex, pAceList, nAceListLength));
1627 BOOL WINAPI AddMandatoryAce(ACL *acl, DWORD ace_revision, DWORD ace_flags, DWORD mandatory_policy, PSID label_sid)
1629 FIXME("%p %x %x %x %p - stub\n", acl, ace_revision, ace_flags, mandatory_policy, label_sid);
1630 return FALSE;
1633 /******************************************************************************
1634 * DeleteAce [ADVAPI32.@]
1636 BOOL WINAPI DeleteAce(PACL pAcl, DWORD dwAceIndex)
1638 return set_ntstatus(RtlDeleteAce(pAcl, dwAceIndex));
1641 /******************************************************************************
1642 * FindFirstFreeAce [ADVAPI32.@]
1644 BOOL WINAPI FindFirstFreeAce(IN PACL pAcl, LPVOID * pAce)
1646 return RtlFirstFreeAce(pAcl, (PACE_HEADER *)pAce);
1649 /******************************************************************************
1650 * GetAce [ADVAPI32.@]
1652 BOOL WINAPI GetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1654 return set_ntstatus(RtlGetAce(pAcl, dwAceIndex, pAce));
1657 /******************************************************************************
1658 * GetAclInformation [ADVAPI32.@]
1660 BOOL WINAPI GetAclInformation(
1661 PACL pAcl,
1662 LPVOID pAclInformation,
1663 DWORD nAclInformationLength,
1664 ACL_INFORMATION_CLASS dwAclInformationClass)
1666 return set_ntstatus(RtlQueryInformationAcl(pAcl, pAclInformation,
1667 nAclInformationLength, dwAclInformationClass));
1670 /******************************************************************************
1671 * IsValidAcl [ADVAPI32.@]
1673 BOOL WINAPI IsValidAcl(IN PACL pAcl)
1675 return RtlValidAcl(pAcl);
1678 /* ##############################
1679 ###### MISC FUNCTIONS ######
1680 ##############################
1683 /******************************************************************************
1684 * AllocateLocallyUniqueId [ADVAPI32.@]
1686 * PARAMS
1687 * lpLuid []
1689 BOOL WINAPI AllocateLocallyUniqueId( PLUID lpLuid )
1691 return set_ntstatus(NtAllocateLocallyUniqueId(lpLuid));
1694 static const WCHAR SE_CREATE_TOKEN_NAME_W[] =
1695 { 'S','e','C','r','e','a','t','e','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 };
1696 static const WCHAR SE_ASSIGNPRIMARYTOKEN_NAME_W[] =
1697 { '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 };
1698 static const WCHAR SE_LOCK_MEMORY_NAME_W[] =
1699 { 'S','e','L','o','c','k','M','e','m','o','r','y','P','r','i','v','i','l','e','g','e',0 };
1700 static const WCHAR SE_INCREASE_QUOTA_NAME_W[] =
1701 { '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 };
1702 static const WCHAR SE_MACHINE_ACCOUNT_NAME_W[] =
1703 { '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 };
1704 static const WCHAR SE_TCB_NAME_W[] =
1705 { 'S','e','T','c','b','P','r','i','v','i','l','e','g','e',0 };
1706 static const WCHAR SE_SECURITY_NAME_W[] =
1707 { 'S','e','S','e','c','u','r','i','t','y','P','r','i','v','i','l','e','g','e',0 };
1708 static const WCHAR SE_TAKE_OWNERSHIP_NAME_W[] =
1709 { '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 };
1710 static const WCHAR SE_LOAD_DRIVER_NAME_W[] =
1711 { 'S','e','L','o','a','d','D','r','i','v','e','r','P','r','i','v','i','l','e','g','e',0 };
1712 static const WCHAR SE_SYSTEM_PROFILE_NAME_W[] =
1713 { '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 };
1714 static const WCHAR SE_SYSTEMTIME_NAME_W[] =
1715 { 'S','e','S','y','s','t','e','m','t','i','m','e','P','r','i','v','i','l','e','g','e',0 };
1716 static const WCHAR SE_PROF_SINGLE_PROCESS_NAME_W[] =
1717 { '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 };
1718 static const WCHAR SE_INC_BASE_PRIORITY_NAME_W[] =
1719 { '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 };
1720 static const WCHAR SE_CREATE_PAGEFILE_NAME_W[] =
1721 { '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 };
1722 static const WCHAR SE_CREATE_PERMANENT_NAME_W[] =
1723 { '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 };
1724 static const WCHAR SE_BACKUP_NAME_W[] =
1725 { 'S','e','B','a','c','k','u','p','P','r','i','v','i','l','e','g','e',0 };
1726 static const WCHAR SE_RESTORE_NAME_W[] =
1727 { 'S','e','R','e','s','t','o','r','e','P','r','i','v','i','l','e','g','e',0 };
1728 static const WCHAR SE_SHUTDOWN_NAME_W[] =
1729 { 'S','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 };
1730 static const WCHAR SE_DEBUG_NAME_W[] =
1731 { 'S','e','D','e','b','u','g','P','r','i','v','i','l','e','g','e',0 };
1732 static const WCHAR SE_AUDIT_NAME_W[] =
1733 { 'S','e','A','u','d','i','t','P','r','i','v','i','l','e','g','e',0 };
1734 static const WCHAR SE_SYSTEM_ENVIRONMENT_NAME_W[] =
1735 { '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 };
1736 static const WCHAR SE_CHANGE_NOTIFY_NAME_W[] =
1737 { 'S','e','C','h','a','n','g','e','N','o','t','i','f','y','P','r','i','v','i','l','e','g','e',0 };
1738 static const WCHAR SE_REMOTE_SHUTDOWN_NAME_W[] =
1739 { '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 };
1740 static const WCHAR SE_UNDOCK_NAME_W[] =
1741 { 'S','e','U','n','d','o','c','k','P','r','i','v','i','l','e','g','e',0 };
1742 static const WCHAR SE_SYNC_AGENT_NAME_W[] =
1743 { 'S','e','S','y','n','c','A','g','e','n','t','P','r','i','v','i','l','e','g','e',0 };
1744 static const WCHAR SE_ENABLE_DELEGATION_NAME_W[] =
1745 { '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 };
1746 static const WCHAR SE_MANAGE_VOLUME_NAME_W[] =
1747 { 'S','e','M','a','n','a','g','e','V','o','l','u','m','e','P','r','i','v','i','l','e','g','e',0 };
1748 static const WCHAR SE_IMPERSONATE_NAME_W[] =
1749 { 'S','e','I','m','p','e','r','s','o','n','a','t','e','P','r','i','v','i','l','e','g','e',0 };
1750 static const WCHAR SE_CREATE_GLOBAL_NAME_W[] =
1751 { 'S','e','C','r','e','a','t','e','G','l','o','b','a','l','P','r','i','v','i','l','e','g','e',0 };
1753 static const WCHAR * const WellKnownPrivNames[SE_MAX_WELL_KNOWN_PRIVILEGE + 1] =
1755 NULL,
1756 NULL,
1757 SE_CREATE_TOKEN_NAME_W,
1758 SE_ASSIGNPRIMARYTOKEN_NAME_W,
1759 SE_LOCK_MEMORY_NAME_W,
1760 SE_INCREASE_QUOTA_NAME_W,
1761 SE_MACHINE_ACCOUNT_NAME_W,
1762 SE_TCB_NAME_W,
1763 SE_SECURITY_NAME_W,
1764 SE_TAKE_OWNERSHIP_NAME_W,
1765 SE_LOAD_DRIVER_NAME_W,
1766 SE_SYSTEM_PROFILE_NAME_W,
1767 SE_SYSTEMTIME_NAME_W,
1768 SE_PROF_SINGLE_PROCESS_NAME_W,
1769 SE_INC_BASE_PRIORITY_NAME_W,
1770 SE_CREATE_PAGEFILE_NAME_W,
1771 SE_CREATE_PERMANENT_NAME_W,
1772 SE_BACKUP_NAME_W,
1773 SE_RESTORE_NAME_W,
1774 SE_SHUTDOWN_NAME_W,
1775 SE_DEBUG_NAME_W,
1776 SE_AUDIT_NAME_W,
1777 SE_SYSTEM_ENVIRONMENT_NAME_W,
1778 SE_CHANGE_NOTIFY_NAME_W,
1779 SE_REMOTE_SHUTDOWN_NAME_W,
1780 SE_UNDOCK_NAME_W,
1781 SE_SYNC_AGENT_NAME_W,
1782 SE_ENABLE_DELEGATION_NAME_W,
1783 SE_MANAGE_VOLUME_NAME_W,
1784 SE_IMPERSONATE_NAME_W,
1785 SE_CREATE_GLOBAL_NAME_W,
1788 /******************************************************************************
1789 * LookupPrivilegeValueW [ADVAPI32.@]
1791 * See LookupPrivilegeValueA.
1793 BOOL WINAPI
1794 LookupPrivilegeValueW( LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid )
1796 UINT i;
1798 TRACE("%s,%s,%p\n",debugstr_w(lpSystemName), debugstr_w(lpName), lpLuid);
1800 if (!ADVAPI_IsLocalComputer(lpSystemName))
1802 SetLastError(RPC_S_SERVER_UNAVAILABLE);
1803 return FALSE;
1805 if (!lpName)
1807 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1808 return FALSE;
1810 for( i=SE_MIN_WELL_KNOWN_PRIVILEGE; i<=SE_MAX_WELL_KNOWN_PRIVILEGE; i++ )
1812 if( !WellKnownPrivNames[i] )
1813 continue;
1814 if( strcmpiW( WellKnownPrivNames[i], lpName) )
1815 continue;
1816 lpLuid->LowPart = i;
1817 lpLuid->HighPart = 0;
1818 TRACE( "%s -> %08x-%08x\n",debugstr_w( lpSystemName ),
1819 lpLuid->HighPart, lpLuid->LowPart );
1820 return TRUE;
1822 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1823 return FALSE;
1826 /******************************************************************************
1827 * LookupPrivilegeValueA [ADVAPI32.@]
1829 * Retrieves LUID used on a system to represent the privilege name.
1831 * PARAMS
1832 * lpSystemName [I] Name of the system
1833 * lpName [I] Name of the privilege
1834 * lpLuid [O] Destination for the resulting LUID
1836 * RETURNS
1837 * Success: TRUE. lpLuid contains the requested LUID.
1838 * Failure: FALSE.
1840 BOOL WINAPI
1841 LookupPrivilegeValueA( LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid )
1843 UNICODE_STRING lpSystemNameW;
1844 UNICODE_STRING lpNameW;
1845 BOOL ret;
1847 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1848 RtlCreateUnicodeStringFromAsciiz(&lpNameW,lpName);
1849 ret = LookupPrivilegeValueW(lpSystemNameW.Buffer, lpNameW.Buffer, lpLuid);
1850 RtlFreeUnicodeString(&lpNameW);
1851 RtlFreeUnicodeString(&lpSystemNameW);
1852 return ret;
1855 BOOL WINAPI LookupPrivilegeDisplayNameA( LPCSTR lpSystemName, LPCSTR lpName, LPSTR lpDisplayName,
1856 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1858 FIXME("%s %s %s %p %p - stub\n", debugstr_a(lpSystemName), debugstr_a(lpName),
1859 debugstr_a(lpDisplayName), cchDisplayName, lpLanguageId);
1861 return FALSE;
1864 BOOL WINAPI LookupPrivilegeDisplayNameW( LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName,
1865 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1867 FIXME("%s %s %s %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpName),
1868 debugstr_w(lpDisplayName), cchDisplayName, lpLanguageId);
1870 return FALSE;
1873 /******************************************************************************
1874 * LookupPrivilegeNameA [ADVAPI32.@]
1876 * See LookupPrivilegeNameW.
1878 BOOL WINAPI
1879 LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName,
1880 LPDWORD cchName)
1882 UNICODE_STRING lpSystemNameW;
1883 BOOL ret;
1884 DWORD wLen = 0;
1886 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
1888 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1889 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
1890 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1892 LPWSTR lpNameW = heap_alloc(wLen * sizeof(WCHAR));
1894 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
1895 &wLen);
1896 if (ret)
1898 /* Windows crashes if cchName is NULL, so will I */
1899 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
1900 *cchName, NULL, NULL);
1902 if (len == 0)
1904 /* WideCharToMultiByte failed */
1905 ret = FALSE;
1907 else if (len > *cchName)
1909 *cchName = len;
1910 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1911 ret = FALSE;
1913 else
1915 /* WideCharToMultiByte succeeded, output length needs to be
1916 * length not including NULL terminator
1918 *cchName = len - 1;
1921 heap_free(lpNameW);
1923 RtlFreeUnicodeString(&lpSystemNameW);
1924 return ret;
1927 /******************************************************************************
1928 * LookupPrivilegeNameW [ADVAPI32.@]
1930 * Retrieves the privilege name referred to by the LUID lpLuid.
1932 * PARAMS
1933 * lpSystemName [I] Name of the system
1934 * lpLuid [I] Privilege value
1935 * lpName [O] Name of the privilege
1936 * cchName [I/O] Number of characters in lpName.
1938 * RETURNS
1939 * Success: TRUE. lpName contains the name of the privilege whose value is
1940 * *lpLuid.
1941 * Failure: FALSE.
1943 * REMARKS
1944 * Only well-known privilege names (those defined in winnt.h) can be retrieved
1945 * using this function.
1946 * If the length of lpName is too small, on return *cchName will contain the
1947 * number of WCHARs needed to contain the privilege, including the NULL
1948 * terminator, and GetLastError will return ERROR_INSUFFICIENT_BUFFER.
1949 * On success, *cchName will contain the number of characters stored in
1950 * lpName, NOT including the NULL terminator.
1952 BOOL WINAPI
1953 LookupPrivilegeNameW( LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName,
1954 LPDWORD cchName)
1956 size_t privNameLen;
1958 TRACE("%s,%p,%p,%p\n",debugstr_w(lpSystemName), lpLuid, lpName, cchName);
1960 if (!ADVAPI_IsLocalComputer(lpSystemName))
1962 SetLastError(RPC_S_SERVER_UNAVAILABLE);
1963 return FALSE;
1965 if (lpLuid->HighPart || (lpLuid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
1966 lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
1968 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1969 return FALSE;
1971 privNameLen = strlenW(WellKnownPrivNames[lpLuid->LowPart]);
1972 /* Windows crashes if cchName is NULL, so will I */
1973 if (*cchName <= privNameLen)
1975 *cchName = privNameLen + 1;
1976 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1977 return FALSE;
1979 else
1981 strcpyW(lpName, WellKnownPrivNames[lpLuid->LowPart]);
1982 *cchName = privNameLen;
1983 return TRUE;
1987 /******************************************************************************
1988 * GetFileSecurityA [ADVAPI32.@]
1990 * Obtains Specified information about the security of a file or directory.
1992 * PARAMS
1993 * lpFileName [I] Name of the file to get info for
1994 * RequestedInformation [I] SE_ flags from "winnt.h"
1995 * pSecurityDescriptor [O] Destination for security information
1996 * nLength [I] Length of pSecurityDescriptor
1997 * lpnLengthNeeded [O] Destination for length of returned security information
1999 * RETURNS
2000 * Success: TRUE. pSecurityDescriptor contains the requested information.
2001 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
2003 * NOTES
2004 * The information returned is constrained by the callers access rights and
2005 * privileges.
2007 BOOL WINAPI
2008 GetFileSecurityA( LPCSTR lpFileName,
2009 SECURITY_INFORMATION RequestedInformation,
2010 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2011 DWORD nLength, LPDWORD lpnLengthNeeded )
2013 BOOL r;
2014 LPWSTR name;
2016 name = SERV_dup(lpFileName);
2017 r = GetFileSecurityW( name, RequestedInformation, pSecurityDescriptor,
2018 nLength, lpnLengthNeeded );
2019 heap_free( name );
2021 return r;
2024 /******************************************************************************
2025 * GetFileSecurityW [ADVAPI32.@]
2027 * See GetFileSecurityA.
2029 BOOL WINAPI
2030 GetFileSecurityW( LPCWSTR lpFileName,
2031 SECURITY_INFORMATION RequestedInformation,
2032 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2033 DWORD nLength, LPDWORD lpnLengthNeeded )
2035 HANDLE hfile;
2036 NTSTATUS status;
2037 DWORD access = 0, err;
2039 TRACE("(%s,%d,%p,%d,%p)\n", debugstr_w(lpFileName),
2040 RequestedInformation, pSecurityDescriptor,
2041 nLength, lpnLengthNeeded);
2043 if (RequestedInformation & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|
2044 DACL_SECURITY_INFORMATION))
2045 access |= READ_CONTROL;
2046 if (RequestedInformation & SACL_SECURITY_INFORMATION)
2047 access |= ACCESS_SYSTEM_SECURITY;
2049 err = get_security_file( lpFileName, access, &hfile);
2050 if (err)
2052 SetLastError(err);
2053 return FALSE;
2056 status = NtQuerySecurityObject( hfile, RequestedInformation, pSecurityDescriptor,
2057 nLength, lpnLengthNeeded );
2058 CloseHandle( hfile );
2059 return set_ntstatus( status );
2063 /******************************************************************************
2064 * LookupAccountSidA [ADVAPI32.@]
2066 BOOL WINAPI
2067 LookupAccountSidA(
2068 IN LPCSTR system,
2069 IN PSID sid,
2070 OUT LPSTR account,
2071 IN OUT LPDWORD accountSize,
2072 OUT LPSTR domain,
2073 IN OUT LPDWORD domainSize,
2074 OUT PSID_NAME_USE name_use )
2076 DWORD len;
2077 BOOL r;
2078 LPWSTR systemW;
2079 LPWSTR accountW = NULL;
2080 LPWSTR domainW = NULL;
2081 DWORD accountSizeW = *accountSize;
2082 DWORD domainSizeW = *domainSize;
2084 systemW = SERV_dup(system);
2085 if (account)
2086 accountW = heap_alloc( accountSizeW * sizeof(WCHAR) );
2087 if (domain)
2088 domainW = heap_alloc( domainSizeW * sizeof(WCHAR) );
2090 r = LookupAccountSidW( systemW, sid, accountW, &accountSizeW, domainW, &domainSizeW, name_use );
2092 if (r) {
2093 if (accountW && *accountSize) {
2094 len = WideCharToMultiByte( CP_ACP, 0, accountW, -1, NULL, 0, NULL, NULL );
2095 WideCharToMultiByte( CP_ACP, 0, accountW, -1, account, len, NULL, NULL );
2096 *accountSize = len;
2097 } else
2098 *accountSize = accountSizeW + 1;
2100 if (domainW && *domainSize) {
2101 len = WideCharToMultiByte( CP_ACP, 0, domainW, -1, NULL, 0, NULL, NULL );
2102 WideCharToMultiByte( CP_ACP, 0, domainW, -1, domain, len, NULL, NULL );
2103 *domainSize = len;
2104 } else
2105 *domainSize = domainSizeW + 1;
2107 else
2109 *accountSize = accountSizeW + 1;
2110 *domainSize = domainSizeW + 1;
2113 heap_free( systemW );
2114 heap_free( accountW );
2115 heap_free( domainW );
2117 return r;
2120 /******************************************************************************
2121 * LookupAccountSidW [ADVAPI32.@]
2123 * PARAMS
2124 * system []
2125 * sid []
2126 * account []
2127 * accountSize []
2128 * domain []
2129 * domainSize []
2130 * name_use []
2133 BOOL WINAPI
2134 LookupAccountSidW(
2135 IN LPCWSTR system,
2136 IN PSID sid,
2137 OUT LPWSTR account,
2138 IN OUT LPDWORD accountSize,
2139 OUT LPWSTR domain,
2140 IN OUT LPDWORD domainSize,
2141 OUT PSID_NAME_USE name_use )
2143 unsigned int i, j;
2144 const WCHAR * ac = NULL;
2145 const WCHAR * dm = NULL;
2146 SID_NAME_USE use = 0;
2147 LPWSTR computer_name = NULL;
2148 LPWSTR account_name = NULL;
2150 TRACE("(%s,sid=%s,%p,%p(%u),%p,%p(%u),%p)\n",
2151 debugstr_w(system),debugstr_sid(sid),
2152 account,accountSize,accountSize?*accountSize:0,
2153 domain,domainSize,domainSize?*domainSize:0,
2154 name_use);
2156 if (!ADVAPI_IsLocalComputer(system)) {
2157 FIXME("Only local computer supported!\n");
2158 SetLastError(RPC_S_SERVER_UNAVAILABLE);
2159 return FALSE;
2162 /* check the well known SIDs first */
2163 for (i = 0; i <= 60; i++) {
2164 if (IsWellKnownSid(sid, i)) {
2165 for (j = 0; j < (sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0])); j++) {
2166 if (ACCOUNT_SIDS[j].type == i) {
2167 ac = ACCOUNT_SIDS[j].account;
2168 dm = ACCOUNT_SIDS[j].domain;
2169 use = ACCOUNT_SIDS[j].name_use;
2172 break;
2176 if (dm == NULL) {
2177 MAX_SID local;
2179 /* check for the local computer next */
2180 if (ADVAPI_GetComputerSid(&local)) {
2181 DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
2182 BOOL result;
2184 computer_name = heap_alloc(size * sizeof(WCHAR));
2185 result = GetComputerNameW(computer_name, &size);
2187 if (result) {
2188 if (EqualSid(sid, &local)) {
2189 dm = computer_name;
2190 ac = Blank;
2191 use = 3;
2192 } else {
2193 local.SubAuthorityCount++;
2195 if (EqualPrefixSid(sid, &local)) {
2196 dm = computer_name;
2197 use = 1;
2198 switch (((MAX_SID *)sid)->SubAuthority[4]) {
2199 case DOMAIN_USER_RID_ADMIN:
2200 ac = Administrator;
2201 break;
2202 case DOMAIN_USER_RID_GUEST:
2203 ac = Guest;
2204 break;
2205 case DOMAIN_GROUP_RID_ADMINS:
2206 ac = Domain_Admins;
2207 break;
2208 case DOMAIN_GROUP_RID_USERS:
2209 ac = Domain_Users;
2210 break;
2211 case DOMAIN_GROUP_RID_GUESTS:
2212 ac = Domain_Guests;
2213 break;
2214 case DOMAIN_GROUP_RID_COMPUTERS:
2215 ac = Domain_Computers;
2216 break;
2217 case DOMAIN_GROUP_RID_CONTROLLERS:
2218 ac = Domain_Controllers;
2219 break;
2220 case DOMAIN_GROUP_RID_CERT_ADMINS:
2221 ac = Cert_Publishers;
2222 break;
2223 case DOMAIN_GROUP_RID_SCHEMA_ADMINS:
2224 ac = Schema_Admins;
2225 break;
2226 case DOMAIN_GROUP_RID_ENTERPRISE_ADMINS:
2227 ac = Enterprise_Admins;
2228 break;
2229 case DOMAIN_GROUP_RID_POLICY_ADMINS:
2230 ac = Group_Policy_Creator_Owners;
2231 break;
2232 case DOMAIN_ALIAS_RID_RAS_SERVERS:
2233 ac = RAS_and_IAS_Servers;
2234 break;
2235 case 1000: /* first user account */
2236 size = UNLEN + 1;
2237 account_name = heap_alloc(size * sizeof(WCHAR));
2238 if (GetUserNameW(account_name, &size))
2239 ac = account_name;
2240 else
2241 dm = NULL;
2243 break;
2244 default:
2245 dm = NULL;
2246 break;
2254 if (dm) {
2255 DWORD ac_len = lstrlenW(ac);
2256 DWORD dm_len = lstrlenW(dm);
2257 BOOL status = TRUE;
2259 if (*accountSize > ac_len) {
2260 if (account)
2261 lstrcpyW(account, ac);
2263 if (*domainSize > dm_len) {
2264 if (domain)
2265 lstrcpyW(domain, dm);
2267 if ((*accountSize && *accountSize < ac_len) ||
2268 (!account && !*accountSize && ac_len) ||
2269 (*domainSize && *domainSize < dm_len) ||
2270 (!domain && !*domainSize && dm_len))
2272 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2273 status = FALSE;
2275 if (*domainSize)
2276 *domainSize = dm_len;
2277 else
2278 *domainSize = dm_len + 1;
2279 if (*accountSize)
2280 *accountSize = ac_len;
2281 else
2282 *accountSize = ac_len + 1;
2284 heap_free(account_name);
2285 heap_free(computer_name);
2286 if (status) *name_use = use;
2287 return status;
2290 heap_free(account_name);
2291 heap_free(computer_name);
2292 SetLastError(ERROR_NONE_MAPPED);
2293 return FALSE;
2296 /******************************************************************************
2297 * SetFileSecurityA [ADVAPI32.@]
2299 * See SetFileSecurityW.
2301 BOOL WINAPI SetFileSecurityA( LPCSTR lpFileName,
2302 SECURITY_INFORMATION RequestedInformation,
2303 PSECURITY_DESCRIPTOR pSecurityDescriptor)
2305 BOOL r;
2306 LPWSTR name;
2308 name = SERV_dup(lpFileName);
2309 r = SetFileSecurityW( name, RequestedInformation, pSecurityDescriptor );
2310 heap_free( name );
2312 return r;
2315 /******************************************************************************
2316 * SetFileSecurityW [ADVAPI32.@]
2318 * Sets the security of a file or directory.
2320 * PARAMS
2321 * lpFileName []
2322 * RequestedInformation []
2323 * pSecurityDescriptor []
2325 * RETURNS
2326 * Success: TRUE.
2327 * Failure: FALSE.
2329 BOOL WINAPI
2330 SetFileSecurityW( LPCWSTR lpFileName,
2331 SECURITY_INFORMATION RequestedInformation,
2332 PSECURITY_DESCRIPTOR pSecurityDescriptor )
2334 HANDLE file;
2335 DWORD access = 0, err;
2336 NTSTATUS status;
2338 TRACE("(%s, 0x%x, %p)\n", debugstr_w(lpFileName), RequestedInformation,
2339 pSecurityDescriptor );
2341 if (RequestedInformation & OWNER_SECURITY_INFORMATION ||
2342 RequestedInformation & GROUP_SECURITY_INFORMATION)
2343 access |= WRITE_OWNER;
2344 if (RequestedInformation & SACL_SECURITY_INFORMATION)
2345 access |= ACCESS_SYSTEM_SECURITY;
2346 if (RequestedInformation & DACL_SECURITY_INFORMATION)
2347 access |= WRITE_DAC;
2349 err = get_security_file( lpFileName, access, &file);
2350 if (err)
2352 SetLastError(err);
2353 return FALSE;
2356 status = NtSetSecurityObject( file, RequestedInformation, pSecurityDescriptor );
2357 CloseHandle( file );
2358 return set_ntstatus( status );
2361 /******************************************************************************
2362 * QueryWindows31FilesMigration [ADVAPI32.@]
2364 * PARAMS
2365 * x1 []
2367 BOOL WINAPI
2368 QueryWindows31FilesMigration( DWORD x1 )
2370 FIXME("(%d):stub\n",x1);
2371 return TRUE;
2374 /******************************************************************************
2375 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
2377 * PARAMS
2378 * x1 []
2379 * x2 []
2380 * x3 []
2381 * x4 []
2383 BOOL WINAPI
2384 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
2385 DWORD x4 )
2387 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
2388 return TRUE;
2391 /******************************************************************************
2392 * NotifyBootConfigStatus [ADVAPI32.@]
2394 * PARAMS
2395 * x1 []
2397 BOOL WINAPI
2398 NotifyBootConfigStatus( BOOL x1 )
2400 FIXME("(0x%08d):stub\n",x1);
2401 return TRUE;
2404 /******************************************************************************
2405 * RevertToSelf [ADVAPI32.@]
2407 * Ends the impersonation of a user.
2409 * PARAMS
2410 * void []
2412 * RETURNS
2413 * Success: TRUE.
2414 * Failure: FALSE.
2416 BOOL WINAPI
2417 RevertToSelf( void )
2419 HANDLE Token = NULL;
2420 return set_ntstatus( NtSetInformationThread( GetCurrentThread(),
2421 ThreadImpersonationToken, &Token, sizeof(Token) ) );
2424 /******************************************************************************
2425 * ImpersonateSelf [ADVAPI32.@]
2427 * Makes an impersonation token that represents the process user and assigns
2428 * to the current thread.
2430 * PARAMS
2431 * ImpersonationLevel [I] Level at which to impersonate.
2433 * RETURNS
2434 * Success: TRUE.
2435 * Failure: FALSE.
2437 BOOL WINAPI
2438 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
2440 return set_ntstatus( RtlImpersonateSelf( ImpersonationLevel ) );
2443 /******************************************************************************
2444 * ImpersonateLoggedOnUser [ADVAPI32.@]
2446 BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken)
2448 DWORD size;
2449 NTSTATUS Status;
2450 HANDLE ImpersonationToken;
2451 TOKEN_TYPE Type;
2452 static BOOL warn = TRUE;
2454 if (warn)
2456 FIXME( "(%p)\n", hToken );
2457 warn = FALSE;
2459 if (!GetTokenInformation( hToken, TokenType, &Type,
2460 sizeof(TOKEN_TYPE), &size ))
2461 return FALSE;
2463 if (Type == TokenPrimary)
2465 OBJECT_ATTRIBUTES ObjectAttributes;
2467 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
2469 Status = NtDuplicateToken( hToken,
2470 TOKEN_IMPERSONATE | TOKEN_QUERY,
2471 &ObjectAttributes,
2472 SecurityImpersonation,
2473 TokenImpersonation,
2474 &ImpersonationToken );
2475 if (Status != STATUS_SUCCESS)
2477 ERR( "NtDuplicateToken failed with error 0x%08x\n", Status );
2478 SetLastError( RtlNtStatusToDosError( Status ) );
2479 return FALSE;
2482 else
2483 ImpersonationToken = hToken;
2485 Status = NtSetInformationThread( GetCurrentThread(),
2486 ThreadImpersonationToken,
2487 &ImpersonationToken,
2488 sizeof(ImpersonationToken) );
2490 if (Type == TokenPrimary)
2491 NtClose( ImpersonationToken );
2493 if (Status != STATUS_SUCCESS)
2495 ERR( "NtSetInformationThread failed with error 0x%08x\n", Status );
2496 SetLastError( RtlNtStatusToDosError( Status ) );
2497 return FALSE;
2500 return TRUE;
2503 /******************************************************************************
2504 * ImpersonateAnonymousToken [ADVAPI32.@]
2506 BOOL WINAPI ImpersonateAnonymousToken( HANDLE thread )
2508 TRACE("(%p)\n", thread);
2509 return set_ntstatus( NtImpersonateAnonymousToken( thread ) );
2512 /******************************************************************************
2513 * AccessCheck [ADVAPI32.@]
2515 BOOL WINAPI
2516 AccessCheck(
2517 PSECURITY_DESCRIPTOR SecurityDescriptor,
2518 HANDLE ClientToken,
2519 DWORD DesiredAccess,
2520 PGENERIC_MAPPING GenericMapping,
2521 PPRIVILEGE_SET PrivilegeSet,
2522 LPDWORD PrivilegeSetLength,
2523 LPDWORD GrantedAccess,
2524 LPBOOL AccessStatus)
2526 NTSTATUS access_status;
2527 BOOL ret = set_ntstatus( NtAccessCheck(SecurityDescriptor, ClientToken, DesiredAccess,
2528 GenericMapping, PrivilegeSet, PrivilegeSetLength,
2529 GrantedAccess, &access_status) );
2530 if (ret) *AccessStatus = set_ntstatus( access_status );
2531 return ret;
2535 /******************************************************************************
2536 * AccessCheckByType [ADVAPI32.@]
2538 BOOL WINAPI AccessCheckByType(
2539 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2540 PSID PrincipalSelfSid,
2541 HANDLE ClientToken,
2542 DWORD DesiredAccess,
2543 POBJECT_TYPE_LIST ObjectTypeList,
2544 DWORD ObjectTypeListLength,
2545 PGENERIC_MAPPING GenericMapping,
2546 PPRIVILEGE_SET PrivilegeSet,
2547 LPDWORD PrivilegeSetLength,
2548 LPDWORD GrantedAccess,
2549 LPBOOL AccessStatus)
2551 FIXME("stub\n");
2553 *AccessStatus = TRUE;
2555 return !*AccessStatus;
2558 /******************************************************************************
2559 * MapGenericMask [ADVAPI32.@]
2561 * Maps generic access rights into specific access rights according to the
2562 * supplied mapping.
2564 * PARAMS
2565 * AccessMask [I/O] Access rights.
2566 * GenericMapping [I] The mapping between generic and specific rights.
2568 * RETURNS
2569 * Nothing.
2571 VOID WINAPI MapGenericMask( PDWORD AccessMask, PGENERIC_MAPPING GenericMapping )
2573 RtlMapGenericMask( AccessMask, GenericMapping );
2576 /*************************************************************************
2577 * SetKernelObjectSecurity [ADVAPI32.@]
2579 BOOL WINAPI SetKernelObjectSecurity (
2580 IN HANDLE Handle,
2581 IN SECURITY_INFORMATION SecurityInformation,
2582 IN PSECURITY_DESCRIPTOR SecurityDescriptor )
2584 return set_ntstatus (NtSetSecurityObject (Handle, SecurityInformation, SecurityDescriptor));
2588 /******************************************************************************
2589 * AddAuditAccessAce [ADVAPI32.@]
2591 BOOL WINAPI AddAuditAccessAce(
2592 IN OUT PACL pAcl,
2593 IN DWORD dwAceRevision,
2594 IN DWORD dwAccessMask,
2595 IN PSID pSid,
2596 IN BOOL bAuditSuccess,
2597 IN BOOL bAuditFailure)
2599 return set_ntstatus( RtlAddAuditAccessAce(pAcl, dwAceRevision, dwAccessMask, pSid,
2600 bAuditSuccess, bAuditFailure) );
2603 /******************************************************************************
2604 * AddAuditAccessAce [ADVAPI32.@]
2606 BOOL WINAPI AddAuditAccessAceEx(
2607 IN OUT PACL pAcl,
2608 IN DWORD dwAceRevision,
2609 IN DWORD dwAceFlags,
2610 IN DWORD dwAccessMask,
2611 IN PSID pSid,
2612 IN BOOL bAuditSuccess,
2613 IN BOOL bAuditFailure)
2615 return set_ntstatus( RtlAddAuditAccessAceEx(pAcl, dwAceRevision, dwAceFlags, dwAccessMask, pSid,
2616 bAuditSuccess, bAuditFailure) );
2619 /******************************************************************************
2620 * LookupAccountNameA [ADVAPI32.@]
2622 BOOL WINAPI
2623 LookupAccountNameA(
2624 IN LPCSTR system,
2625 IN LPCSTR account,
2626 OUT PSID sid,
2627 OUT LPDWORD cbSid,
2628 LPSTR ReferencedDomainName,
2629 IN OUT LPDWORD cbReferencedDomainName,
2630 OUT PSID_NAME_USE name_use )
2632 BOOL ret;
2633 UNICODE_STRING lpSystemW;
2634 UNICODE_STRING lpAccountW;
2635 LPWSTR lpReferencedDomainNameW = NULL;
2637 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, system);
2638 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, account);
2640 if (ReferencedDomainName)
2641 lpReferencedDomainNameW = heap_alloc(*cbReferencedDomainName * sizeof(WCHAR));
2643 ret = LookupAccountNameW(lpSystemW.Buffer, lpAccountW.Buffer, sid, cbSid, lpReferencedDomainNameW,
2644 cbReferencedDomainName, name_use);
2646 if (ret && lpReferencedDomainNameW)
2648 WideCharToMultiByte(CP_ACP, 0, lpReferencedDomainNameW, -1,
2649 ReferencedDomainName, *cbReferencedDomainName+1, NULL, NULL);
2652 RtlFreeUnicodeString(&lpSystemW);
2653 RtlFreeUnicodeString(&lpAccountW);
2654 heap_free(lpReferencedDomainNameW);
2656 return ret;
2659 /******************************************************************************
2660 * lookup_user_account_name
2662 static BOOL lookup_user_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2663 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2665 char buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
2666 DWORD len = sizeof(buffer);
2667 HANDLE token;
2668 BOOL ret;
2669 PSID pSid;
2670 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
2671 DWORD nameLen;
2673 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
2675 if (GetLastError() != ERROR_NO_TOKEN) return FALSE;
2676 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) return FALSE;
2679 ret = GetTokenInformation(token, TokenUser, buffer, len, &len);
2680 CloseHandle( token );
2682 if (!ret) return FALSE;
2684 pSid = ((TOKEN_USER *)buffer)->User.Sid;
2686 if (Sid != NULL && (*cbSid >= GetLengthSid(pSid)))
2687 CopySid(*cbSid, Sid, pSid);
2688 if (*cbSid < GetLengthSid(pSid))
2690 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2691 ret = FALSE;
2693 *cbSid = GetLengthSid(pSid);
2695 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
2696 if (!GetComputerNameW(domainName, &nameLen))
2698 domainName[0] = 0;
2699 nameLen = 0;
2701 if (*cchReferencedDomainName <= nameLen || !ret)
2703 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2704 nameLen += 1;
2705 ret = FALSE;
2707 else if (ReferencedDomainName)
2708 strcpyW(ReferencedDomainName, domainName);
2710 *cchReferencedDomainName = nameLen;
2712 if (ret)
2713 *peUse = SidTypeUser;
2715 return ret;
2718 /******************************************************************************
2719 * lookup_computer_account_name
2721 static BOOL lookup_computer_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2722 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2724 MAX_SID local;
2725 BOOL ret;
2726 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
2727 DWORD nameLen;
2729 if ((ret = ADVAPI_GetComputerSid(&local)))
2731 if (Sid != NULL && (*cbSid >= GetLengthSid(&local)))
2732 CopySid(*cbSid, Sid, &local);
2733 if (*cbSid < GetLengthSid(&local))
2735 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2736 ret = FALSE;
2738 *cbSid = GetLengthSid(&local);
2741 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
2742 if (!GetComputerNameW(domainName, &nameLen))
2744 domainName[0] = 0;
2745 nameLen = 0;
2747 if (*cchReferencedDomainName <= nameLen || !ret)
2749 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2750 nameLen += 1;
2751 ret = FALSE;
2753 else if (ReferencedDomainName)
2754 strcpyW(ReferencedDomainName, domainName);
2756 *cchReferencedDomainName = nameLen;
2758 if (ret)
2759 *peUse = SidTypeDomain;
2761 return ret;
2764 static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STRING *account,
2765 LSA_UNICODE_STRING *domain )
2767 WCHAR *p = str->Buffer + str->Length / sizeof(WCHAR) - 1;
2769 while (p > str->Buffer && *p != '\\') p--;
2771 if (*p == '\\')
2773 domain->Buffer = str->Buffer;
2774 domain->Length = (p - str->Buffer) * sizeof(WCHAR);
2776 account->Buffer = p + 1;
2777 account->Length = str->Length - ((p - str->Buffer + 1) * sizeof(WCHAR));
2779 else
2781 domain->Buffer = NULL;
2782 domain->Length = 0;
2784 account->Buffer = str->Buffer;
2785 account->Length = str->Length;
2789 static BOOL match_domain( ULONG idx, const LSA_UNICODE_STRING *domain )
2791 ULONG len = strlenW( ACCOUNT_SIDS[idx].domain );
2793 if (len == domain->Length / sizeof(WCHAR) && !strncmpiW( domain->Buffer, ACCOUNT_SIDS[idx].domain, len ))
2794 return TRUE;
2796 return FALSE;
2799 static BOOL match_account( ULONG idx, const LSA_UNICODE_STRING *account )
2801 ULONG len = strlenW( ACCOUNT_SIDS[idx].account );
2803 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].account, len ))
2804 return TRUE;
2806 if (ACCOUNT_SIDS[idx].alias)
2808 len = strlenW( ACCOUNT_SIDS[idx].alias );
2809 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].alias, len ))
2810 return TRUE;
2812 return FALSE;
2816 * Helper function for LookupAccountNameW
2818 BOOL lookup_local_wellknown_name( const LSA_UNICODE_STRING *account_and_domain,
2819 PSID Sid, LPDWORD cbSid,
2820 LPWSTR ReferencedDomainName,
2821 LPDWORD cchReferencedDomainName,
2822 PSID_NAME_USE peUse, BOOL *handled )
2824 PSID pSid;
2825 LSA_UNICODE_STRING account, domain;
2826 BOOL ret = TRUE;
2827 ULONG i;
2829 *handled = FALSE;
2830 split_domain_account( account_and_domain, &account, &domain );
2832 for (i = 0; i < sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0]); i++)
2834 /* check domain first */
2835 if (domain.Buffer && !match_domain( i, &domain )) continue;
2837 if (match_account( i, &account ))
2839 DWORD len, sidLen = SECURITY_MAX_SID_SIZE;
2841 if (!(pSid = heap_alloc( sidLen ))) return FALSE;
2843 if ((ret = CreateWellKnownSid( ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen )))
2845 if (*cbSid < sidLen)
2847 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2848 ret = FALSE;
2850 else if (Sid)
2852 CopySid(*cbSid, Sid, pSid);
2854 *cbSid = sidLen;
2857 len = strlenW( ACCOUNT_SIDS[i].domain );
2858 if (*cchReferencedDomainName <= len || !ret)
2860 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2861 len++;
2862 ret = FALSE;
2864 else if (ReferencedDomainName)
2866 strcpyW( ReferencedDomainName, ACCOUNT_SIDS[i].domain );
2869 *cchReferencedDomainName = len;
2870 if (ret)
2871 *peUse = ACCOUNT_SIDS[i].name_use;
2873 heap_free(pSid);
2874 *handled = TRUE;
2875 return ret;
2878 return ret;
2881 BOOL lookup_local_user_name( const LSA_UNICODE_STRING *account_and_domain,
2882 PSID Sid, LPDWORD cbSid,
2883 LPWSTR ReferencedDomainName,
2884 LPDWORD cchReferencedDomainName,
2885 PSID_NAME_USE peUse, BOOL *handled )
2887 DWORD nameLen;
2888 LPWSTR userName = NULL;
2889 LSA_UNICODE_STRING account, domain;
2890 BOOL ret = TRUE;
2892 *handled = FALSE;
2893 split_domain_account( account_and_domain, &account, &domain );
2895 /* Let the current Unix user id masquerade as first Windows user account */
2897 nameLen = UNLEN + 1;
2898 if (!(userName = heap_alloc( nameLen * sizeof(WCHAR) ))) return FALSE;
2900 if (domain.Buffer)
2902 /* check to make sure this account is on this computer */
2903 if (GetComputerNameW( userName, &nameLen ) &&
2904 (domain.Length / sizeof(WCHAR) != nameLen || strncmpW( domain.Buffer, userName, nameLen )))
2906 SetLastError(ERROR_NONE_MAPPED);
2907 ret = FALSE;
2909 nameLen = UNLEN + 1;
2912 if (GetUserNameW( userName, &nameLen ) &&
2913 account.Length / sizeof(WCHAR) == nameLen - 1 && !strncmpW( account.Buffer, userName, nameLen - 1 ))
2915 ret = lookup_user_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2916 *handled = TRUE;
2918 else
2920 nameLen = UNLEN + 1;
2921 if (GetComputerNameW( userName, &nameLen ) &&
2922 account.Length / sizeof(WCHAR) == nameLen && !strncmpW( account.Buffer, userName , nameLen ))
2924 ret = lookup_computer_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2925 *handled = TRUE;
2929 heap_free(userName);
2930 return ret;
2933 /******************************************************************************
2934 * LookupAccountNameW [ADVAPI32.@]
2936 BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
2937 LPDWORD cbSid, LPWSTR ReferencedDomainName,
2938 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2940 BOOL ret, handled;
2941 LSA_UNICODE_STRING account;
2943 TRACE("%s %s %p %p %p %p %p\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
2944 Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
2946 if (!ADVAPI_IsLocalComputer( lpSystemName ))
2948 FIXME("remote computer not supported\n");
2949 SetLastError( RPC_S_SERVER_UNAVAILABLE );
2950 return FALSE;
2953 if (!lpAccountName || !strcmpW( lpAccountName, Blank ))
2955 lpAccountName = BUILTIN;
2958 RtlInitUnicodeString( &account, lpAccountName );
2960 /* Check well known SIDs first */
2961 ret = lookup_local_wellknown_name( &account, Sid, cbSid, ReferencedDomainName,
2962 cchReferencedDomainName, peUse, &handled );
2963 if (handled)
2964 return ret;
2966 /* Check user names */
2967 ret = lookup_local_user_name( &account, Sid, cbSid, ReferencedDomainName,
2968 cchReferencedDomainName, peUse, &handled);
2969 if (handled)
2970 return ret;
2972 SetLastError( ERROR_NONE_MAPPED );
2973 return FALSE;
2976 /******************************************************************************
2977 * PrivilegeCheck [ADVAPI32.@]
2979 BOOL WINAPI PrivilegeCheck( HANDLE ClientToken, PPRIVILEGE_SET RequiredPrivileges, LPBOOL pfResult)
2981 BOOL ret;
2982 BOOLEAN Result;
2984 TRACE("%p %p %p\n", ClientToken, RequiredPrivileges, pfResult);
2986 ret = set_ntstatus (NtPrivilegeCheck (ClientToken, RequiredPrivileges, &Result));
2987 if (ret)
2988 *pfResult = Result;
2989 return ret;
2992 /******************************************************************************
2993 * AccessCheckAndAuditAlarmA [ADVAPI32.@]
2995 BOOL WINAPI AccessCheckAndAuditAlarmA(LPCSTR Subsystem, LPVOID HandleId, LPSTR ObjectTypeName,
2996 LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
2997 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
2998 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
3000 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_a(Subsystem),
3001 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName),
3002 SecurityDescriptor, DesiredAccess, GenericMapping,
3003 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
3004 return TRUE;
3007 /******************************************************************************
3008 * AccessCheckAndAuditAlarmW [ADVAPI32.@]
3010 BOOL WINAPI AccessCheckAndAuditAlarmW(LPCWSTR Subsystem, LPVOID HandleId, LPWSTR ObjectTypeName,
3011 LPWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
3012 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
3013 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
3015 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_w(Subsystem),
3016 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName),
3017 SecurityDescriptor, DesiredAccess, GenericMapping,
3018 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
3019 return TRUE;
3022 BOOL WINAPI ObjectCloseAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3024 FIXME("stub (%s,%p,%x)\n", debugstr_a(SubsystemName), HandleId, GenerateOnClose);
3026 return TRUE;
3029 BOOL WINAPI ObjectCloseAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3031 FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
3033 return TRUE;
3036 BOOL WINAPI ObjectDeleteAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3038 FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
3040 return TRUE;
3043 BOOL WINAPI ObjectOpenAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName,
3044 LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3045 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3046 LPBOOL GenerateOnClose)
3048 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_a(SubsystemName),
3049 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName), pSecurityDescriptor,
3050 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3051 GenerateOnClose);
3053 return TRUE;
3056 BOOL WINAPI ObjectOpenAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName,
3057 LPWSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3058 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3059 LPBOOL GenerateOnClose)
3061 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_w(SubsystemName),
3062 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName), pSecurityDescriptor,
3063 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3064 GenerateOnClose);
3066 return TRUE;
3069 BOOL WINAPI ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3070 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3072 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_a(SubsystemName), HandleId, ClientToken,
3073 DesiredAccess, Privileges, AccessGranted);
3075 return TRUE;
3078 BOOL WINAPI ObjectPrivilegeAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3079 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3081 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_w(SubsystemName), HandleId, ClientToken,
3082 DesiredAccess, Privileges, AccessGranted);
3084 return TRUE;
3087 BOOL WINAPI PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken,
3088 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3090 FIXME("stub (%s,%s,%p,%p,%x)\n", debugstr_a(SubsystemName), debugstr_a(ServiceName),
3091 ClientToken, Privileges, AccessGranted);
3093 return TRUE;
3096 BOOL WINAPI PrivilegedServiceAuditAlarmW( LPCWSTR SubsystemName, LPCWSTR ServiceName, HANDLE ClientToken,
3097 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3099 FIXME("stub %s,%s,%p,%p,%x)\n", debugstr_w(SubsystemName), debugstr_w(ServiceName),
3100 ClientToken, Privileges, AccessGranted);
3102 return TRUE;
3105 /******************************************************************************
3106 * GetSecurityInfo [ADVAPI32.@]
3108 * Retrieves a copy of the security descriptor associated with an object.
3110 * PARAMS
3111 * hObject [I] A handle for the object.
3112 * ObjectType [I] The type of object.
3113 * SecurityInfo [I] A bitmask indicating what info to retrieve.
3114 * ppsidOwner [O] If non-null, receives a pointer to the owner SID.
3115 * ppsidGroup [O] If non-null, receives a pointer to the group SID.
3116 * ppDacl [O] If non-null, receives a pointer to the DACL.
3117 * ppSacl [O] If non-null, receives a pointer to the SACL.
3118 * ppSecurityDescriptor [O] Receives a pointer to the security descriptor,
3119 * which must be freed with LocalFree.
3121 * RETURNS
3122 * ERROR_SUCCESS if all's well, and a WIN32 error code otherwise.
3124 DWORD WINAPI GetSecurityInfo(
3125 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3126 SECURITY_INFORMATION SecurityInfo, PSID *ppsidOwner,
3127 PSID *ppsidGroup, PACL *ppDacl, PACL *ppSacl,
3128 PSECURITY_DESCRIPTOR *ppSecurityDescriptor
3131 PSECURITY_DESCRIPTOR sd;
3132 NTSTATUS status;
3133 ULONG n1, n2;
3134 BOOL present, defaulted;
3136 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
3137 if (!(ppsidOwner||ppsidGroup||ppDacl||ppSacl||ppSecurityDescriptor)) return ERROR_INVALID_PARAMETER;
3139 /* If no descriptor, we have to check that there's a pointer for the requested information */
3140 if( !ppSecurityDescriptor && (
3141 ((SecurityInfo & OWNER_SECURITY_INFORMATION) && !ppsidOwner)
3142 || ((SecurityInfo & GROUP_SECURITY_INFORMATION) && !ppsidGroup)
3143 || ((SecurityInfo & DACL_SECURITY_INFORMATION) && !ppDacl)
3144 || ((SecurityInfo & SACL_SECURITY_INFORMATION) && !ppSacl) ))
3145 return ERROR_INVALID_PARAMETER;
3147 switch (ObjectType)
3149 case SE_SERVICE:
3150 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, NULL, 0, &n1);
3151 break;
3152 default:
3153 status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1);
3154 break;
3156 if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS)
3157 return RtlNtStatusToDosError(status);
3159 sd = LocalAlloc(0, n1);
3160 if (!sd)
3161 return ERROR_NOT_ENOUGH_MEMORY;
3163 switch (ObjectType)
3165 case SE_SERVICE:
3166 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, sd, n1, &n2);
3167 break;
3168 default:
3169 status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2);
3170 break;
3172 if (status != STATUS_SUCCESS)
3174 LocalFree(sd);
3175 return RtlNtStatusToDosError(status);
3178 if (ppsidOwner)
3180 *ppsidOwner = NULL;
3181 GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted);
3183 if (ppsidGroup)
3185 *ppsidGroup = NULL;
3186 GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted);
3188 if (ppDacl)
3190 *ppDacl = NULL;
3191 GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted);
3193 if (ppSacl)
3195 *ppSacl = NULL;
3196 GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted);
3198 if (ppSecurityDescriptor)
3199 *ppSecurityDescriptor = sd;
3201 /* The security descriptor (sd) cannot be freed if ppSecurityDescriptor is
3202 * NULL, because native happily returns the SIDs and ACLs that are requested
3203 * in this case.
3206 return ERROR_SUCCESS;
3209 /******************************************************************************
3210 * GetSecurityInfoExA [ADVAPI32.@]
3212 DWORD WINAPI GetSecurityInfoExA(
3213 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3214 SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
3215 LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
3216 PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
3219 FIXME("stub!\n");
3220 return ERROR_BAD_PROVIDER;
3223 /******************************************************************************
3224 * GetSecurityInfoExW [ADVAPI32.@]
3226 DWORD WINAPI GetSecurityInfoExW(
3227 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3228 SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
3229 LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList,
3230 PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
3233 FIXME("stub!\n");
3234 return ERROR_BAD_PROVIDER;
3237 /******************************************************************************
3238 * BuildExplicitAccessWithNameA [ADVAPI32.@]
3240 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
3241 LPSTR pTrusteeName, DWORD AccessPermissions,
3242 ACCESS_MODE AccessMode, DWORD Inheritance )
3244 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_a(pTrusteeName),
3245 AccessPermissions, AccessMode, Inheritance);
3247 pExplicitAccess->grfAccessPermissions = AccessPermissions;
3248 pExplicitAccess->grfAccessMode = AccessMode;
3249 pExplicitAccess->grfInheritance = Inheritance;
3251 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3252 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3253 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3254 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3255 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3258 /******************************************************************************
3259 * BuildExplicitAccessWithNameW [ADVAPI32.@]
3261 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
3262 LPWSTR pTrusteeName, DWORD AccessPermissions,
3263 ACCESS_MODE AccessMode, DWORD Inheritance )
3265 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_w(pTrusteeName),
3266 AccessPermissions, AccessMode, Inheritance);
3268 pExplicitAccess->grfAccessPermissions = AccessPermissions;
3269 pExplicitAccess->grfAccessMode = AccessMode;
3270 pExplicitAccess->grfInheritance = Inheritance;
3272 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3273 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3274 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3275 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3276 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3279 /******************************************************************************
3280 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
3282 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
3283 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
3284 LPSTR InheritedObjectTypeName, LPSTR Name )
3286 DWORD ObjectsPresent = 0;
3288 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3289 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
3291 /* Fill the OBJECTS_AND_NAME structure */
3292 pObjName->ObjectType = ObjectType;
3293 if (ObjectTypeName != NULL)
3295 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3298 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3299 if (InheritedObjectTypeName != NULL)
3301 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3304 pObjName->ObjectsPresent = ObjectsPresent;
3305 pObjName->ptstrName = Name;
3307 /* Fill the TRUSTEE structure */
3308 pTrustee->pMultipleTrustee = NULL;
3309 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3310 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3311 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3312 pTrustee->ptstrName = (LPSTR)pObjName;
3315 /******************************************************************************
3316 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
3318 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
3319 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
3320 LPWSTR InheritedObjectTypeName, LPWSTR Name )
3322 DWORD ObjectsPresent = 0;
3324 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3325 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
3327 /* Fill the OBJECTS_AND_NAME structure */
3328 pObjName->ObjectType = ObjectType;
3329 if (ObjectTypeName != NULL)
3331 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3334 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3335 if (InheritedObjectTypeName != NULL)
3337 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3340 pObjName->ObjectsPresent = ObjectsPresent;
3341 pObjName->ptstrName = Name;
3343 /* Fill the TRUSTEE structure */
3344 pTrustee->pMultipleTrustee = NULL;
3345 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3346 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3347 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3348 pTrustee->ptstrName = (LPWSTR)pObjName;
3351 /******************************************************************************
3352 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
3354 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
3355 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3357 DWORD ObjectsPresent = 0;
3359 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3361 /* Fill the OBJECTS_AND_SID structure */
3362 if (pObjectGuid != NULL)
3364 pObjSid->ObjectTypeGuid = *pObjectGuid;
3365 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3367 else
3369 ZeroMemory(&pObjSid->ObjectTypeGuid,
3370 sizeof(GUID));
3373 if (pInheritedObjectGuid != NULL)
3375 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3376 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3378 else
3380 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3381 sizeof(GUID));
3384 pObjSid->ObjectsPresent = ObjectsPresent;
3385 pObjSid->pSid = pSid;
3387 /* Fill the TRUSTEE structure */
3388 pTrustee->pMultipleTrustee = NULL;
3389 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3390 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3391 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3392 pTrustee->ptstrName = (LPSTR) pObjSid;
3395 /******************************************************************************
3396 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
3398 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
3399 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3401 DWORD ObjectsPresent = 0;
3403 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3405 /* Fill the OBJECTS_AND_SID structure */
3406 if (pObjectGuid != NULL)
3408 pObjSid->ObjectTypeGuid = *pObjectGuid;
3409 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3411 else
3413 ZeroMemory(&pObjSid->ObjectTypeGuid,
3414 sizeof(GUID));
3417 if (pInheritedObjectGuid != NULL)
3419 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3420 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3422 else
3424 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3425 sizeof(GUID));
3428 pObjSid->ObjectsPresent = ObjectsPresent;
3429 pObjSid->pSid = pSid;
3431 /* Fill the TRUSTEE structure */
3432 pTrustee->pMultipleTrustee = NULL;
3433 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3434 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3435 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3436 pTrustee->ptstrName = (LPWSTR) pObjSid;
3439 /******************************************************************************
3440 * BuildTrusteeWithSidA [ADVAPI32.@]
3442 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA 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 * BuildTrusteeWithSidW [ADVAPI32.@]
3456 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
3458 TRACE("%p %p\n", pTrustee, pSid);
3460 pTrustee->pMultipleTrustee = NULL;
3461 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3462 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3463 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3464 pTrustee->ptstrName = pSid;
3467 /******************************************************************************
3468 * BuildTrusteeWithNameA [ADVAPI32.@]
3470 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
3472 TRACE("%p %s\n", pTrustee, debugstr_a(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 * BuildTrusteeWithNameW [ADVAPI32.@]
3484 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
3486 TRACE("%p %s\n", pTrustee, debugstr_w(name) );
3488 pTrustee->pMultipleTrustee = NULL;
3489 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3490 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3491 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3492 pTrustee->ptstrName = name;
3495 /******************************************************************************
3496 * GetTrusteeFormA [ADVAPI32.@]
3498 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee)
3500 TRACE("(%p)\n", pTrustee);
3502 if (!pTrustee)
3503 return TRUSTEE_BAD_FORM;
3505 return pTrustee->TrusteeForm;
3508 /******************************************************************************
3509 * GetTrusteeFormW [ADVAPI32.@]
3511 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee)
3513 TRACE("(%p)\n", pTrustee);
3515 if (!pTrustee)
3516 return TRUSTEE_BAD_FORM;
3518 return pTrustee->TrusteeForm;
3521 /******************************************************************************
3522 * GetTrusteeNameA [ADVAPI32.@]
3524 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee)
3526 TRACE("(%p)\n", pTrustee);
3528 if (!pTrustee)
3529 return NULL;
3531 return pTrustee->ptstrName;
3534 /******************************************************************************
3535 * GetTrusteeNameW [ADVAPI32.@]
3537 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee)
3539 TRACE("(%p)\n", pTrustee);
3541 if (!pTrustee)
3542 return NULL;
3544 return pTrustee->ptstrName;
3547 /******************************************************************************
3548 * GetTrusteeTypeA [ADVAPI32.@]
3550 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee)
3552 TRACE("(%p)\n", pTrustee);
3554 if (!pTrustee)
3555 return TRUSTEE_IS_UNKNOWN;
3557 return pTrustee->TrusteeType;
3560 /******************************************************************************
3561 * GetTrusteeTypeW [ADVAPI32.@]
3563 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee)
3565 TRACE("(%p)\n", pTrustee);
3567 if (!pTrustee)
3568 return TRUSTEE_IS_UNKNOWN;
3570 return pTrustee->TrusteeType;
3573 BOOL WINAPI SetAclInformation( PACL pAcl, LPVOID pAclInformation,
3574 DWORD nAclInformationLength,
3575 ACL_INFORMATION_CLASS dwAclInformationClass )
3577 FIXME("%p %p 0x%08x 0x%08x - stub\n", pAcl, pAclInformation,
3578 nAclInformationLength, dwAclInformationClass);
3580 return TRUE;
3583 static DWORD trustee_name_A_to_W(TRUSTEE_FORM form, char *trustee_nameA, WCHAR **ptrustee_nameW)
3585 switch (form)
3587 case TRUSTEE_IS_NAME:
3589 *ptrustee_nameW = SERV_dup(trustee_nameA);
3590 return ERROR_SUCCESS;
3592 case TRUSTEE_IS_OBJECTS_AND_NAME:
3594 OBJECTS_AND_NAME_A *objA = (OBJECTS_AND_NAME_A *)trustee_nameA;
3595 OBJECTS_AND_NAME_W *objW = NULL;
3597 if (objA)
3599 if (!(objW = heap_alloc( sizeof(OBJECTS_AND_NAME_W) )))
3600 return ERROR_NOT_ENOUGH_MEMORY;
3602 objW->ObjectsPresent = objA->ObjectsPresent;
3603 objW->ObjectType = objA->ObjectType;
3604 objW->ObjectTypeName = SERV_dup(objA->ObjectTypeName);
3605 objW->InheritedObjectTypeName = SERV_dup(objA->InheritedObjectTypeName);
3606 objW->ptstrName = SERV_dup(objA->ptstrName);
3609 *ptrustee_nameW = (WCHAR *)objW;
3610 return ERROR_SUCCESS;
3612 /* These forms do not require conversion. */
3613 case TRUSTEE_IS_SID:
3614 case TRUSTEE_IS_OBJECTS_AND_SID:
3615 *ptrustee_nameW = (WCHAR *)trustee_nameA;
3616 return ERROR_SUCCESS;
3617 default:
3618 return ERROR_INVALID_PARAMETER;
3622 static void free_trustee_name(TRUSTEE_FORM form, WCHAR *trustee_nameW)
3624 switch (form)
3626 case TRUSTEE_IS_NAME:
3627 heap_free( trustee_nameW );
3628 break;
3629 case TRUSTEE_IS_OBJECTS_AND_NAME:
3631 OBJECTS_AND_NAME_W *objW = (OBJECTS_AND_NAME_W *)trustee_nameW;
3633 if (objW)
3635 heap_free( objW->ptstrName );
3636 heap_free( objW->InheritedObjectTypeName );
3637 heap_free( objW->ObjectTypeName );
3638 heap_free( objW );
3641 break;
3643 /* Other forms did not require allocation, so no freeing is necessary. */
3644 default:
3645 break;
3649 /******************************************************************************
3650 * SetEntriesInAclA [ADVAPI32.@]
3652 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
3653 PACL OldAcl, PACL* NewAcl )
3655 DWORD err = ERROR_SUCCESS;
3656 EXPLICIT_ACCESSW *pEntriesW;
3657 UINT alloc_index, free_index;
3659 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3661 if (NewAcl)
3662 *NewAcl = NULL;
3664 if (!count && !OldAcl)
3665 return ERROR_SUCCESS;
3667 pEntriesW = heap_alloc( count * sizeof(EXPLICIT_ACCESSW) );
3668 if (!pEntriesW)
3669 return ERROR_NOT_ENOUGH_MEMORY;
3671 for (alloc_index = 0; alloc_index < count; ++alloc_index)
3673 pEntriesW[alloc_index].grfAccessPermissions = pEntries[alloc_index].grfAccessPermissions;
3674 pEntriesW[alloc_index].grfAccessMode = pEntries[alloc_index].grfAccessMode;
3675 pEntriesW[alloc_index].grfInheritance = pEntries[alloc_index].grfInheritance;
3676 pEntriesW[alloc_index].Trustee.pMultipleTrustee = NULL; /* currently not supported */
3677 pEntriesW[alloc_index].Trustee.MultipleTrusteeOperation = pEntries[alloc_index].Trustee.MultipleTrusteeOperation;
3678 pEntriesW[alloc_index].Trustee.TrusteeForm = pEntries[alloc_index].Trustee.TrusteeForm;
3679 pEntriesW[alloc_index].Trustee.TrusteeType = pEntries[alloc_index].Trustee.TrusteeType;
3681 err = trustee_name_A_to_W( pEntries[alloc_index].Trustee.TrusteeForm,
3682 pEntries[alloc_index].Trustee.ptstrName,
3683 &pEntriesW[alloc_index].Trustee.ptstrName );
3684 if (err != ERROR_SUCCESS)
3686 if (err == ERROR_INVALID_PARAMETER)
3687 WARN("bad trustee form %d for trustee %d\n",
3688 pEntries[alloc_index].Trustee.TrusteeForm, alloc_index);
3690 goto cleanup;
3694 err = SetEntriesInAclW( count, pEntriesW, OldAcl, NewAcl );
3696 cleanup:
3697 /* Free any previously allocated trustee name buffers, taking into account
3698 * a possible out-of-memory condition while building the EXPLICIT_ACCESSW
3699 * list. */
3700 for (free_index = 0; free_index < alloc_index; ++free_index)
3701 free_trustee_name( pEntriesW[free_index].Trustee.TrusteeForm, pEntriesW[free_index].Trustee.ptstrName );
3703 heap_free( pEntriesW );
3704 return err;
3707 /******************************************************************************
3708 * SetEntriesInAclW [ADVAPI32.@]
3710 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
3711 PACL OldAcl, PACL* NewAcl )
3713 ULONG i;
3714 PSID *ppsid;
3715 DWORD ret = ERROR_SUCCESS;
3716 DWORD acl_size = sizeof(ACL);
3717 NTSTATUS status;
3719 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3721 if (NewAcl)
3722 *NewAcl = NULL;
3724 if (!count && !OldAcl)
3725 return ERROR_SUCCESS;
3727 /* allocate array of maximum sized sids allowed */
3728 ppsid = heap_alloc(count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
3729 if (!ppsid)
3730 return ERROR_OUTOFMEMORY;
3732 for (i = 0; i < count; i++)
3734 ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3736 TRACE("[%d]:\n\tgrfAccessPermissions = 0x%x\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%x\n\t"
3737 "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
3738 "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
3739 pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
3740 pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
3741 pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
3742 pEntries[i].Trustee.ptstrName);
3744 if (pEntries[i].Trustee.MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
3746 WARN("bad multiple trustee operation %d for trustee %d\n", pEntries[i].Trustee.MultipleTrusteeOperation, i);
3747 ret = ERROR_INVALID_PARAMETER;
3748 goto exit;
3751 switch (pEntries[i].Trustee.TrusteeForm)
3753 case TRUSTEE_IS_SID:
3754 if (!CopySid(FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]),
3755 ppsid[i], pEntries[i].Trustee.ptstrName))
3757 WARN("bad sid %p for trustee %d\n", pEntries[i].Trustee.ptstrName, i);
3758 ret = ERROR_INVALID_PARAMETER;
3759 goto exit;
3761 break;
3762 case TRUSTEE_IS_NAME:
3764 DWORD sid_size = FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3765 DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
3766 SID_NAME_USE use;
3767 if (!strcmpW( pEntries[i].Trustee.ptstrName, CURRENT_USER ))
3769 if (!lookup_user_account_name( ppsid[i], &sid_size, NULL, &domain_size, &use ))
3771 ret = GetLastError();
3772 goto exit;
3775 else if (!LookupAccountNameW(NULL, pEntries[i].Trustee.ptstrName, ppsid[i], &sid_size, NULL, &domain_size, &use))
3777 WARN("bad user name %s for trustee %d\n", debugstr_w(pEntries[i].Trustee.ptstrName), i);
3778 ret = ERROR_INVALID_PARAMETER;
3779 goto exit;
3781 break;
3783 case TRUSTEE_IS_OBJECTS_AND_SID:
3784 FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
3785 break;
3786 case TRUSTEE_IS_OBJECTS_AND_NAME:
3787 FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
3788 break;
3789 default:
3790 WARN("bad trustee form %d for trustee %d\n", pEntries[i].Trustee.TrusteeForm, i);
3791 ret = ERROR_INVALID_PARAMETER;
3792 goto exit;
3795 /* Note: we overestimate the ACL size here as a tradeoff between
3796 * instructions (simplicity) and memory */
3797 switch (pEntries[i].grfAccessMode)
3799 case GRANT_ACCESS:
3800 case SET_ACCESS:
3801 acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3802 break;
3803 case DENY_ACCESS:
3804 acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3805 break;
3806 case SET_AUDIT_SUCCESS:
3807 case SET_AUDIT_FAILURE:
3808 acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
3809 break;
3810 case REVOKE_ACCESS:
3811 break;
3812 default:
3813 WARN("bad access mode %d for trustee %d\n", pEntries[i].grfAccessMode, i);
3814 ret = ERROR_INVALID_PARAMETER;
3815 goto exit;
3819 if (OldAcl)
3821 ACL_SIZE_INFORMATION size_info;
3823 status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
3824 if (status != STATUS_SUCCESS)
3826 ret = RtlNtStatusToDosError(status);
3827 goto exit;
3829 acl_size += size_info.AclBytesInUse - sizeof(ACL);
3832 *NewAcl = LocalAlloc(0, acl_size);
3833 if (!*NewAcl)
3835 ret = ERROR_OUTOFMEMORY;
3836 goto exit;
3839 status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
3840 if (status != STATUS_SUCCESS)
3842 ret = RtlNtStatusToDosError(status);
3843 goto exit;
3846 for (i = 0; i < count; i++)
3848 switch (pEntries[i].grfAccessMode)
3850 case GRANT_ACCESS:
3851 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3852 pEntries[i].grfInheritance,
3853 pEntries[i].grfAccessPermissions,
3854 ppsid[i]);
3855 break;
3856 case SET_ACCESS:
3858 ULONG j;
3859 BOOL add = TRUE;
3860 if (OldAcl)
3862 for (j = 0; ; j++)
3864 const ACE_HEADER *existing_ace_header;
3865 status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
3866 if (status != STATUS_SUCCESS)
3867 break;
3868 if (pEntries[i].grfAccessMode == SET_ACCESS &&
3869 existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3870 EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
3872 add = FALSE;
3873 break;
3877 if (add)
3878 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3879 pEntries[i].grfInheritance,
3880 pEntries[i].grfAccessPermissions,
3881 ppsid[i]);
3882 break;
3884 case DENY_ACCESS:
3885 status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
3886 pEntries[i].grfInheritance,
3887 pEntries[i].grfAccessPermissions,
3888 ppsid[i]);
3889 break;
3890 case SET_AUDIT_SUCCESS:
3891 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3892 pEntries[i].grfInheritance,
3893 pEntries[i].grfAccessPermissions,
3894 ppsid[i], TRUE, FALSE);
3895 break;
3896 case SET_AUDIT_FAILURE:
3897 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3898 pEntries[i].grfInheritance,
3899 pEntries[i].grfAccessPermissions,
3900 ppsid[i], FALSE, TRUE);
3901 break;
3902 default:
3903 FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
3907 if (OldAcl)
3909 for (i = 0; ; i++)
3911 BOOL add = TRUE;
3912 ULONG j;
3913 const ACE_HEADER *old_ace_header;
3914 status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
3915 if (status != STATUS_SUCCESS) break;
3916 for (j = 0; j < count; j++)
3918 if (pEntries[j].grfAccessMode == SET_ACCESS &&
3919 old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3920 EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3922 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
3923 add = FALSE;
3924 break;
3926 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
3928 switch (old_ace_header->AceType)
3930 case ACCESS_ALLOWED_ACE_TYPE:
3931 if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3932 add = FALSE;
3933 break;
3934 case ACCESS_DENIED_ACE_TYPE:
3935 if (EqualSid(ppsid[j], &((ACCESS_DENIED_ACE *)old_ace_header)->SidStart))
3936 add = FALSE;
3937 break;
3938 case SYSTEM_AUDIT_ACE_TYPE:
3939 if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
3940 add = FALSE;
3941 break;
3942 case SYSTEM_ALARM_ACE_TYPE:
3943 if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
3944 add = FALSE;
3945 break;
3946 default:
3947 FIXME("unhandled ace type %d\n", old_ace_header->AceType);
3950 if (!add)
3951 break;
3954 if (add)
3955 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
3956 if (status != STATUS_SUCCESS)
3958 WARN("RtlAddAce failed with error 0x%08x\n", status);
3959 ret = RtlNtStatusToDosError(status);
3960 break;
3965 exit:
3966 heap_free(ppsid);
3967 return ret;
3970 /******************************************************************************
3971 * SetNamedSecurityInfoA [ADVAPI32.@]
3973 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
3974 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
3975 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
3977 LPWSTR wstr;
3978 DWORD r;
3980 TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
3981 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
3983 wstr = SERV_dup(pObjectName);
3984 r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
3985 psidGroup, pDacl, pSacl );
3987 heap_free( wstr );
3989 return r;
3992 BOOL WINAPI SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation,
3993 PSECURITY_DESCRIPTOR ModificationDescriptor,
3994 PSECURITY_DESCRIPTOR* ObjectsSecurityDescriptor,
3995 PGENERIC_MAPPING GenericMapping,
3996 HANDLE Token )
3998 FIXME("0x%08x %p %p %p %p - stub\n", SecurityInformation, ModificationDescriptor,
3999 ObjectsSecurityDescriptor, GenericMapping, Token);
4001 return TRUE;
4004 BOOL WINAPI AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
4006 return RtlAreAllAccessesGranted( GrantedAccess, DesiredAccess );
4009 /******************************************************************************
4010 * AreAnyAccessesGranted [ADVAPI32.@]
4012 * Determines whether or not any of a set of specified access permissions have
4013 * been granted or not.
4015 * PARAMS
4016 * GrantedAccess [I] The permissions that have been granted.
4017 * DesiredAccess [I] The permissions that you want to have.
4019 * RETURNS
4020 * Nonzero if any of the permissions have been granted, zero if none of the
4021 * permissions have been granted.
4024 BOOL WINAPI AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
4026 return RtlAreAnyAccessesGranted( GrantedAccess, DesiredAccess );
4029 /******************************************************************************
4030 * SetNamedSecurityInfoW [ADVAPI32.@]
4032 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
4033 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
4034 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
4036 DWORD access = 0;
4037 HANDLE handle;
4038 DWORD err;
4040 TRACE( "%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
4041 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
4043 if (!pObjectName) return ERROR_INVALID_PARAMETER;
4045 if (SecurityInfo & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION))
4046 access |= WRITE_OWNER;
4047 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4048 access |= WRITE_DAC;
4049 if (SecurityInfo & SACL_SECURITY_INFORMATION)
4050 access |= ACCESS_SYSTEM_SECURITY;
4052 switch (ObjectType)
4054 case SE_SERVICE:
4055 if (!(err = get_security_service( pObjectName, access, &handle )))
4057 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4058 CloseServiceHandle( handle );
4060 break;
4061 case SE_REGISTRY_KEY:
4062 if (!(err = get_security_regkey( pObjectName, access, &handle )))
4064 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4065 RegCloseKey( handle );
4067 break;
4068 case SE_FILE_OBJECT:
4069 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4070 access |= READ_CONTROL;
4071 if (!(err = get_security_file( pObjectName, access, &handle )))
4073 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4074 CloseHandle( handle );
4076 break;
4077 default:
4078 FIXME( "Object type %d is not currently supported.\n", ObjectType );
4079 return ERROR_SUCCESS;
4081 return err;
4084 /******************************************************************************
4085 * GetExplicitEntriesFromAclA [ADVAPI32.@]
4087 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
4088 PEXPLICIT_ACCESSA* pListOfExplicitEntries)
4090 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
4091 return ERROR_CALL_NOT_IMPLEMENTED;
4094 /******************************************************************************
4095 * GetExplicitEntriesFromAclW [ADVAPI32.@]
4097 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
4098 PEXPLICIT_ACCESSW* pListOfExplicitEntries)
4100 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
4101 return ERROR_CALL_NOT_IMPLEMENTED;
4104 /******************************************************************************
4105 * GetAuditedPermissionsFromAclA [ADVAPI32.@]
4107 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
4108 PACCESS_MASK pFailedAuditRights)
4110 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
4111 return ERROR_CALL_NOT_IMPLEMENTED;
4115 /******************************************************************************
4116 * GetAuditedPermissionsFromAclW [ADVAPI32.@]
4118 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
4119 PACCESS_MASK pFailedAuditRights)
4121 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
4122 return ERROR_CALL_NOT_IMPLEMENTED;
4126 /******************************************************************************
4127 * ParseAclStringFlags
4129 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
4131 DWORD flags = 0;
4132 LPCWSTR szAcl = *StringAcl;
4134 while (*szAcl != '(')
4136 if (*szAcl == 'P')
4138 flags |= SE_DACL_PROTECTED;
4140 else if (*szAcl == 'A')
4142 szAcl++;
4143 if (*szAcl == 'R')
4144 flags |= SE_DACL_AUTO_INHERIT_REQ;
4145 else if (*szAcl == 'I')
4146 flags |= SE_DACL_AUTO_INHERITED;
4148 szAcl++;
4151 *StringAcl = szAcl;
4152 return flags;
4155 /******************************************************************************
4156 * ParseAceStringType
4158 static const ACEFLAG AceType[] =
4160 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
4161 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
4162 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
4163 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
4164 { SDDL_MANDATORY_LABEL,SYSTEM_MANDATORY_LABEL_ACE_TYPE },
4166 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
4167 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
4168 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
4169 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
4171 { NULL, 0 },
4174 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
4176 UINT len = 0;
4177 LPCWSTR szAcl = *StringAcl;
4178 const ACEFLAG *lpaf = AceType;
4180 while (*szAcl == ' ')
4181 szAcl++;
4183 while (lpaf->wstr &&
4184 (len = strlenW(lpaf->wstr)) &&
4185 strncmpW(lpaf->wstr, szAcl, len))
4186 lpaf++;
4188 if (!lpaf->wstr)
4189 return 0;
4191 *StringAcl = szAcl + len;
4192 return lpaf->value;
4196 /******************************************************************************
4197 * ParseAceStringFlags
4199 static const ACEFLAG AceFlags[] =
4201 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
4202 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
4203 { SDDL_INHERITED, INHERITED_ACE },
4204 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
4205 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
4206 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
4207 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
4208 { NULL, 0 },
4211 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
4213 UINT len = 0;
4214 BYTE flags = 0;
4215 LPCWSTR szAcl = *StringAcl;
4217 while (*szAcl == ' ')
4218 szAcl++;
4220 while (*szAcl != ';')
4222 const ACEFLAG *lpaf = AceFlags;
4224 while (lpaf->wstr &&
4225 (len = strlenW(lpaf->wstr)) &&
4226 strncmpW(lpaf->wstr, szAcl, len))
4227 lpaf++;
4229 if (!lpaf->wstr)
4230 return 0;
4232 flags |= lpaf->value;
4233 szAcl += len;
4236 *StringAcl = szAcl;
4237 return flags;
4241 /******************************************************************************
4242 * ParseAceStringRights
4244 static const ACEFLAG AceRights[] =
4246 { SDDL_GENERIC_ALL, GENERIC_ALL },
4247 { SDDL_GENERIC_READ, GENERIC_READ },
4248 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
4249 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
4251 { SDDL_READ_CONTROL, READ_CONTROL },
4252 { SDDL_STANDARD_DELETE, DELETE },
4253 { SDDL_WRITE_DAC, WRITE_DAC },
4254 { SDDL_WRITE_OWNER, WRITE_OWNER },
4256 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
4257 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
4258 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
4259 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
4260 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
4261 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
4262 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
4263 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
4264 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
4266 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
4267 { SDDL_FILE_READ, FILE_GENERIC_READ },
4268 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
4269 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
4271 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
4272 { SDDL_KEY_READ, KEY_READ },
4273 { SDDL_KEY_WRITE, KEY_WRITE },
4274 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
4276 { SDDL_NO_READ_UP, SYSTEM_MANDATORY_LABEL_NO_READ_UP },
4277 { SDDL_NO_WRITE_UP, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP },
4278 { SDDL_NO_EXECUTE_UP, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP },
4279 { NULL, 0 },
4282 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
4284 UINT len = 0;
4285 DWORD rights = 0;
4286 LPCWSTR szAcl = *StringAcl;
4288 while (*szAcl == ' ')
4289 szAcl++;
4291 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
4293 LPCWSTR p = szAcl;
4295 while (*p && *p != ';')
4296 p++;
4298 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
4300 rights = strtoulW(szAcl, NULL, 16);
4301 szAcl = p;
4303 else
4304 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
4306 else
4308 while (*szAcl != ';')
4310 const ACEFLAG *lpaf = AceRights;
4312 while (lpaf->wstr &&
4313 (len = strlenW(lpaf->wstr)) &&
4314 strncmpW(lpaf->wstr, szAcl, len))
4316 lpaf++;
4319 if (!lpaf->wstr)
4320 return 0;
4322 rights |= lpaf->value;
4323 szAcl += len;
4327 *StringAcl = szAcl;
4328 return rights;
4332 /******************************************************************************
4333 * ParseStringAclToAcl
4335 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
4337 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
4338 PACL pAcl, LPDWORD cBytes)
4340 DWORD val;
4341 DWORD sidlen;
4342 DWORD length = sizeof(ACL);
4343 DWORD acesize = 0;
4344 DWORD acecount = 0;
4345 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
4346 DWORD error = ERROR_INVALID_ACL;
4348 TRACE("%s\n", debugstr_w(StringAcl));
4350 if (!StringAcl)
4351 return FALSE;
4353 if (pAcl) /* pAce is only useful if we're setting values */
4354 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
4356 /* Parse ACL flags */
4357 *lpdwFlags = ParseAclStringFlags(&StringAcl);
4359 /* Parse ACE */
4360 while (*StringAcl == '(')
4362 StringAcl++;
4364 /* Parse ACE type */
4365 val = ParseAceStringType(&StringAcl);
4366 if (pAce)
4367 pAce->Header.AceType = (BYTE) val;
4368 if (*StringAcl != ';')
4370 error = RPC_S_INVALID_STRING_UUID;
4371 goto lerr;
4373 StringAcl++;
4375 /* Parse ACE flags */
4376 val = ParseAceStringFlags(&StringAcl);
4377 if (pAce)
4378 pAce->Header.AceFlags = (BYTE) val;
4379 if (*StringAcl != ';')
4380 goto lerr;
4381 StringAcl++;
4383 /* Parse ACE rights */
4384 val = ParseAceStringRights(&StringAcl);
4385 if (pAce)
4386 pAce->Mask = val;
4387 if (*StringAcl != ';')
4388 goto lerr;
4389 StringAcl++;
4391 /* Parse ACE object guid */
4392 while (*StringAcl == ' ')
4393 StringAcl++;
4394 if (*StringAcl != ';')
4396 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4397 goto lerr;
4399 StringAcl++;
4401 /* Parse ACE inherit object guid */
4402 while (*StringAcl == ' ')
4403 StringAcl++;
4404 if (*StringAcl != ';')
4406 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4407 goto lerr;
4409 StringAcl++;
4411 /* Parse ACE account sid */
4412 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
4414 while (*StringAcl && *StringAcl != ')')
4415 StringAcl++;
4418 if (*StringAcl != ')')
4419 goto lerr;
4420 StringAcl++;
4422 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
4423 length += acesize;
4424 if (pAce)
4426 pAce->Header.AceSize = acesize;
4427 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
4429 acecount++;
4432 *cBytes = length;
4434 if (length > 0xffff)
4436 ERR("ACL too large\n");
4437 goto lerr;
4440 if (pAcl)
4442 pAcl->AclRevision = ACL_REVISION;
4443 pAcl->Sbz1 = 0;
4444 pAcl->AclSize = length;
4445 pAcl->AceCount = acecount++;
4446 pAcl->Sbz2 = 0;
4448 return TRUE;
4450 lerr:
4451 SetLastError(error);
4452 WARN("Invalid ACE string format\n");
4453 return FALSE;
4457 /******************************************************************************
4458 * ParseStringSecurityDescriptorToSecurityDescriptor
4460 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
4461 LPCWSTR StringSecurityDescriptor,
4462 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
4463 LPDWORD cBytes)
4465 BOOL bret = FALSE;
4466 WCHAR toktype;
4467 WCHAR tok[MAX_PATH];
4468 LPCWSTR lptoken;
4469 LPBYTE lpNext = NULL;
4470 DWORD len;
4472 *cBytes = sizeof(SECURITY_DESCRIPTOR);
4474 if (SecurityDescriptor)
4475 lpNext = (LPBYTE)(SecurityDescriptor + 1);
4477 while (*StringSecurityDescriptor == ' ')
4478 StringSecurityDescriptor++;
4480 while (*StringSecurityDescriptor)
4482 toktype = *StringSecurityDescriptor;
4484 /* Expect char identifier followed by ':' */
4485 StringSecurityDescriptor++;
4486 if (*StringSecurityDescriptor != ':')
4488 SetLastError(ERROR_INVALID_PARAMETER);
4489 goto lend;
4491 StringSecurityDescriptor++;
4493 /* Extract token */
4494 lptoken = StringSecurityDescriptor;
4495 while (*lptoken && *lptoken != ':')
4496 lptoken++;
4498 if (*lptoken)
4499 lptoken--;
4501 len = lptoken - StringSecurityDescriptor;
4502 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
4503 tok[len] = 0;
4505 switch (toktype)
4507 case 'O':
4509 DWORD bytes;
4511 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4512 goto lend;
4514 if (SecurityDescriptor)
4516 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
4517 lpNext += bytes; /* Advance to next token */
4520 *cBytes += bytes;
4522 break;
4525 case 'G':
4527 DWORD bytes;
4529 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4530 goto lend;
4532 if (SecurityDescriptor)
4534 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
4535 lpNext += bytes; /* Advance to next token */
4538 *cBytes += bytes;
4540 break;
4543 case 'D':
4545 DWORD flags;
4546 DWORD bytes;
4548 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4549 goto lend;
4551 if (SecurityDescriptor)
4553 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
4554 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
4555 lpNext += bytes; /* Advance to next token */
4558 *cBytes += bytes;
4560 break;
4563 case 'S':
4565 DWORD flags;
4566 DWORD bytes;
4568 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4569 goto lend;
4571 if (SecurityDescriptor)
4573 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
4574 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
4575 lpNext += bytes; /* Advance to next token */
4578 *cBytes += bytes;
4580 break;
4583 default:
4584 FIXME("Unknown token\n");
4585 SetLastError(ERROR_INVALID_PARAMETER);
4586 goto lend;
4589 StringSecurityDescriptor = lptoken;
4592 bret = TRUE;
4594 lend:
4595 return bret;
4598 /******************************************************************************
4599 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
4601 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
4602 LPCSTR StringSecurityDescriptor,
4603 DWORD StringSDRevision,
4604 PSECURITY_DESCRIPTOR* SecurityDescriptor,
4605 PULONG SecurityDescriptorSize)
4607 BOOL ret;
4608 LPWSTR StringSecurityDescriptorW;
4610 if(!StringSecurityDescriptor)
4611 return FALSE;
4613 StringSecurityDescriptorW = SERV_dup(StringSecurityDescriptor);
4614 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
4615 StringSDRevision, SecurityDescriptor,
4616 SecurityDescriptorSize);
4617 heap_free(StringSecurityDescriptorW);
4619 return ret;
4622 /******************************************************************************
4623 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
4625 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
4626 LPCWSTR StringSecurityDescriptor,
4627 DWORD StringSDRevision,
4628 PSECURITY_DESCRIPTOR* SecurityDescriptor,
4629 PULONG SecurityDescriptorSize)
4631 DWORD cBytes;
4632 SECURITY_DESCRIPTOR* psd;
4633 BOOL bret = FALSE;
4635 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
4637 if (GetVersion() & 0x80000000)
4639 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4640 goto lend;
4642 else if (!StringSecurityDescriptor || !SecurityDescriptor)
4644 SetLastError(ERROR_INVALID_PARAMETER);
4645 goto lend;
4647 else if (StringSDRevision != SID_REVISION)
4649 SetLastError(ERROR_UNKNOWN_REVISION);
4650 goto lend;
4653 /* Compute security descriptor length */
4654 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4655 NULL, &cBytes))
4656 goto lend;
4658 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
4659 if (!psd) goto lend;
4661 psd->Revision = SID_REVISION;
4662 psd->Control |= SE_SELF_RELATIVE;
4664 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4665 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
4667 LocalFree(psd);
4668 goto lend;
4671 if (SecurityDescriptorSize)
4672 *SecurityDescriptorSize = cBytes;
4674 bret = TRUE;
4676 lend:
4677 TRACE(" ret=%d\n", bret);
4678 return bret;
4681 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
4683 if (cch == -1)
4684 cch = strlenW(string);
4686 if (plen)
4687 *plen += cch;
4689 if (pwptr)
4691 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
4692 *pwptr += cch;
4696 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
4698 DWORD i;
4699 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
4700 WCHAR subauthfmt[] = { '-','%','u',0 };
4701 WCHAR buf[26];
4702 SID *pisid = psid;
4704 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
4706 SetLastError(ERROR_INVALID_SID);
4707 return FALSE;
4710 if (pisid->IdentifierAuthority.Value[0] ||
4711 pisid->IdentifierAuthority.Value[1])
4713 FIXME("not matching MS' bugs\n");
4714 SetLastError(ERROR_INVALID_SID);
4715 return FALSE;
4718 sprintfW( buf, fmt, pisid->Revision,
4719 MAKELONG(
4720 MAKEWORD( pisid->IdentifierAuthority.Value[5],
4721 pisid->IdentifierAuthority.Value[4] ),
4722 MAKEWORD( pisid->IdentifierAuthority.Value[3],
4723 pisid->IdentifierAuthority.Value[2] )
4724 ) );
4725 DumpString(buf, -1, pwptr, plen);
4727 for( i=0; i<pisid->SubAuthorityCount; i++ )
4729 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
4730 DumpString(buf, -1, pwptr, plen);
4732 return TRUE;
4735 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
4737 size_t i;
4738 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
4740 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
4742 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
4743 return TRUE;
4747 return DumpSidNumeric(psid, pwptr, plen);
4750 static const LPCWSTR AceRightBitNames[32] = {
4751 SDDL_CREATE_CHILD, /* 0 */
4752 SDDL_DELETE_CHILD,
4753 SDDL_LIST_CHILDREN,
4754 SDDL_SELF_WRITE,
4755 SDDL_READ_PROPERTY, /* 4 */
4756 SDDL_WRITE_PROPERTY,
4757 SDDL_DELETE_TREE,
4758 SDDL_LIST_OBJECT,
4759 SDDL_CONTROL_ACCESS, /* 8 */
4760 NULL,
4761 NULL,
4762 NULL,
4763 NULL, /* 12 */
4764 NULL,
4765 NULL,
4766 NULL,
4767 SDDL_STANDARD_DELETE, /* 16 */
4768 SDDL_READ_CONTROL,
4769 SDDL_WRITE_DAC,
4770 SDDL_WRITE_OWNER,
4771 NULL, /* 20 */
4772 NULL,
4773 NULL,
4774 NULL,
4775 NULL, /* 24 */
4776 NULL,
4777 NULL,
4778 NULL,
4779 SDDL_GENERIC_ALL, /* 28 */
4780 SDDL_GENERIC_EXECUTE,
4781 SDDL_GENERIC_WRITE,
4782 SDDL_GENERIC_READ
4785 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
4787 static const WCHAR fmtW[] = {'0','x','%','x',0};
4788 WCHAR buf[15];
4789 size_t i;
4791 if (mask == 0)
4792 return;
4794 /* first check if the right have name */
4795 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
4797 if (AceRights[i].wstr == NULL)
4798 break;
4799 if (mask == AceRights[i].value)
4801 DumpString(AceRights[i].wstr, -1, pwptr, plen);
4802 return;
4806 /* then check if it can be built from bit names */
4807 for (i = 0; i < 32; i++)
4809 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
4811 /* can't be built from bit names */
4812 sprintfW(buf, fmtW, mask);
4813 DumpString(buf, -1, pwptr, plen);
4814 return;
4818 /* build from bit names */
4819 for (i = 0; i < 32; i++)
4820 if (mask & (1 << i))
4821 DumpString(AceRightBitNames[i], -1, pwptr, plen);
4824 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
4826 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
4827 static const WCHAR openbr = '(';
4828 static const WCHAR closebr = ')';
4829 static const WCHAR semicolon = ';';
4831 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
4833 SetLastError(ERROR_INVALID_ACL);
4834 return FALSE;
4837 piace = pace;
4838 DumpString(&openbr, 1, pwptr, plen);
4839 switch (piace->Header.AceType)
4841 case ACCESS_ALLOWED_ACE_TYPE:
4842 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
4843 break;
4844 case ACCESS_DENIED_ACE_TYPE:
4845 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
4846 break;
4847 case SYSTEM_AUDIT_ACE_TYPE:
4848 DumpString(SDDL_AUDIT, -1, pwptr, plen);
4849 break;
4850 case SYSTEM_ALARM_ACE_TYPE:
4851 DumpString(SDDL_ALARM, -1, pwptr, plen);
4852 break;
4854 DumpString(&semicolon, 1, pwptr, plen);
4856 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
4857 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
4858 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
4859 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
4860 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
4861 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
4862 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
4863 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
4864 if (piace->Header.AceFlags & INHERITED_ACE)
4865 DumpString(SDDL_INHERITED, -1, pwptr, plen);
4866 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
4867 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
4868 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
4869 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
4870 DumpString(&semicolon, 1, pwptr, plen);
4871 DumpRights(piace->Mask, pwptr, plen);
4872 DumpString(&semicolon, 1, pwptr, plen);
4873 /* objects not supported */
4874 DumpString(&semicolon, 1, pwptr, plen);
4875 /* objects not supported */
4876 DumpString(&semicolon, 1, pwptr, plen);
4877 if (!DumpSid(&piace->SidStart, pwptr, plen))
4878 return FALSE;
4879 DumpString(&closebr, 1, pwptr, plen);
4880 return TRUE;
4883 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
4885 WORD count;
4886 UINT i;
4888 if (protected)
4889 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
4890 if (autoInheritReq)
4891 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
4892 if (autoInherited)
4893 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
4895 if (pacl == NULL)
4896 return TRUE;
4898 if (!IsValidAcl(pacl))
4899 return FALSE;
4901 count = pacl->AceCount;
4902 for (i = 0; i < count; i++)
4904 LPVOID ace;
4905 if (!GetAce(pacl, i, &ace))
4906 return FALSE;
4907 if (!DumpAce(ace, pwptr, plen))
4908 return FALSE;
4911 return TRUE;
4914 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4916 static const WCHAR prefix[] = {'O',':',0};
4917 BOOL bDefaulted;
4918 PSID psid;
4920 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
4921 return FALSE;
4923 if (psid == NULL)
4924 return TRUE;
4926 DumpString(prefix, -1, pwptr, plen);
4927 if (!DumpSid(psid, pwptr, plen))
4928 return FALSE;
4929 return TRUE;
4932 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4934 static const WCHAR prefix[] = {'G',':',0};
4935 BOOL bDefaulted;
4936 PSID psid;
4938 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
4939 return FALSE;
4941 if (psid == NULL)
4942 return TRUE;
4944 DumpString(prefix, -1, pwptr, plen);
4945 if (!DumpSid(psid, pwptr, plen))
4946 return FALSE;
4947 return TRUE;
4950 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4952 static const WCHAR dacl[] = {'D',':',0};
4953 SECURITY_DESCRIPTOR_CONTROL control;
4954 BOOL present, defaulted;
4955 DWORD revision;
4956 PACL pacl;
4958 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
4959 return FALSE;
4961 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4962 return FALSE;
4964 if (!present)
4965 return TRUE;
4967 DumpString(dacl, 2, pwptr, plen);
4968 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
4969 return FALSE;
4970 return TRUE;
4973 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4975 static const WCHAR sacl[] = {'S',':',0};
4976 SECURITY_DESCRIPTOR_CONTROL control;
4977 BOOL present, defaulted;
4978 DWORD revision;
4979 PACL pacl;
4981 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
4982 return FALSE;
4984 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
4985 return FALSE;
4987 if (!present)
4988 return TRUE;
4990 DumpString(sacl, 2, pwptr, plen);
4991 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
4992 return FALSE;
4993 return TRUE;
4996 /******************************************************************************
4997 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
4999 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
5001 ULONG len;
5002 WCHAR *wptr, *wstr;
5004 if (SDRevision != SDDL_REVISION_1)
5006 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
5007 SetLastError(ERROR_UNKNOWN_REVISION);
5008 return FALSE;
5011 len = 0;
5012 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
5013 if (!DumpOwner(SecurityDescriptor, NULL, &len))
5014 return FALSE;
5015 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
5016 if (!DumpGroup(SecurityDescriptor, NULL, &len))
5017 return FALSE;
5018 if (RequestedInformation & DACL_SECURITY_INFORMATION)
5019 if (!DumpDacl(SecurityDescriptor, NULL, &len))
5020 return FALSE;
5021 if (RequestedInformation & SACL_SECURITY_INFORMATION)
5022 if (!DumpSacl(SecurityDescriptor, NULL, &len))
5023 return FALSE;
5025 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
5026 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
5027 if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) {
5028 LocalFree (wstr);
5029 return FALSE;
5031 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
5032 if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) {
5033 LocalFree (wstr);
5034 return FALSE;
5036 if (RequestedInformation & DACL_SECURITY_INFORMATION)
5037 if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) {
5038 LocalFree (wstr);
5039 return FALSE;
5041 if (RequestedInformation & SACL_SECURITY_INFORMATION)
5042 if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) {
5043 LocalFree (wstr);
5044 return FALSE;
5046 *wptr = 0;
5048 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
5049 *OutputString = wstr;
5050 if (OutputLen)
5051 *OutputLen = strlenW(*OutputString)+1;
5052 return TRUE;
5055 /******************************************************************************
5056 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
5058 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
5060 LPWSTR wstr;
5061 ULONG len;
5062 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
5064 int lenA;
5066 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
5067 *OutputString = heap_alloc(lenA);
5068 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
5069 LocalFree(wstr);
5071 if (OutputLen != NULL)
5072 *OutputLen = lenA;
5073 return TRUE;
5075 else
5077 *OutputString = NULL;
5078 if (OutputLen)
5079 *OutputLen = 0;
5080 return FALSE;
5084 /******************************************************************************
5085 * ConvertStringSidToSidW [ADVAPI32.@]
5087 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
5089 BOOL bret = FALSE;
5090 DWORD cBytes;
5092 TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
5093 if (GetVersion() & 0x80000000)
5094 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5095 else if (!StringSid || !Sid)
5096 SetLastError(ERROR_INVALID_PARAMETER);
5097 else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
5099 PSID pSid = *Sid = LocalAlloc(0, cBytes);
5101 bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
5102 if (!bret)
5103 LocalFree(*Sid);
5105 return bret;
5108 /******************************************************************************
5109 * ConvertStringSidToSidA [ADVAPI32.@]
5111 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
5113 BOOL bret = FALSE;
5115 TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
5116 if (GetVersion() & 0x80000000)
5117 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5118 else if (!StringSid || !Sid)
5119 SetLastError(ERROR_INVALID_PARAMETER);
5120 else
5122 WCHAR *wStringSid = SERV_dup(StringSid);
5123 bret = ConvertStringSidToSidW(wStringSid, Sid);
5124 heap_free(wStringSid);
5126 return bret;
5129 /******************************************************************************
5130 * ConvertSidToStringSidW [ADVAPI32.@]
5132 * format of SID string is:
5133 * S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
5134 * where
5135 * <rev> is the revision of the SID encoded as decimal
5136 * <auth> is the identifier authority encoded as hex
5137 * <subauthN> is the subauthority id encoded as decimal
5139 BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
5141 DWORD len = 0;
5142 LPWSTR wstr, wptr;
5144 TRACE("%p %p\n", pSid, pstr );
5146 len = 0;
5147 if (!DumpSidNumeric(pSid, NULL, &len))
5148 return FALSE;
5149 wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
5150 DumpSidNumeric(pSid, &wptr, NULL);
5151 *wptr = 0;
5153 *pstr = wstr;
5154 return TRUE;
5157 /******************************************************************************
5158 * ConvertSidToStringSidA [ADVAPI32.@]
5160 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
5162 LPWSTR wstr = NULL;
5163 LPSTR str;
5164 UINT len;
5166 TRACE("%p %p\n", pSid, pstr );
5168 if( !ConvertSidToStringSidW( pSid, &wstr ) )
5169 return FALSE;
5171 len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
5172 str = LocalAlloc( 0, len );
5173 WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
5174 LocalFree( wstr );
5176 *pstr = str;
5178 return TRUE;
5181 BOOL WINAPI ConvertToAutoInheritPrivateObjectSecurity(
5182 PSECURITY_DESCRIPTOR pdesc,
5183 PSECURITY_DESCRIPTOR cdesc,
5184 PSECURITY_DESCRIPTOR* ndesc,
5185 GUID* objtype,
5186 BOOL isdir,
5187 PGENERIC_MAPPING genmap )
5189 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
5191 return FALSE;
5194 BOOL WINAPI CreatePrivateObjectSecurity(
5195 PSECURITY_DESCRIPTOR ParentDescriptor,
5196 PSECURITY_DESCRIPTOR CreatorDescriptor,
5197 PSECURITY_DESCRIPTOR* NewDescriptor,
5198 BOOL IsDirectoryObject,
5199 HANDLE Token,
5200 PGENERIC_MAPPING GenericMapping )
5202 SECURITY_DESCRIPTOR_RELATIVE *relative;
5203 DWORD needed, offset;
5204 BYTE *buffer;
5206 FIXME("%p %p %p %d %p %p - returns fake SECURITY_DESCRIPTOR\n", ParentDescriptor,
5207 CreatorDescriptor, NewDescriptor, IsDirectoryObject, Token, GenericMapping);
5209 needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5210 needed += sizeof(sidWorld);
5211 needed += sizeof(sidWorld);
5212 needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5213 needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5215 if (!(buffer = heap_alloc( needed ))) return FALSE;
5216 relative = (SECURITY_DESCRIPTOR_RELATIVE *)buffer;
5217 if (!InitializeSecurityDescriptor( relative, SECURITY_DESCRIPTOR_REVISION ))
5219 heap_free( buffer );
5220 return FALSE;
5222 relative->Control |= SE_SELF_RELATIVE;
5223 offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5225 memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5226 relative->Owner = offset;
5227 offset += sizeof(sidWorld);
5229 memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5230 relative->Group = offset;
5231 offset += sizeof(sidWorld);
5233 GetWorldAccessACL( (ACL *)(buffer + offset) );
5234 relative->Dacl = offset;
5235 offset += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5237 GetWorldAccessACL( (ACL *)(buffer + offset) );
5238 relative->Sacl = offset;
5240 *NewDescriptor = relative;
5241 return TRUE;
5244 BOOL WINAPI DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR* ObjectDescriptor )
5246 FIXME("%p - stub\n", ObjectDescriptor);
5248 heap_free( *ObjectDescriptor );
5249 return TRUE;
5252 BOOL WINAPI CreateProcessAsUserA(
5253 HANDLE hToken,
5254 LPCSTR lpApplicationName,
5255 LPSTR lpCommandLine,
5256 LPSECURITY_ATTRIBUTES lpProcessAttributes,
5257 LPSECURITY_ATTRIBUTES lpThreadAttributes,
5258 BOOL bInheritHandles,
5259 DWORD dwCreationFlags,
5260 LPVOID lpEnvironment,
5261 LPCSTR lpCurrentDirectory,
5262 LPSTARTUPINFOA lpStartupInfo,
5263 LPPROCESS_INFORMATION lpProcessInformation )
5265 BOOL ret;
5266 WCHAR *appW, *cmdlnW, *cwdW;
5267 STARTUPINFOW sinfo;
5269 TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_a(lpApplicationName),
5270 debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
5271 dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5273 appW = SERV_dup(lpApplicationName);
5274 cmdlnW = SERV_dup(lpCommandLine);
5275 cwdW = SERV_dup(lpCurrentDirectory);
5276 sinfo.cb = sizeof(sinfo);
5277 sinfo.lpReserved = SERV_dup(lpStartupInfo->lpReserved);
5278 sinfo.lpDesktop = SERV_dup(lpStartupInfo->lpDesktop);
5279 sinfo.lpTitle = SERV_dup(lpStartupInfo->lpTitle);
5280 sinfo.dwX = lpStartupInfo->dwX;
5281 sinfo.dwY = lpStartupInfo->dwY;
5282 sinfo.dwXSize = lpStartupInfo->dwXSize;
5283 sinfo.dwYSize = lpStartupInfo->dwYSize;
5284 sinfo.dwXCountChars = lpStartupInfo->dwXCountChars;
5285 sinfo.dwYCountChars = lpStartupInfo->dwYCountChars;
5286 sinfo.dwFillAttribute = lpStartupInfo->dwFillAttribute;
5287 sinfo.dwFlags = lpStartupInfo->dwFlags;
5288 sinfo.wShowWindow = lpStartupInfo->wShowWindow;
5289 sinfo.cbReserved2 = lpStartupInfo->cbReserved2;
5290 sinfo.lpReserved2 = lpStartupInfo->lpReserved2;
5291 sinfo.hStdInput = lpStartupInfo->hStdInput;
5292 sinfo.hStdOutput = lpStartupInfo->hStdOutput;
5293 sinfo.hStdError = lpStartupInfo->hStdError;
5294 ret = CreateProcessAsUserW(hToken, appW, cmdlnW, lpProcessAttributes,
5295 lpThreadAttributes, bInheritHandles, dwCreationFlags,
5296 lpEnvironment, cwdW, &sinfo, lpProcessInformation);
5297 heap_free(appW);
5298 heap_free(cmdlnW);
5299 heap_free(cwdW);
5300 heap_free(sinfo.lpReserved);
5301 heap_free(sinfo.lpDesktop);
5302 heap_free(sinfo.lpTitle);
5304 return ret;
5307 BOOL WINAPI CreateProcessAsUserW(
5308 HANDLE hToken,
5309 LPCWSTR lpApplicationName,
5310 LPWSTR lpCommandLine,
5311 LPSECURITY_ATTRIBUTES lpProcessAttributes,
5312 LPSECURITY_ATTRIBUTES lpThreadAttributes,
5313 BOOL bInheritHandles,
5314 DWORD dwCreationFlags,
5315 LPVOID lpEnvironment,
5316 LPCWSTR lpCurrentDirectory,
5317 LPSTARTUPINFOW lpStartupInfo,
5318 LPPROCESS_INFORMATION lpProcessInformation )
5320 FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - semi-stub\n", hToken,
5321 debugstr_w(lpApplicationName), debugstr_w(lpCommandLine), lpProcessAttributes,
5322 lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
5323 debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5325 /* We should create the process with a suspended main thread */
5326 if (!CreateProcessW (lpApplicationName,
5327 lpCommandLine,
5328 lpProcessAttributes,
5329 lpThreadAttributes,
5330 bInheritHandles,
5331 dwCreationFlags, /* CREATE_SUSPENDED */
5332 lpEnvironment,
5333 lpCurrentDirectory,
5334 lpStartupInfo,
5335 lpProcessInformation))
5337 return FALSE;
5340 return TRUE;
5343 /******************************************************************************
5344 * CreateProcessWithLogonW
5346 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
5347 LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
5348 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
5350 FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
5351 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
5352 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
5353 lpStartupInfo, lpProcessInformation);
5355 return FALSE;
5358 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line,
5359 DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info,
5360 PROCESS_INFORMATION *process_information )
5362 FIXME("%p 0x%08x %s %s 0x%08x %p %s %p %p - semi-stub\n", token,
5363 logon_flags, debugstr_w(application_name), debugstr_w(command_line),
5364 creation_flags, environment, debugstr_w(current_directory),
5365 startup_info, process_information);
5367 /* FIXME: check if handles should be inherited */
5368 return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment,
5369 current_directory, startup_info, process_information );
5372 /******************************************************************************
5373 * DuplicateTokenEx [ADVAPI32.@]
5375 BOOL WINAPI DuplicateTokenEx(
5376 HANDLE ExistingTokenHandle, DWORD dwDesiredAccess,
5377 LPSECURITY_ATTRIBUTES lpTokenAttributes,
5378 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5379 TOKEN_TYPE TokenType,
5380 PHANDLE DuplicateTokenHandle )
5382 OBJECT_ATTRIBUTES ObjectAttributes;
5384 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
5385 ImpersonationLevel, TokenType, DuplicateTokenHandle);
5387 InitializeObjectAttributes(
5388 &ObjectAttributes,
5389 NULL,
5390 (lpTokenAttributes && lpTokenAttributes->bInheritHandle) ? OBJ_INHERIT : 0,
5391 NULL,
5392 lpTokenAttributes ? lpTokenAttributes->lpSecurityDescriptor : NULL );
5394 return set_ntstatus( NtDuplicateToken( ExistingTokenHandle,
5395 dwDesiredAccess,
5396 &ObjectAttributes,
5397 ImpersonationLevel,
5398 TokenType,
5399 DuplicateTokenHandle ) );
5402 BOOL WINAPI DuplicateToken(
5403 HANDLE ExistingTokenHandle,
5404 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5405 PHANDLE DuplicateTokenHandle )
5407 return DuplicateTokenEx( ExistingTokenHandle, TOKEN_IMPERSONATE | TOKEN_QUERY,
5408 NULL, ImpersonationLevel, TokenImpersonation,
5409 DuplicateTokenHandle );
5412 /******************************************************************************
5413 * ComputeStringSidSize
5415 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
5417 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
5419 int ctok = 0;
5420 while (*StringSid)
5422 if (*StringSid == '-')
5423 ctok++;
5424 StringSid++;
5427 if (ctok >= 3)
5428 return GetSidLengthRequired(ctok - 2);
5430 else /* String constant format - Only available in winxp and above */
5432 unsigned int i;
5434 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5435 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5436 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
5438 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
5439 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
5441 MAX_SID local;
5442 ADVAPI_GetComputerSid(&local);
5443 return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1);
5448 return GetSidLengthRequired(0);
5451 /******************************************************************************
5452 * ParseStringSidToSid
5454 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
5456 BOOL bret = FALSE;
5457 SID* pisid=pSid;
5459 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
5460 if (!StringSid)
5462 SetLastError(ERROR_INVALID_PARAMETER);
5463 TRACE("StringSid is NULL, returning FALSE\n");
5464 return FALSE;
5467 while (*StringSid == ' ')
5468 StringSid++;
5470 *cBytes = ComputeStringSidSize(StringSid);
5471 if (!pisid) /* Simply compute the size */
5473 TRACE("only size requested, returning TRUE with %d\n", *cBytes);
5474 return TRUE;
5477 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
5479 DWORD i = 0, identAuth;
5480 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
5482 StringSid += 2; /* Advance to Revision */
5483 pisid->Revision = atoiW(StringSid);
5485 if (pisid->Revision != SDDL_REVISION)
5487 TRACE("Revision %d is unknown\n", pisid->Revision);
5488 goto lend; /* ERROR_INVALID_SID */
5490 if (csubauth == 0)
5492 TRACE("SubAuthorityCount is 0\n");
5493 goto lend; /* ERROR_INVALID_SID */
5496 pisid->SubAuthorityCount = csubauth;
5498 /* Advance to identifier authority */
5499 while (*StringSid && *StringSid != '-')
5500 StringSid++;
5501 if (*StringSid == '-')
5502 StringSid++;
5504 /* MS' implementation can't handle values greater than 2^32 - 1, so
5505 * we don't either; assume most significant bytes are always 0
5507 pisid->IdentifierAuthority.Value[0] = 0;
5508 pisid->IdentifierAuthority.Value[1] = 0;
5509 identAuth = atoiW(StringSid);
5510 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
5511 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
5512 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
5513 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
5515 /* Advance to first sub authority */
5516 while (*StringSid && *StringSid != '-')
5517 StringSid++;
5518 if (*StringSid == '-')
5519 StringSid++;
5521 while (*StringSid)
5523 pisid->SubAuthority[i++] = atoiW(StringSid);
5525 while (*StringSid && *StringSid != '-')
5526 StringSid++;
5527 if (*StringSid == '-')
5528 StringSid++;
5531 if (i != pisid->SubAuthorityCount)
5532 goto lend; /* ERROR_INVALID_SID */
5534 bret = TRUE;
5536 else /* String constant format - Only available in winxp and above */
5538 unsigned int i;
5539 pisid->Revision = SDDL_REVISION;
5541 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5542 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5544 DWORD j;
5545 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
5546 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
5547 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
5548 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
5549 bret = TRUE;
5552 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
5553 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
5555 ADVAPI_GetComputerSid(pisid);
5556 pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid;
5557 pisid->SubAuthorityCount++;
5558 bret = TRUE;
5561 if (!bret)
5562 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
5565 lend:
5566 if (!bret)
5567 SetLastError(ERROR_INVALID_SID);
5569 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
5570 return bret;
5573 /******************************************************************************
5574 * GetNamedSecurityInfoA [ADVAPI32.@]
5576 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
5577 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5578 PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
5579 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
5581 LPWSTR wstr;
5582 DWORD r;
5584 TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
5585 ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
5587 wstr = SERV_dup(pObjectName);
5588 r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
5589 ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
5591 heap_free( wstr );
5593 return r;
5596 /******************************************************************************
5597 * GetNamedSecurityInfoW [ADVAPI32.@]
5599 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
5600 SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
5601 PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
5603 DWORD access = 0;
5604 HANDLE handle;
5605 DWORD err;
5607 TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
5608 group, dacl, sacl, descriptor );
5610 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
5611 if (!name || !(owner||group||dacl||sacl||descriptor) ) return ERROR_INVALID_PARAMETER;
5613 /* If no descriptor, we have to check that there's a pointer for the requested information */
5614 if( !descriptor && (
5615 ((info & OWNER_SECURITY_INFORMATION) && !owner)
5616 || ((info & GROUP_SECURITY_INFORMATION) && !group)
5617 || ((info & DACL_SECURITY_INFORMATION) && !dacl)
5618 || ((info & SACL_SECURITY_INFORMATION) && !sacl) ))
5619 return ERROR_INVALID_PARAMETER;
5621 if (info & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION))
5622 access |= READ_CONTROL;
5623 if (info & SACL_SECURITY_INFORMATION)
5624 access |= ACCESS_SYSTEM_SECURITY;
5626 switch (type)
5628 case SE_SERVICE:
5629 if (!(err = get_security_service( name, access, &handle )))
5631 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5632 CloseServiceHandle( handle );
5634 break;
5635 case SE_REGISTRY_KEY:
5636 if (!(err = get_security_regkey( name, access, &handle )))
5638 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5639 RegCloseKey( handle );
5641 break;
5642 case SE_FILE_OBJECT:
5643 if (!(err = get_security_file( name, access, &handle )))
5645 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5646 CloseHandle( handle );
5648 break;
5649 default:
5650 FIXME( "Object type %d is not currently supported.\n", type );
5651 if (owner) *owner = NULL;
5652 if (group) *group = NULL;
5653 if (dacl) *dacl = NULL;
5654 if (sacl) *sacl = NULL;
5655 if (descriptor) *descriptor = NULL;
5656 return ERROR_SUCCESS;
5658 return err;
5661 /******************************************************************************
5662 * GetNamedSecurityInfoExW [ADVAPI32.@]
5664 DWORD WINAPI GetNamedSecurityInfoExW( LPCWSTR object, SE_OBJECT_TYPE type,
5665 SECURITY_INFORMATION info, LPCWSTR provider, LPCWSTR property,
5666 PACTRL_ACCESSW* access_list, PACTRL_AUDITW* audit_list, LPWSTR* owner, LPWSTR* group )
5668 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_w(object), type, info,
5669 debugstr_w(provider), debugstr_w(property), access_list, audit_list, owner, group);
5670 return ERROR_CALL_NOT_IMPLEMENTED;
5673 /******************************************************************************
5674 * GetNamedSecurityInfoExA [ADVAPI32.@]
5676 DWORD WINAPI GetNamedSecurityInfoExA( LPCSTR object, SE_OBJECT_TYPE type,
5677 SECURITY_INFORMATION info, LPCSTR provider, LPCSTR property,
5678 PACTRL_ACCESSA* access_list, PACTRL_AUDITA* audit_list, LPSTR* owner, LPSTR* group )
5680 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_a(object), type, info,
5681 debugstr_a(provider), debugstr_a(property), access_list, audit_list, owner, group);
5682 return ERROR_CALL_NOT_IMPLEMENTED;
5685 /******************************************************************************
5686 * DecryptFileW [ADVAPI32.@]
5688 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
5690 FIXME("(%s, %08x): stub\n", debugstr_w(lpFileName), dwReserved);
5691 return TRUE;
5694 /******************************************************************************
5695 * DecryptFileA [ADVAPI32.@]
5697 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
5699 FIXME("(%s, %08x): stub\n", debugstr_a(lpFileName), dwReserved);
5700 return TRUE;
5703 /******************************************************************************
5704 * EncryptFileW [ADVAPI32.@]
5706 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
5708 FIXME("(%s): stub\n", debugstr_w(lpFileName));
5709 return TRUE;
5712 /******************************************************************************
5713 * EncryptFileA [ADVAPI32.@]
5715 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
5717 FIXME("(%s): stub\n", debugstr_a(lpFileName));
5718 return TRUE;
5721 /******************************************************************************
5722 * FileEncryptionStatusW [ADVAPI32.@]
5724 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
5726 FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
5727 if (!lpStatus)
5728 return FALSE;
5729 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5730 return TRUE;
5733 /******************************************************************************
5734 * FileEncryptionStatusA [ADVAPI32.@]
5736 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
5738 FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
5739 if (!lpStatus)
5740 return FALSE;
5741 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5742 return TRUE;
5745 /******************************************************************************
5746 * SetSecurityInfo [ADVAPI32.@]
5748 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType,
5749 SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
5750 PSID psidGroup, PACL pDacl, PACL pSacl)
5752 SECURITY_DESCRIPTOR sd;
5753 PACL dacl = pDacl;
5754 NTSTATUS status;
5756 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
5757 return ERROR_INVALID_SECURITY_DESCR;
5759 if (SecurityInfo & OWNER_SECURITY_INFORMATION)
5760 SetSecurityDescriptorOwner(&sd, psidOwner, FALSE);
5761 if (SecurityInfo & GROUP_SECURITY_INFORMATION)
5762 SetSecurityDescriptorGroup(&sd, psidGroup, FALSE);
5763 if (SecurityInfo & DACL_SECURITY_INFORMATION)
5765 if (ObjectType == SE_FILE_OBJECT && pDacl)
5767 SECURITY_DESCRIPTOR_CONTROL control;
5768 PSECURITY_DESCRIPTOR psd;
5769 OBJECT_NAME_INFORMATION *name_info;
5770 DWORD size, rev;
5772 status = NtQuerySecurityObject(handle, SecurityInfo, NULL, 0, &size);
5773 if (status != STATUS_BUFFER_TOO_SMALL)
5774 return RtlNtStatusToDosError(status);
5776 psd = heap_alloc(size);
5777 if (!psd)
5778 return ERROR_NOT_ENOUGH_MEMORY;
5780 status = NtQuerySecurityObject(handle, SecurityInfo, psd, size, &size);
5781 if (status)
5783 heap_free(psd);
5784 return RtlNtStatusToDosError(status);
5787 status = RtlGetControlSecurityDescriptor(psd, &control, &rev);
5788 heap_free(psd);
5789 if (status)
5790 return RtlNtStatusToDosError(status);
5791 /* TODO: copy some control flags to new sd */
5793 /* inherit parent directory DACL */
5794 if (!(control & SE_DACL_PROTECTED))
5796 status = NtQueryObject(handle, ObjectNameInformation, NULL, 0, &size);
5797 if (status != STATUS_INFO_LENGTH_MISMATCH)
5798 return RtlNtStatusToDosError(status);
5800 name_info = heap_alloc(size);
5801 if (!name_info)
5802 return ERROR_NOT_ENOUGH_MEMORY;
5804 status = NtQueryObject(handle, ObjectNameInformation, name_info, size, NULL);
5805 if (status)
5807 heap_free(name_info);
5808 return RtlNtStatusToDosError(status);
5811 for (name_info->Name.Length-=2; name_info->Name.Length>0; name_info->Name.Length-=2)
5812 if (name_info->Name.Buffer[name_info->Name.Length/2-1]=='\\' ||
5813 name_info->Name.Buffer[name_info->Name.Length/2-1]=='/')
5814 break;
5815 if (name_info->Name.Length)
5817 OBJECT_ATTRIBUTES attr;
5818 IO_STATUS_BLOCK io;
5819 HANDLE parent;
5820 PSECURITY_DESCRIPTOR parent_sd;
5821 ACL *parent_dacl;
5822 DWORD err = ERROR_ACCESS_DENIED;
5824 name_info->Name.Buffer[name_info->Name.Length/2] = 0;
5826 attr.Length = sizeof(attr);
5827 attr.RootDirectory = 0;
5828 attr.Attributes = 0;
5829 attr.ObjectName = &name_info->Name;
5830 attr.SecurityDescriptor = NULL;
5831 status = NtOpenFile(&parent, READ_CONTROL, &attr, &io,
5832 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5833 FILE_OPEN_FOR_BACKUP_INTENT);
5834 heap_free(name_info);
5835 if (!status)
5837 err = GetSecurityInfo(parent, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
5838 NULL, NULL, &parent_dacl, NULL, &parent_sd);
5839 CloseHandle(parent);
5842 if (!err)
5844 int i;
5846 dacl = heap_alloc_zero(pDacl->AclSize+parent_dacl->AclSize);
5847 if (!dacl)
5849 LocalFree(parent_sd);
5850 return ERROR_NOT_ENOUGH_MEMORY;
5852 memcpy(dacl, pDacl, pDacl->AclSize);
5853 dacl->AclSize = pDacl->AclSize+parent_dacl->AclSize;
5855 for (i=0; i<parent_dacl->AceCount; i++)
5857 ACE_HEADER *ace;
5859 if (!GetAce(parent_dacl, i, (void*)&ace))
5860 continue;
5861 if (!(ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)))
5862 continue;
5863 if ((ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) !=
5864 (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE))
5866 FIXME("unsupported flags: %x\n", ace->AceFlags);
5867 continue;
5870 if (ace->AceFlags & NO_PROPAGATE_INHERIT_ACE)
5871 ace->AceFlags &= ~(OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE|NO_PROPAGATE_INHERIT_ACE);
5872 ace->AceFlags &= ~INHERIT_ONLY_ACE;
5873 ace->AceFlags |= INHERITED_ACE;
5875 if(!AddAce(dacl, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
5876 WARN("error adding inherited ACE\n");
5878 LocalFree(parent_sd);
5881 else
5882 heap_free(name_info);
5886 SetSecurityDescriptorDacl(&sd, TRUE, dacl, FALSE);
5888 if (SecurityInfo & SACL_SECURITY_INFORMATION)
5889 SetSecurityDescriptorSacl(&sd, TRUE, pSacl, FALSE);
5891 switch (ObjectType)
5893 case SE_SERVICE:
5894 FIXME("stub: Service objects are not supported at this time.\n");
5895 status = STATUS_SUCCESS; /* Implement SetServiceObjectSecurity */
5896 break;
5897 default:
5898 status = NtSetSecurityObject(handle, SecurityInfo, &sd);
5899 break;
5901 if (dacl != pDacl)
5902 heap_free(dacl);
5903 return RtlNtStatusToDosError(status);
5906 /******************************************************************************
5907 * SaferCreateLevel [ADVAPI32.@]
5909 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
5910 SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
5912 FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
5914 *LevelHandle = (SAFER_LEVEL_HANDLE)0xdeadbeef;
5915 return TRUE;
5918 /******************************************************************************
5919 * SaferComputeTokenFromLevel [ADVAPI32.@]
5921 BOOL WINAPI SaferComputeTokenFromLevel(SAFER_LEVEL_HANDLE handle, HANDLE token, PHANDLE access_token,
5922 DWORD flags, LPVOID reserved)
5924 FIXME("(%p, %p, %p, %x, %p) stub\n", handle, token, access_token, flags, reserved);
5926 *access_token = (HANDLE)0xdeadbeef;
5927 return TRUE;
5930 /******************************************************************************
5931 * SaferCloseLevel [ADVAPI32.@]
5933 BOOL WINAPI SaferCloseLevel(SAFER_LEVEL_HANDLE handle)
5935 FIXME("(%p) stub\n", handle);
5936 return TRUE;
5939 DWORD WINAPI TreeResetNamedSecurityInfoW( LPWSTR pObjectName,
5940 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5941 PSID pOwner, PSID pGroup, PACL pDacl, PACL pSacl,
5942 BOOL KeepExplicit, FN_PROGRESS fnProgress,
5943 PROG_INVOKE_SETTING ProgressInvokeSetting, PVOID Args)
5945 FIXME("(%s, %i, %i, %p, %p, %p, %p, %i, %p, %i, %p) stub\n",
5946 debugstr_w(pObjectName), ObjectType, SecurityInfo, pOwner, pGroup,
5947 pDacl, pSacl, KeepExplicit, fnProgress, ProgressInvokeSetting, Args);
5949 return ERROR_SUCCESS;
5952 /******************************************************************************
5953 * SaferGetPolicyInformation [ADVAPI32.@]
5955 BOOL WINAPI SaferGetPolicyInformation(DWORD scope, SAFER_POLICY_INFO_CLASS class, DWORD size,
5956 PVOID buffer, PDWORD required, LPVOID lpReserved)
5958 FIXME("(%u %u %u %p %p %p) stub\n", scope, class, size, buffer, required, lpReserved);
5959 return FALSE;
5962 /******************************************************************************
5963 * SaferSetLevelInformation [ADVAPI32.@]
5965 BOOL WINAPI SaferSetLevelInformation(SAFER_LEVEL_HANDLE handle, SAFER_OBJECT_INFO_CLASS infotype,
5966 LPVOID buffer, DWORD size)
5968 FIXME("(%p %u %p %u) stub\n", handle, infotype, buffer, size);
5969 return FALSE;