makefiles: Generate dependencies for static libraries.
[wine.git] / dlls / advapi32 / security.c
blob08f88c09f945f231934ef4a9dfc49dad7feebe8f
1 /*
2 * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
3 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
4 * Copyright 2006 Robert Reif
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
24 #include <stdarg.h>
25 #include <string.h>
27 #include "ntstatus.h"
28 #define WIN32_NO_STATUS
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "winreg.h"
33 #include "winsafer.h"
34 #include "winternl.h"
35 #include "winioctl.h"
36 #include "accctrl.h"
37 #include "sddl.h"
38 #include "winsvc.h"
39 #include "aclapi.h"
40 #include "objbase.h"
41 #include "iads.h"
42 #include "advapi32_misc.h"
43 #include "lmcons.h"
45 #include "wine/debug.h"
46 #include "wine/unicode.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
50 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes);
51 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
52 PACL pAcl, LPDWORD cBytes);
53 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl);
54 static BYTE ParseAceStringType(LPCWSTR* StringAcl);
55 static DWORD ParseAceStringRights(LPCWSTR* StringAcl);
56 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
57 LPCWSTR StringSecurityDescriptor,
58 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
59 LPDWORD cBytes);
60 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl);
62 typedef struct _ACEFLAG
64 LPCWSTR wstr;
65 DWORD value;
66 } ACEFLAG, *LPACEFLAG;
68 typedef struct _MAX_SID
70 /* same fields as struct _SID */
71 BYTE Revision;
72 BYTE SubAuthorityCount;
73 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
74 DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
75 } MAX_SID;
77 typedef struct WELLKNOWNSID
79 WCHAR wstr[2];
80 WELL_KNOWN_SID_TYPE Type;
81 MAX_SID Sid;
82 } WELLKNOWNSID;
84 static const WELLKNOWNSID WellKnownSids[] =
86 { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
87 { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
88 { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
89 { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
90 { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
91 { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
92 { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
93 { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
94 { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
95 { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
96 { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
97 { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
98 { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
99 { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
100 { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
101 { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
102 { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
103 { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
104 { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
105 { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
106 { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
107 { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
108 { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
109 { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
110 { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
111 { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
112 { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
113 { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
114 { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
115 { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
116 { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
117 { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
118 { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
119 { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
120 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
121 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
122 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
123 { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
124 { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
125 { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
126 { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
127 { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
128 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS } } },
129 { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
130 { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
131 { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
132 { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
133 { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
134 { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } },
135 { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } },
136 { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } },
137 { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } },
138 { {0,0}, WinBuiltinAnyPackageSid, { SID_REVISION, 2, { SECURITY_APP_PACKAGE_AUTHORITY }, { SECURITY_APP_PACKAGE_BASE_RID, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE } } },
141 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */
142 typedef struct WELLKNOWNRID
144 WCHAR wstr[2];
145 WELL_KNOWN_SID_TYPE Type;
146 DWORD Rid;
147 } WELLKNOWNRID;
149 static const WELLKNOWNRID WellKnownRids[] = {
150 { {'L','A'}, WinAccountAdministratorSid, DOMAIN_USER_RID_ADMIN },
151 { {'L','G'}, WinAccountGuestSid, DOMAIN_USER_RID_GUEST },
152 { {0,0}, WinAccountKrbtgtSid, DOMAIN_USER_RID_KRBTGT },
153 { {'D','A'}, WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS },
154 { {'D','U'}, WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS },
155 { {'D','G'}, WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS },
156 { {'D','C'}, WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS },
157 { {'D','D'}, WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS },
158 { {'C','A'}, WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS },
159 { {'S','A'}, WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS },
160 { {'E','A'}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
161 { {'P','A'}, WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS },
162 { {'R','S'}, WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
166 static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
168 typedef struct _AccountSid {
169 WELL_KNOWN_SID_TYPE type;
170 LPCWSTR account;
171 LPCWSTR domain;
172 SID_NAME_USE name_use;
173 LPCWSTR alias;
174 } AccountSid;
176 static const WCHAR Account_Operators[] = { 'A','c','c','o','u','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
177 static const WCHAR Administrator[] = {'A','d','m','i','n','i','s','t','r','a','t','o','r',0 };
178 static const WCHAR Administrators[] = { 'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0 };
179 static const WCHAR ALL_APPLICATION_PACKAGES[] = { 'A','L','L',' ','A','P','P','L','I','C','A','T','I','O','N',' ','P','A','C','K','A','G','E','S',0 };
180 static const WCHAR ANONYMOUS_LOGON[] = { 'A','N','O','N','Y','M','O','U','S',' ','L','O','G','O','N',0 };
181 static const WCHAR APPLICATION_PACKAGE_AUTHORITY[] = { 'A','P','P','L','I','C','A','T','I','O','N',' ','P','A','C','K','A','G','E',' ','A','U','T','H','O','R','I','T','Y',0 };
182 static const WCHAR Authenticated_Users[] = { 'A','u','t','h','e','n','t','i','c','a','t','e','d',' ','U','s','e','r','s',0 };
183 static const WCHAR Backup_Operators[] = { 'B','a','c','k','u','p',' ','O','p','e','r','a','t','o','r','s',0 };
184 static const WCHAR BATCH[] = { 'B','A','T','C','H',0 };
185 static const WCHAR Blank[] = { 0 };
186 static const WCHAR BUILTIN[] = { 'B','U','I','L','T','I','N',0 };
187 static const WCHAR Cert_Publishers[] = { 'C','e','r','t',' ','P','u','b','l','i','s','h','e','r','s',0 };
188 static const WCHAR CREATOR_GROUP[] = { 'C','R','E','A','T','O','R',' ','G','R','O','U','P',0 };
189 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 };
190 static const WCHAR CREATOR_OWNER[] = { 'C','R','E','A','T','O','R',' ','O','W','N','E','R',0 };
191 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 };
192 static const WCHAR CURRENT_USER[] = { 'C','U','R','R','E','N','T','_','U','S','E','R',0 };
193 static const WCHAR DIALUP[] = { 'D','I','A','L','U','P',0 };
194 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 };
195 static const WCHAR Domain_Admins[] = { 'D','o','m','a','i','n',' ','A','d','m','i','n','s',0 };
196 static const WCHAR Domain_Computers[] = { 'D','o','m','a','i','n',' ','C','o','m','p','u','t','e','r','s',0 };
197 static const WCHAR Domain_Controllers[] = { 'D','o','m','a','i','n',' ','C','o','n','t','r','o','l','l','e','r','s',0 };
198 static const WCHAR Domain_Guests[] = { 'D','o','m','a','i','n',' ','G','u','e','s','t','s',0 };
199 static const WCHAR Domain_Users[] = { 'D','o','m','a','i','n',' ','U','s','e','r','s',0 };
200 static const WCHAR Enterprise_Admins[] = { 'E','n','t','e','r','p','r','i','s','e',' ','A','d','m','i','n','s',0 };
201 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 };
202 static const WCHAR Everyone[] = { 'E','v','e','r','y','o','n','e',0 };
203 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 };
204 static const WCHAR Guest[] = { 'G','u','e','s','t',0 };
205 static const WCHAR Guests[] = { 'G','u','e','s','t','s',0 };
206 static const WCHAR INTERACTIVE[] = { 'I','N','T','E','R','A','C','T','I','V','E',0 };
207 static const WCHAR LOCAL[] = { 'L','O','C','A','L',0 };
208 static const WCHAR LOCAL_SERVICE[] = { 'L','O','C','A','L',' ','S','E','R','V','I','C','E',0 };
209 static const WCHAR LOCAL_SERVICE2[] = { 'L','O','C','A','L','S','E','R','V','I','C','E',0 };
210 static const WCHAR NETWORK[] = { 'N','E','T','W','O','R','K',0 };
211 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 };
212 static const WCHAR NETWORK_SERVICE[] = { 'N','E','T','W','O','R','K',' ','S','E','R','V','I','C','E',0 };
213 static const WCHAR NETWORK_SERVICE2[] = { 'N','E','T','W','O','R','K','S','E','R','V','I','C','E',0 };
214 static const WCHAR NT_AUTHORITY[] = { 'N','T',' ','A','U','T','H','O','R','I','T','Y',0 };
215 static const WCHAR NT_Pseudo_Domain[] = { 'N','T',' ','P','s','e','u','d','o',' ','D','o','m','a','i','n',0 };
216 static const WCHAR NTML_Authentication[] = { 'N','T','M','L',' ','A','u','t','h','e','n','t','i','c','a','t','i','o','n',0 };
217 static const WCHAR NULL_SID[] = { 'N','U','L','L',' ','S','I','D',0 };
218 static const WCHAR Other_Organization[] = { 'O','t','h','e','r',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
219 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 };
220 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 };
221 static const WCHAR Power_Users[] = { 'P','o','w','e','r',' ','U','s','e','r','s',0 };
222 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 };
223 static const WCHAR Print_Operators[] = { 'P','r','i','n','t',' ','O','p','e','r','a','t','o','r','s',0 };
224 static const WCHAR PROXY[] = { 'P','R','O','X','Y',0 };
225 static const WCHAR RAS_and_IAS_Servers[] = { 'R','A','S',' ','a','n','d',' ','I','A','S',' ','S','e','r','v','e','r','s',0 };
226 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 };
227 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 };
228 static const WCHAR Replicators[] = { 'R','e','p','l','i','c','a','t','o','r','s',0 };
229 static const WCHAR RESTRICTED[] = { 'R','E','S','T','R','I','C','T','E','D',0 };
230 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 };
231 static const WCHAR Schema_Admins[] = { 'S','c','h','e','m','a',' ','A','d','m','i','n','s',0 };
232 static const WCHAR SELF[] = { 'S','E','L','F',0 };
233 static const WCHAR Server_Operators[] = { 'S','e','r','v','e','r',' ','O','p','e','r','a','t','o','r','s',0 };
234 static const WCHAR SERVICE[] = { 'S','E','R','V','I','C','E',0 };
235 static const WCHAR SYSTEM[] = { 'S','Y','S','T','E','M',0 };
236 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 };
237 static const WCHAR This_Organization[] = { 'T','h','i','s',' ','O','r','g','a','n','i','z','a','t','i','o','n',0 };
238 static const WCHAR Users[] = { 'U','s','e','r','s',0 };
240 static const AccountSid ACCOUNT_SIDS[] = {
241 { WinNullSid, NULL_SID, Blank, SidTypeWellKnownGroup },
242 { WinWorldSid, Everyone, Blank, SidTypeWellKnownGroup },
243 { WinLocalSid, LOCAL, Blank, SidTypeWellKnownGroup },
244 { WinCreatorOwnerSid, CREATOR_OWNER, Blank, SidTypeWellKnownGroup },
245 { WinCreatorGroupSid, CREATOR_GROUP, Blank, SidTypeWellKnownGroup },
246 { WinCreatorOwnerServerSid, CREATOR_OWNER_SERVER, Blank, SidTypeWellKnownGroup },
247 { WinCreatorGroupServerSid, CREATOR_GROUP_SERVER, Blank, SidTypeWellKnownGroup },
248 { WinNtAuthoritySid, NT_Pseudo_Domain, NT_Pseudo_Domain, SidTypeDomain },
249 { WinDialupSid, DIALUP, NT_AUTHORITY, SidTypeWellKnownGroup },
250 { WinNetworkSid, NETWORK, NT_AUTHORITY, SidTypeWellKnownGroup },
251 { WinBatchSid, BATCH, NT_AUTHORITY, SidTypeWellKnownGroup },
252 { WinInteractiveSid, INTERACTIVE, NT_AUTHORITY, SidTypeWellKnownGroup },
253 { WinServiceSid, SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup },
254 { WinAnonymousSid, ANONYMOUS_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
255 { WinProxySid, PROXY, NT_AUTHORITY, SidTypeWellKnownGroup },
256 { WinEnterpriseControllersSid, ENTERPRISE_DOMAIN_CONTROLLERS, NT_AUTHORITY, SidTypeWellKnownGroup },
257 { WinSelfSid, SELF, NT_AUTHORITY, SidTypeWellKnownGroup },
258 { WinAuthenticatedUserSid, Authenticated_Users, NT_AUTHORITY, SidTypeWellKnownGroup },
259 { WinRestrictedCodeSid, RESTRICTED, NT_AUTHORITY, SidTypeWellKnownGroup },
260 { WinTerminalServerSid, TERMINAL_SERVER_USER, NT_AUTHORITY, SidTypeWellKnownGroup },
261 { WinRemoteLogonIdSid, REMOTE_INTERACTIVE_LOGON, NT_AUTHORITY, SidTypeWellKnownGroup },
262 { WinLocalSystemSid, SYSTEM, NT_AUTHORITY, SidTypeWellKnownGroup },
263 { WinLocalServiceSid, LOCAL_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup, LOCAL_SERVICE2 },
264 { WinNetworkServiceSid, NETWORK_SERVICE, NT_AUTHORITY, SidTypeWellKnownGroup , NETWORK_SERVICE2},
265 { WinBuiltinDomainSid, BUILTIN, BUILTIN, SidTypeDomain },
266 { WinBuiltinAdministratorsSid, Administrators, BUILTIN, SidTypeAlias },
267 { WinBuiltinUsersSid, Users, BUILTIN, SidTypeAlias },
268 { WinBuiltinGuestsSid, Guests, BUILTIN, SidTypeAlias },
269 { WinBuiltinPowerUsersSid, Power_Users, BUILTIN, SidTypeAlias },
270 { WinBuiltinAccountOperatorsSid, Account_Operators, BUILTIN, SidTypeAlias },
271 { WinBuiltinSystemOperatorsSid, Server_Operators, BUILTIN, SidTypeAlias },
272 { WinBuiltinPrintOperatorsSid, Print_Operators, BUILTIN, SidTypeAlias },
273 { WinBuiltinBackupOperatorsSid, Backup_Operators, BUILTIN, SidTypeAlias },
274 { WinBuiltinReplicatorSid, Replicators, BUILTIN, SidTypeAlias },
275 { WinBuiltinPreWindows2000CompatibleAccessSid, Pre_Windows_2000_Compatible_Access, BUILTIN, SidTypeAlias },
276 { WinBuiltinRemoteDesktopUsersSid, Remote_Desktop_Users, BUILTIN, SidTypeAlias },
277 { WinBuiltinNetworkConfigurationOperatorsSid, Network_Configuration_Operators, BUILTIN, SidTypeAlias },
278 { WinNTLMAuthenticationSid, NTML_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
279 { WinDigestAuthenticationSid, Digest_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
280 { WinSChannelAuthenticationSid, SChannel_Authentication, NT_AUTHORITY, SidTypeWellKnownGroup },
281 { WinThisOrganizationSid, This_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
282 { WinOtherOrganizationSid, Other_Organization, NT_AUTHORITY, SidTypeWellKnownGroup },
283 { WinBuiltinPerfMonitoringUsersSid, Performance_Monitor_Users, BUILTIN, SidTypeAlias },
284 { WinBuiltinPerfLoggingUsersSid, Performance_Log_Users, BUILTIN, SidTypeAlias },
285 { WinBuiltinAnyPackageSid, ALL_APPLICATION_PACKAGES, APPLICATION_PACKAGE_AUTHORITY, SidTypeWellKnownGroup },
288 * ACE access rights
290 static const WCHAR SDDL_READ_CONTROL[] = {'R','C',0};
291 static const WCHAR SDDL_WRITE_DAC[] = {'W','D',0};
292 static const WCHAR SDDL_WRITE_OWNER[] = {'W','O',0};
293 static const WCHAR SDDL_STANDARD_DELETE[] = {'S','D',0};
295 static const WCHAR SDDL_READ_PROPERTY[] = {'R','P',0};
296 static const WCHAR SDDL_WRITE_PROPERTY[] = {'W','P',0};
297 static const WCHAR SDDL_CREATE_CHILD[] = {'C','C',0};
298 static const WCHAR SDDL_DELETE_CHILD[] = {'D','C',0};
299 static const WCHAR SDDL_LIST_CHILDREN[] = {'L','C',0};
300 static const WCHAR SDDL_SELF_WRITE[] = {'S','W',0};
301 static const WCHAR SDDL_LIST_OBJECT[] = {'L','O',0};
302 static const WCHAR SDDL_DELETE_TREE[] = {'D','T',0};
303 static const WCHAR SDDL_CONTROL_ACCESS[] = {'C','R',0};
305 static const WCHAR SDDL_FILE_ALL[] = {'F','A',0};
306 static const WCHAR SDDL_FILE_READ[] = {'F','R',0};
307 static const WCHAR SDDL_FILE_WRITE[] = {'F','W',0};
308 static const WCHAR SDDL_FILE_EXECUTE[] = {'F','X',0};
310 static const WCHAR SDDL_KEY_ALL[] = {'K','A',0};
311 static const WCHAR SDDL_KEY_READ[] = {'K','R',0};
312 static const WCHAR SDDL_KEY_WRITE[] = {'K','W',0};
313 static const WCHAR SDDL_KEY_EXECUTE[] = {'K','X',0};
315 static const WCHAR SDDL_GENERIC_ALL[] = {'G','A',0};
316 static const WCHAR SDDL_GENERIC_READ[] = {'G','R',0};
317 static const WCHAR SDDL_GENERIC_WRITE[] = {'G','W',0};
318 static const WCHAR SDDL_GENERIC_EXECUTE[] = {'G','X',0};
320 static const WCHAR SDDL_NO_READ_UP[] = {'N','R',0};
321 static const WCHAR SDDL_NO_WRITE_UP[] = {'N','W',0};
322 static const WCHAR SDDL_NO_EXECUTE_UP[] = {'N','X',0};
325 * ACL flags
327 static const WCHAR SDDL_PROTECTED[] = {'P',0};
328 static const WCHAR SDDL_AUTO_INHERIT_REQ[] = {'A','R',0};
329 static const WCHAR SDDL_AUTO_INHERITED[] = {'A','I',0};
332 * ACE types
334 static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0};
335 static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0};
336 static const WCHAR SDDL_AUDIT[] = {'A','U',0};
337 static const WCHAR SDDL_ALARM[] = {'A','L',0};
338 static const WCHAR SDDL_MANDATORY_LABEL[] = {'M','L',0};
341 * ACE flags
343 static const WCHAR SDDL_CONTAINER_INHERIT[] = {'C','I',0};
344 static const WCHAR SDDL_OBJECT_INHERIT[] = {'O','I',0};
345 static const WCHAR SDDL_NO_PROPAGATE[] = {'N','P',0};
346 static const WCHAR SDDL_INHERIT_ONLY[] = {'I','O',0};
347 static const WCHAR SDDL_INHERITED[] = {'I','D',0};
348 static const WCHAR SDDL_AUDIT_SUCCESS[] = {'S','A',0};
349 static const WCHAR SDDL_AUDIT_FAILURE[] = {'F','A',0};
351 const char * debugstr_sid(PSID sid)
353 int auth = 0;
354 SID * psid = sid;
356 if (psid == NULL)
357 return "(null)";
359 auth = psid->IdentifierAuthority.Value[5] +
360 (psid->IdentifierAuthority.Value[4] << 8) +
361 (psid->IdentifierAuthority.Value[3] << 16) +
362 (psid->IdentifierAuthority.Value[2] << 24);
364 switch (psid->SubAuthorityCount) {
365 case 0:
366 return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
367 case 1:
368 return wine_dbg_sprintf("S-%d-%d-%u", psid->Revision, auth,
369 psid->SubAuthority[0]);
370 case 2:
371 return wine_dbg_sprintf("S-%d-%d-%u-%u", psid->Revision, auth,
372 psid->SubAuthority[0], psid->SubAuthority[1]);
373 case 3:
374 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u", psid->Revision, auth,
375 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
376 case 4:
377 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u", psid->Revision, auth,
378 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
379 psid->SubAuthority[3]);
380 case 5:
381 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u", psid->Revision, auth,
382 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
383 psid->SubAuthority[3], psid->SubAuthority[4]);
384 case 6:
385 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
386 psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
387 psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
388 case 7:
389 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
390 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
391 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
392 psid->SubAuthority[6]);
393 case 8:
394 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
395 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
396 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
397 psid->SubAuthority[6], psid->SubAuthority[7]);
399 return "(too-big)";
402 /* set last error code from NT status and get the proper boolean return value */
403 /* used for functions that are a simple wrapper around the corresponding ntdll API */
404 static inline BOOL set_ntstatus( NTSTATUS status )
406 if (status) SetLastError( RtlNtStatusToDosError( status ));
407 return !status;
410 /* helper function for SE_FILE_OBJECT objects in [Get|Set]NamedSecurityInfo */
411 static inline DWORD get_security_file( LPCWSTR full_file_name, DWORD access, HANDLE *file )
413 UNICODE_STRING file_nameW;
414 OBJECT_ATTRIBUTES attr;
415 IO_STATUS_BLOCK io;
416 NTSTATUS status;
418 if (!RtlDosPathNameToNtPathName_U( full_file_name, &file_nameW, NULL, NULL ))
419 return ERROR_PATH_NOT_FOUND;
420 attr.Length = sizeof(attr);
421 attr.RootDirectory = 0;
422 attr.Attributes = OBJ_CASE_INSENSITIVE;
423 attr.ObjectName = &file_nameW;
424 attr.SecurityDescriptor = NULL;
425 status = NtCreateFile( file, access|SYNCHRONIZE, &attr, &io, NULL, FILE_FLAG_BACKUP_SEMANTICS,
426 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
427 FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 );
428 RtlFreeUnicodeString( &file_nameW );
429 return RtlNtStatusToDosError( status );
432 /* helper function for SE_SERVICE objects in [Get|Set]NamedSecurityInfo */
433 static inline DWORD get_security_service( LPWSTR full_service_name, DWORD access, HANDLE *service )
435 SC_HANDLE manager = 0;
436 DWORD err;
438 err = SERV_OpenSCManagerW( NULL, NULL, access, (SC_HANDLE *)&manager );
439 if (err == ERROR_SUCCESS)
441 err = SERV_OpenServiceW( manager, full_service_name, access, (SC_HANDLE *)service );
442 CloseServiceHandle( manager );
444 return err;
447 /* helper function for SE_REGISTRY_KEY objects in [Get|Set]NamedSecurityInfo */
448 static inline DWORD get_security_regkey( LPWSTR full_key_name, DWORD access, HANDLE *key )
450 WCHAR classes_rootW[] = {'C','L','A','S','S','E','S','_','R','O','O','T',0};
451 WCHAR current_userW[] = {'C','U','R','R','E','N','T','_','U','S','E','R',0};
452 WCHAR machineW[] = {'M','A','C','H','I','N','E',0};
453 WCHAR usersW[] = {'U','S','E','R','S',0};
454 LPWSTR p = strchrW(full_key_name, '\\');
455 int len = p-full_key_name;
456 HKEY hParent;
458 if (!p) return ERROR_INVALID_PARAMETER;
459 if (strncmpW( full_key_name, classes_rootW, len ) == 0)
460 hParent = HKEY_CLASSES_ROOT;
461 else if (strncmpW( full_key_name, current_userW, len ) == 0)
462 hParent = HKEY_CURRENT_USER;
463 else if (strncmpW( full_key_name, machineW, len ) == 0)
464 hParent = HKEY_LOCAL_MACHINE;
465 else if (strncmpW( full_key_name, usersW, len ) == 0)
466 hParent = HKEY_USERS;
467 else
468 return ERROR_INVALID_PARAMETER;
469 return RegOpenKeyExW( hParent, p+1, 0, access, (HKEY *)key );
472 #define WINE_SIZE_OF_WORLD_ACCESS_ACL (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD))
474 static void GetWorldAccessACL(PACL pACL)
476 PACCESS_ALLOWED_ACE pACE = (PACCESS_ALLOWED_ACE) (pACL + 1);
478 pACL->AclRevision = ACL_REVISION;
479 pACL->Sbz1 = 0;
480 pACL->AclSize = WINE_SIZE_OF_WORLD_ACCESS_ACL;
481 pACL->AceCount = 1;
482 pACL->Sbz2 = 0;
484 pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
485 pACE->Header.AceFlags = CONTAINER_INHERIT_ACE;
486 pACE->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD);
487 pACE->Mask = 0xf3ffffff; /* Everything except reserved bits */
488 memcpy(&pACE->SidStart, &sidWorld, sizeof(sidWorld));
491 /************************************************************
492 * ADVAPI_IsLocalComputer
494 * Checks whether the server name indicates local machine.
496 BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName)
498 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
499 BOOL Result;
500 LPWSTR buf;
502 if (!ServerName || !ServerName[0])
503 return TRUE;
505 buf = heap_alloc(dwSize * sizeof(WCHAR));
506 Result = GetComputerNameW(buf, &dwSize);
507 if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
508 ServerName += 2;
509 Result = Result && !lstrcmpW(ServerName, buf);
510 heap_free(buf);
512 return Result;
515 /************************************************************
516 * ADVAPI_GetComputerSid
518 BOOL ADVAPI_GetComputerSid(PSID sid)
520 static const struct /* same fields as struct SID */
522 BYTE Revision;
523 BYTE SubAuthorityCount;
524 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
525 DWORD SubAuthority[4];
526 } computer_sid =
527 { SID_REVISION, 4, { SECURITY_NT_AUTHORITY }, { SECURITY_NT_NON_UNIQUE, 0, 0, 0 } };
529 memcpy( sid, &computer_sid, sizeof(computer_sid) );
530 return TRUE;
533 /* ##############################
534 ###### TOKEN FUNCTIONS ######
535 ##############################
538 /******************************************************************************
539 * OpenProcessToken [ADVAPI32.@]
540 * Opens the access token associated with a process handle.
542 * PARAMS
543 * ProcessHandle [I] Handle to process
544 * DesiredAccess [I] Desired access to process
545 * TokenHandle [O] Pointer to handle of open access token
547 * RETURNS
548 * Success: TRUE. TokenHandle contains the access token.
549 * Failure: FALSE.
551 * NOTES
552 * See NtOpenProcessToken.
554 BOOL WINAPI
555 OpenProcessToken( HANDLE ProcessHandle, DWORD DesiredAccess,
556 HANDLE *TokenHandle )
558 return set_ntstatus(NtOpenProcessToken( ProcessHandle, DesiredAccess, TokenHandle ));
561 /******************************************************************************
562 * OpenThreadToken [ADVAPI32.@]
564 * Opens the access token associated with a thread handle.
566 * PARAMS
567 * ThreadHandle [I] Handle to process
568 * DesiredAccess [I] Desired access to the thread
569 * OpenAsSelf [I] ???
570 * TokenHandle [O] Destination for the token handle
572 * RETURNS
573 * Success: TRUE. TokenHandle contains the access token.
574 * Failure: FALSE.
576 * NOTES
577 * See NtOpenThreadToken.
579 BOOL WINAPI
580 OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess,
581 BOOL OpenAsSelf, HANDLE *TokenHandle)
583 return set_ntstatus( NtOpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle));
586 BOOL WINAPI
587 AdjustTokenGroups( HANDLE TokenHandle, BOOL ResetToDefault, PTOKEN_GROUPS NewState,
588 DWORD BufferLength, PTOKEN_GROUPS PreviousState, PDWORD ReturnLength )
590 return set_ntstatus( NtAdjustGroupsToken(TokenHandle, ResetToDefault, NewState, BufferLength,
591 PreviousState, ReturnLength));
594 /******************************************************************************
595 * AdjustTokenPrivileges [ADVAPI32.@]
597 * Adjust the privileges of an open token handle.
599 * PARAMS
600 * TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
601 * DisableAllPrivileges [I] TRUE=Remove all privileges, FALSE=Use NewState
602 * NewState [I] Desired new privileges of the token
603 * BufferLength [I] Length of NewState
604 * PreviousState [O] Destination for the previous state
605 * ReturnLength [I/O] Size of PreviousState
608 * RETURNS
609 * Success: TRUE. Privileges are set to NewState and PreviousState is updated.
610 * Failure: FALSE.
612 * NOTES
613 * See NtAdjustPrivilegesToken.
615 BOOL WINAPI
616 AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges,
617 PTOKEN_PRIVILEGES NewState, DWORD BufferLength,
618 PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength )
620 NTSTATUS status;
622 TRACE("(%p %d %p %d %p %p)\n", TokenHandle, DisableAllPrivileges, NewState, BufferLength,
623 PreviousState, ReturnLength);
625 status = NtAdjustPrivilegesToken(TokenHandle, DisableAllPrivileges,
626 NewState, BufferLength, PreviousState,
627 ReturnLength);
628 SetLastError( RtlNtStatusToDosError( status ));
629 if ((status == STATUS_SUCCESS) || (status == STATUS_NOT_ALL_ASSIGNED))
630 return TRUE;
631 else
632 return FALSE;
635 /******************************************************************************
636 * CheckTokenMembership [ADVAPI32.@]
638 * Determine if an access token is a member of a SID.
640 * PARAMS
641 * TokenHandle [I] Handle from OpenProcessToken() or OpenThreadToken()
642 * SidToCheck [I] SID that possibly contains the token
643 * IsMember [O] Destination for result.
645 * RETURNS
646 * Success: TRUE. IsMember is TRUE if TokenHandle is a member, FALSE otherwise.
647 * Failure: FALSE.
649 BOOL WINAPI
650 CheckTokenMembership( HANDLE token, PSID sid_to_check,
651 PBOOL is_member )
653 PTOKEN_GROUPS token_groups = NULL;
654 HANDLE thread_token = NULL;
655 DWORD size, i;
656 BOOL ret;
658 TRACE("(%p %s %p)\n", token, debugstr_sid(sid_to_check), is_member);
660 *is_member = FALSE;
662 if (!token)
664 if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &thread_token))
666 HANDLE process_token;
667 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &process_token);
668 if (!ret)
669 goto exit;
670 ret = DuplicateTokenEx(process_token, TOKEN_QUERY,
671 NULL, SecurityImpersonation, TokenImpersonation,
672 &thread_token);
673 CloseHandle(process_token);
674 if (!ret)
675 goto exit;
677 token = thread_token;
679 else
681 TOKEN_TYPE type;
683 ret = GetTokenInformation(token, TokenType, &type, sizeof(TOKEN_TYPE), &size);
684 if (!ret) goto exit;
686 if (type == TokenPrimary)
688 SetLastError(ERROR_NO_IMPERSONATION_TOKEN);
689 return FALSE;
693 ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
694 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
695 goto exit;
697 token_groups = heap_alloc(size);
698 if (!token_groups)
700 ret = FALSE;
701 goto exit;
704 ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
705 if (!ret)
706 goto exit;
708 for (i = 0; i < token_groups->GroupCount; i++)
710 TRACE("Groups[%d]: {0x%x, %s}\n", i,
711 token_groups->Groups[i].Attributes,
712 debugstr_sid(token_groups->Groups[i].Sid));
713 if ((token_groups->Groups[i].Attributes & SE_GROUP_ENABLED) &&
714 EqualSid(sid_to_check, token_groups->Groups[i].Sid))
716 *is_member = TRUE;
717 TRACE("sid enabled and found in token\n");
718 break;
722 exit:
723 heap_free(token_groups);
724 if (thread_token != NULL) CloseHandle(thread_token);
726 return ret;
729 /******************************************************************************
730 * GetTokenInformation [ADVAPI32.@]
732 * Get a type of information about an access token.
734 * PARAMS
735 * token [I] Handle from OpenProcessToken() or OpenThreadToken()
736 * tokeninfoclass [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
737 * tokeninfo [O] Destination for token information
738 * tokeninfolength [I] Length of tokeninfo
739 * retlen [O] Destination for returned token information length
741 * RETURNS
742 * Success: TRUE. tokeninfo contains retlen bytes of token information
743 * Failure: FALSE.
745 * NOTES
746 * See NtQueryInformationToken.
748 BOOL WINAPI
749 GetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
750 LPVOID tokeninfo, DWORD tokeninfolength, LPDWORD retlen )
752 TRACE("(%p, %s, %p, %d, %p):\n",
753 token,
754 (tokeninfoclass == TokenUser) ? "TokenUser" :
755 (tokeninfoclass == TokenGroups) ? "TokenGroups" :
756 (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
757 (tokeninfoclass == TokenOwner) ? "TokenOwner" :
758 (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
759 (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
760 (tokeninfoclass == TokenSource) ? "TokenSource" :
761 (tokeninfoclass == TokenType) ? "TokenType" :
762 (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
763 (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
764 (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
765 (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
766 (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
767 (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
768 (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
769 "Unknown",
770 tokeninfo, tokeninfolength, retlen);
771 return set_ntstatus( NtQueryInformationToken( token, tokeninfoclass, tokeninfo,
772 tokeninfolength, retlen));
775 /******************************************************************************
776 * SetTokenInformation [ADVAPI32.@]
778 * Set information for an access token.
780 * PARAMS
781 * token [I] Handle from OpenProcessToken() or OpenThreadToken()
782 * tokeninfoclass [I] A TOKEN_INFORMATION_CLASS from "winnt.h"
783 * tokeninfo [I] Token information to set
784 * tokeninfolength [I] Length of tokeninfo
786 * RETURNS
787 * Success: TRUE. The information for the token is set to tokeninfo.
788 * Failure: FALSE.
790 BOOL WINAPI
791 SetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass,
792 LPVOID tokeninfo, DWORD tokeninfolength )
794 TRACE("(%p, %s, %p, %d): stub\n",
795 token,
796 (tokeninfoclass == TokenUser) ? "TokenUser" :
797 (tokeninfoclass == TokenGroups) ? "TokenGroups" :
798 (tokeninfoclass == TokenPrivileges) ? "TokenPrivileges" :
799 (tokeninfoclass == TokenOwner) ? "TokenOwner" :
800 (tokeninfoclass == TokenPrimaryGroup) ? "TokenPrimaryGroup" :
801 (tokeninfoclass == TokenDefaultDacl) ? "TokenDefaultDacl" :
802 (tokeninfoclass == TokenSource) ? "TokenSource" :
803 (tokeninfoclass == TokenType) ? "TokenType" :
804 (tokeninfoclass == TokenImpersonationLevel) ? "TokenImpersonationLevel" :
805 (tokeninfoclass == TokenStatistics) ? "TokenStatistics" :
806 (tokeninfoclass == TokenRestrictedSids) ? "TokenRestrictedSids" :
807 (tokeninfoclass == TokenSessionId) ? "TokenSessionId" :
808 (tokeninfoclass == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
809 (tokeninfoclass == TokenSessionReference) ? "TokenSessionReference" :
810 (tokeninfoclass == TokenSandBoxInert) ? "TokenSandBoxInert" :
811 "Unknown",
812 tokeninfo, tokeninfolength);
814 return set_ntstatus( NtSetInformationToken( token, tokeninfoclass, tokeninfo, tokeninfolength ));
817 /*************************************************************************
818 * SetThreadToken [ADVAPI32.@]
820 * Assigns an 'impersonation token' to a thread so it can assume the
821 * security privileges of another thread or process. Can also remove
822 * a previously assigned token.
824 * PARAMS
825 * thread [O] Handle to thread to set the token for
826 * token [I] Token to set
828 * RETURNS
829 * Success: TRUE. The threads access token is set to token
830 * Failure: FALSE.
832 * NOTES
833 * Only supported on NT or higher. On Win9X this function does nothing.
834 * See SetTokenInformation.
836 BOOL WINAPI SetThreadToken(PHANDLE thread, HANDLE token)
838 return set_ntstatus( NtSetInformationThread( thread ? *thread : GetCurrentThread(),
839 ThreadImpersonationToken, &token, sizeof token ));
842 /*************************************************************************
843 * CreateRestrictedToken [ADVAPI32.@]
845 * Create a new more restricted token from an existing token.
847 * PARAMS
848 * baseToken [I] Token to base the new restricted token on
849 * flags [I] Options
850 * nDisableSids [I] Length of disableSids array
851 * disableSids [I] Array of SIDs to disable in the new token
852 * nDeletePrivs [I] Length of deletePrivs array
853 * deletePrivs [I] Array of privileges to delete in the new token
854 * nRestrictSids [I] Length of restrictSids array
855 * restrictSids [I] Array of SIDs to restrict in the new token
856 * newToken [O] Address where the new token is stored
858 * RETURNS
859 * Success: TRUE
860 * Failure: FALSE
862 BOOL WINAPI CreateRestrictedToken(
863 HANDLE baseToken,
864 DWORD flags,
865 DWORD nDisableSids,
866 PSID_AND_ATTRIBUTES disableSids,
867 DWORD nDeletePrivs,
868 PLUID_AND_ATTRIBUTES deletePrivs,
869 DWORD nRestrictSids,
870 PSID_AND_ATTRIBUTES restrictSids,
871 PHANDLE newToken)
873 TOKEN_TYPE type;
874 SECURITY_IMPERSONATION_LEVEL level = SecurityAnonymous;
875 DWORD size;
877 FIXME("(%p, 0x%x, %u, %p, %u, %p, %u, %p, %p): stub\n",
878 baseToken, flags, nDisableSids, disableSids,
879 nDeletePrivs, deletePrivs,
880 nRestrictSids, restrictSids,
881 newToken);
883 size = sizeof(type);
884 if (!GetTokenInformation( baseToken, TokenType, &type, size, &size )) return FALSE;
885 if (type == TokenImpersonation)
887 size = sizeof(level);
888 if (!GetTokenInformation( baseToken, TokenImpersonationLevel, &level, size, &size ))
889 return FALSE;
891 return DuplicateTokenEx( baseToken, MAXIMUM_ALLOWED, NULL, level, type, newToken );
894 /* ##############################
895 ###### SID FUNCTIONS ######
896 ##############################
899 /******************************************************************************
900 * AllocateAndInitializeSid [ADVAPI32.@]
902 * PARAMS
903 * pIdentifierAuthority []
904 * nSubAuthorityCount []
905 * nSubAuthority0 []
906 * nSubAuthority1 []
907 * nSubAuthority2 []
908 * nSubAuthority3 []
909 * nSubAuthority4 []
910 * nSubAuthority5 []
911 * nSubAuthority6 []
912 * nSubAuthority7 []
913 * pSid []
915 BOOL WINAPI
916 AllocateAndInitializeSid( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
917 BYTE nSubAuthorityCount,
918 DWORD nSubAuthority0, DWORD nSubAuthority1,
919 DWORD nSubAuthority2, DWORD nSubAuthority3,
920 DWORD nSubAuthority4, DWORD nSubAuthority5,
921 DWORD nSubAuthority6, DWORD nSubAuthority7,
922 PSID *pSid )
924 return set_ntstatus( RtlAllocateAndInitializeSid(
925 pIdentifierAuthority, nSubAuthorityCount,
926 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
927 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7,
928 pSid ));
931 /******************************************************************************
932 * FreeSid [ADVAPI32.@]
934 * PARAMS
935 * pSid []
937 PVOID WINAPI
938 FreeSid( PSID pSid )
940 RtlFreeSid(pSid);
941 return NULL; /* is documented like this */
944 /******************************************************************************
945 * CopySid [ADVAPI32.@]
947 * PARAMS
948 * nDestinationSidLength []
949 * pDestinationSid []
950 * pSourceSid []
952 BOOL WINAPI
953 CopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
955 return RtlCopySid(nDestinationSidLength, pDestinationSid, pSourceSid);
958 /******************************************************************************
959 * CreateWellKnownSid [ADVAPI32.@]
961 BOOL WINAPI
962 CreateWellKnownSid( WELL_KNOWN_SID_TYPE WellKnownSidType,
963 PSID DomainSid,
964 PSID pSid,
965 DWORD* cbSid)
967 unsigned int i;
968 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
970 if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
972 SetLastError(ERROR_INVALID_PARAMETER);
973 return FALSE;
976 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
977 if (WellKnownSids[i].Type == WellKnownSidType) {
978 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
980 if (*cbSid < length)
982 *cbSid = length;
983 SetLastError(ERROR_INSUFFICIENT_BUFFER);
984 return FALSE;
986 if (!pSid)
988 SetLastError(ERROR_INVALID_PARAMETER);
989 return FALSE;
991 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
992 *cbSid = length;
993 return TRUE;
997 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
999 SetLastError(ERROR_INVALID_PARAMETER);
1000 return FALSE;
1003 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
1004 if (WellKnownRids[i].Type == WellKnownSidType) {
1005 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
1006 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
1007 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
1009 if (*cbSid < output_sid_length)
1011 *cbSid = output_sid_length;
1012 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1013 return FALSE;
1015 if (!pSid)
1017 SetLastError(ERROR_INVALID_PARAMETER);
1018 return FALSE;
1020 CopyMemory(pSid, DomainSid, domain_sid_length);
1021 (*GetSidSubAuthorityCount(pSid))++;
1022 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
1023 *cbSid = output_sid_length;
1024 return TRUE;
1027 SetLastError(ERROR_INVALID_PARAMETER);
1028 return FALSE;
1031 /******************************************************************************
1032 * IsWellKnownSid [ADVAPI32.@]
1034 BOOL WINAPI
1035 IsWellKnownSid( PSID pSid, WELL_KNOWN_SID_TYPE WellKnownSidType )
1037 unsigned int i;
1038 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
1040 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
1041 if (WellKnownSids[i].Type == WellKnownSidType)
1042 if (EqualSid(pSid, (PSID)&(WellKnownSids[i].Sid.Revision)))
1043 return TRUE;
1045 return FALSE;
1048 BOOL WINAPI
1049 IsTokenRestricted( HANDLE TokenHandle )
1051 TOKEN_GROUPS *groups;
1052 DWORD size;
1053 NTSTATUS status;
1054 BOOL restricted;
1056 TRACE("(%p)\n", TokenHandle);
1058 status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, NULL, 0, &size);
1059 if (status != STATUS_BUFFER_TOO_SMALL)
1060 return FALSE;
1062 groups = heap_alloc(size);
1063 if (!groups)
1065 SetLastError(ERROR_OUTOFMEMORY);
1066 return FALSE;
1069 status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, groups, size, &size);
1070 if (status != STATUS_SUCCESS)
1072 heap_free(groups);
1073 return set_ntstatus(status);
1076 restricted = groups->GroupCount > 0;
1077 heap_free(groups);
1079 return restricted;
1082 /******************************************************************************
1083 * IsValidSid [ADVAPI32.@]
1085 * PARAMS
1086 * pSid []
1088 BOOL WINAPI
1089 IsValidSid( PSID pSid )
1091 return RtlValidSid( pSid );
1094 /******************************************************************************
1095 * EqualSid [ADVAPI32.@]
1097 * PARAMS
1098 * pSid1 []
1099 * pSid2 []
1101 BOOL WINAPI
1102 EqualSid( PSID pSid1, PSID pSid2 )
1104 BOOL ret = RtlEqualSid( pSid1, pSid2 );
1105 SetLastError(ERROR_SUCCESS);
1106 return ret;
1109 /******************************************************************************
1110 * EqualPrefixSid [ADVAPI32.@]
1112 BOOL WINAPI EqualPrefixSid (PSID pSid1, PSID pSid2)
1114 return RtlEqualPrefixSid(pSid1, pSid2);
1117 /******************************************************************************
1118 * GetSidLengthRequired [ADVAPI32.@]
1120 * PARAMS
1121 * nSubAuthorityCount []
1123 DWORD WINAPI
1124 GetSidLengthRequired( BYTE nSubAuthorityCount )
1126 return RtlLengthRequiredSid(nSubAuthorityCount);
1129 /******************************************************************************
1130 * InitializeSid [ADVAPI32.@]
1132 * PARAMS
1133 * pIdentifierAuthority []
1135 BOOL WINAPI
1136 InitializeSid (
1137 PSID pSid,
1138 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
1139 BYTE nSubAuthorityCount)
1141 return RtlInitializeSid(pSid, pIdentifierAuthority, nSubAuthorityCount);
1144 DWORD WINAPI
1145 GetEffectiveRightsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pAccessRights )
1147 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1149 *pAccessRights = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
1150 return 0;
1153 DWORD WINAPI
1154 GetEffectiveRightsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pAccessRights )
1156 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
1158 return 1;
1161 /******************************************************************************
1162 * GetSidIdentifierAuthority [ADVAPI32.@]
1164 * PARAMS
1165 * pSid []
1167 PSID_IDENTIFIER_AUTHORITY WINAPI
1168 GetSidIdentifierAuthority( PSID pSid )
1170 SetLastError(ERROR_SUCCESS);
1171 return RtlIdentifierAuthoritySid(pSid);
1174 /******************************************************************************
1175 * GetSidSubAuthority [ADVAPI32.@]
1177 * PARAMS
1178 * pSid []
1179 * nSubAuthority []
1181 PDWORD WINAPI
1182 GetSidSubAuthority( PSID pSid, DWORD nSubAuthority )
1184 SetLastError(ERROR_SUCCESS);
1185 return RtlSubAuthoritySid(pSid, nSubAuthority);
1188 /******************************************************************************
1189 * GetSidSubAuthorityCount [ADVAPI32.@]
1191 * PARAMS
1192 * pSid []
1194 PUCHAR WINAPI
1195 GetSidSubAuthorityCount (PSID pSid)
1197 SetLastError(ERROR_SUCCESS);
1198 return RtlSubAuthorityCountSid(pSid);
1201 /******************************************************************************
1202 * GetLengthSid [ADVAPI32.@]
1204 * PARAMS
1205 * pSid []
1207 DWORD WINAPI
1208 GetLengthSid (PSID pSid)
1210 return RtlLengthSid(pSid);
1213 /* ##############################################
1214 ###### SECURITY DESCRIPTOR FUNCTIONS ######
1215 ##############################################
1218 /******************************************************************************
1219 * BuildSecurityDescriptorA [ADVAPI32.@]
1221 * Builds a SD from
1223 * PARAMS
1224 * pOwner [I]
1225 * pGroup [I]
1226 * cCountOfAccessEntries [I]
1227 * pListOfAccessEntries [I]
1228 * cCountOfAuditEntries [I]
1229 * pListofAuditEntries [I]
1230 * pOldSD [I]
1231 * lpdwBufferLength [I/O]
1232 * pNewSD [O]
1234 * RETURNS
1235 * Success: ERROR_SUCCESS
1236 * Failure: nonzero error code from Winerror.h
1238 DWORD WINAPI BuildSecurityDescriptorA(
1239 IN PTRUSTEEA pOwner,
1240 IN PTRUSTEEA pGroup,
1241 IN ULONG cCountOfAccessEntries,
1242 IN PEXPLICIT_ACCESSA pListOfAccessEntries,
1243 IN ULONG cCountOfAuditEntries,
1244 IN PEXPLICIT_ACCESSA pListofAuditEntries,
1245 IN PSECURITY_DESCRIPTOR pOldSD,
1246 IN OUT PULONG lpdwBufferLength,
1247 OUT PSECURITY_DESCRIPTOR* pNewSD)
1249 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1250 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1251 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1253 return ERROR_CALL_NOT_IMPLEMENTED;
1256 /******************************************************************************
1257 * BuildSecurityDescriptorW [ADVAPI32.@]
1259 * See BuildSecurityDescriptorA.
1261 DWORD WINAPI BuildSecurityDescriptorW(
1262 IN PTRUSTEEW pOwner,
1263 IN PTRUSTEEW pGroup,
1264 IN ULONG cCountOfAccessEntries,
1265 IN PEXPLICIT_ACCESSW pListOfAccessEntries,
1266 IN ULONG cCountOfAuditEntries,
1267 IN PEXPLICIT_ACCESSW pListofAuditEntries,
1268 IN PSECURITY_DESCRIPTOR pOldSD,
1269 IN OUT PULONG lpdwBufferLength,
1270 OUT PSECURITY_DESCRIPTOR* pNewSD)
1272 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
1273 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
1274 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
1276 return ERROR_CALL_NOT_IMPLEMENTED;
1279 /******************************************************************************
1280 * InitializeSecurityDescriptor [ADVAPI32.@]
1282 * PARAMS
1283 * pDescr []
1284 * revision []
1286 BOOL WINAPI
1287 InitializeSecurityDescriptor( PSECURITY_DESCRIPTOR pDescr, DWORD revision )
1289 return set_ntstatus( RtlCreateSecurityDescriptor(pDescr, revision ));
1293 /******************************************************************************
1294 * MakeAbsoluteSD [ADVAPI32.@]
1296 BOOL WINAPI MakeAbsoluteSD (
1297 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1298 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1299 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
1300 OUT PACL pDacl,
1301 OUT LPDWORD lpdwDaclSize,
1302 OUT PACL pSacl,
1303 OUT LPDWORD lpdwSaclSize,
1304 OUT PSID pOwner,
1305 OUT LPDWORD lpdwOwnerSize,
1306 OUT PSID pPrimaryGroup,
1307 OUT LPDWORD lpdwPrimaryGroupSize)
1309 return set_ntstatus( RtlSelfRelativeToAbsoluteSD(pSelfRelativeSecurityDescriptor,
1310 pAbsoluteSecurityDescriptor,
1311 lpdwAbsoluteSecurityDescriptorSize,
1312 pDacl, lpdwDaclSize, pSacl, lpdwSaclSize,
1313 pOwner, lpdwOwnerSize,
1314 pPrimaryGroup, lpdwPrimaryGroupSize));
1317 /******************************************************************************
1318 * GetKernelObjectSecurity [ADVAPI32.@]
1320 BOOL WINAPI GetKernelObjectSecurity(
1321 HANDLE Handle,
1322 SECURITY_INFORMATION RequestedInformation,
1323 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1324 DWORD nLength,
1325 LPDWORD lpnLengthNeeded )
1327 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", Handle, RequestedInformation,
1328 pSecurityDescriptor, nLength, lpnLengthNeeded);
1330 return set_ntstatus( NtQuerySecurityObject(Handle, RequestedInformation, pSecurityDescriptor,
1331 nLength, lpnLengthNeeded ));
1334 /******************************************************************************
1335 * GetPrivateObjectSecurity [ADVAPI32.@]
1337 BOOL WINAPI GetPrivateObjectSecurity(
1338 PSECURITY_DESCRIPTOR ObjectDescriptor,
1339 SECURITY_INFORMATION SecurityInformation,
1340 PSECURITY_DESCRIPTOR ResultantDescriptor,
1341 DWORD DescriptorLength,
1342 PDWORD ReturnLength )
1344 SECURITY_DESCRIPTOR desc;
1345 BOOL defaulted, present;
1346 PACL pacl;
1347 PSID psid;
1349 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", ObjectDescriptor, SecurityInformation,
1350 ResultantDescriptor, DescriptorLength, ReturnLength);
1352 if (!InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION))
1353 return FALSE;
1355 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1357 if (!GetSecurityDescriptorOwner(ObjectDescriptor, &psid, &defaulted))
1358 return FALSE;
1359 SetSecurityDescriptorOwner(&desc, psid, defaulted);
1362 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1364 if (!GetSecurityDescriptorGroup(ObjectDescriptor, &psid, &defaulted))
1365 return FALSE;
1366 SetSecurityDescriptorGroup(&desc, psid, defaulted);
1369 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1371 if (!GetSecurityDescriptorDacl(ObjectDescriptor, &present, &pacl, &defaulted))
1372 return FALSE;
1373 SetSecurityDescriptorDacl(&desc, present, pacl, defaulted);
1376 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1378 if (!GetSecurityDescriptorSacl(ObjectDescriptor, &present, &pacl, &defaulted))
1379 return FALSE;
1380 SetSecurityDescriptorSacl(&desc, present, pacl, defaulted);
1383 *ReturnLength = DescriptorLength;
1384 return MakeSelfRelativeSD(&desc, ResultantDescriptor, ReturnLength);
1387 /******************************************************************************
1388 * GetSecurityDescriptorLength [ADVAPI32.@]
1390 DWORD WINAPI GetSecurityDescriptorLength( PSECURITY_DESCRIPTOR pDescr)
1392 return RtlLengthSecurityDescriptor(pDescr);
1395 /******************************************************************************
1396 * GetSecurityDescriptorOwner [ADVAPI32.@]
1398 * PARAMS
1399 * pOwner []
1400 * lpbOwnerDefaulted []
1402 BOOL WINAPI
1403 GetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pDescr, PSID *pOwner,
1404 LPBOOL lpbOwnerDefaulted )
1406 BOOLEAN defaulted;
1407 BOOL ret = set_ntstatus( RtlGetOwnerSecurityDescriptor( pDescr, pOwner, &defaulted ));
1408 *lpbOwnerDefaulted = defaulted;
1409 return ret;
1412 /******************************************************************************
1413 * SetSecurityDescriptorOwner [ADVAPI32.@]
1415 * PARAMS
1417 BOOL WINAPI SetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1418 PSID pOwner, BOOL bOwnerDefaulted)
1420 return set_ntstatus( RtlSetOwnerSecurityDescriptor(pSecurityDescriptor, pOwner, bOwnerDefaulted));
1422 /******************************************************************************
1423 * GetSecurityDescriptorGroup [ADVAPI32.@]
1425 BOOL WINAPI GetSecurityDescriptorGroup(
1426 PSECURITY_DESCRIPTOR SecurityDescriptor,
1427 PSID *Group,
1428 LPBOOL GroupDefaulted)
1430 BOOLEAN defaulted;
1431 BOOL ret = set_ntstatus( RtlGetGroupSecurityDescriptor(SecurityDescriptor, Group, &defaulted ));
1432 *GroupDefaulted = defaulted;
1433 return ret;
1435 /******************************************************************************
1436 * SetSecurityDescriptorGroup [ADVAPI32.@]
1438 BOOL WINAPI SetSecurityDescriptorGroup ( PSECURITY_DESCRIPTOR SecurityDescriptor,
1439 PSID Group, BOOL GroupDefaulted)
1441 return set_ntstatus( RtlSetGroupSecurityDescriptor( SecurityDescriptor, Group, GroupDefaulted));
1444 /******************************************************************************
1445 * IsValidSecurityDescriptor [ADVAPI32.@]
1447 * PARAMS
1448 * lpsecdesc []
1450 BOOL WINAPI
1451 IsValidSecurityDescriptor( PSECURITY_DESCRIPTOR SecurityDescriptor )
1453 return set_ntstatus( RtlValidSecurityDescriptor(SecurityDescriptor));
1456 /******************************************************************************
1457 * GetSecurityDescriptorDacl [ADVAPI32.@]
1459 BOOL WINAPI GetSecurityDescriptorDacl(
1460 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1461 OUT LPBOOL lpbDaclPresent,
1462 OUT PACL *pDacl,
1463 OUT LPBOOL lpbDaclDefaulted)
1465 BOOLEAN present, defaulted;
1466 BOOL ret = set_ntstatus( RtlGetDaclSecurityDescriptor(pSecurityDescriptor, &present, pDacl, &defaulted));
1467 *lpbDaclPresent = present;
1468 *lpbDaclDefaulted = defaulted;
1469 return ret;
1472 /******************************************************************************
1473 * SetSecurityDescriptorDacl [ADVAPI32.@]
1475 BOOL WINAPI
1476 SetSecurityDescriptorDacl (
1477 PSECURITY_DESCRIPTOR lpsd,
1478 BOOL daclpresent,
1479 PACL dacl,
1480 BOOL dacldefaulted )
1482 return set_ntstatus( RtlSetDaclSecurityDescriptor (lpsd, daclpresent, dacl, dacldefaulted ) );
1484 /******************************************************************************
1485 * GetSecurityDescriptorSacl [ADVAPI32.@]
1487 BOOL WINAPI GetSecurityDescriptorSacl(
1488 IN PSECURITY_DESCRIPTOR lpsd,
1489 OUT LPBOOL lpbSaclPresent,
1490 OUT PACL *pSacl,
1491 OUT LPBOOL lpbSaclDefaulted)
1493 BOOLEAN present, defaulted;
1494 BOOL ret = set_ntstatus( RtlGetSaclSecurityDescriptor(lpsd, &present, pSacl, &defaulted) );
1495 *lpbSaclPresent = present;
1496 *lpbSaclDefaulted = defaulted;
1497 return ret;
1500 /**************************************************************************
1501 * SetSecurityDescriptorSacl [ADVAPI32.@]
1503 BOOL WINAPI SetSecurityDescriptorSacl (
1504 PSECURITY_DESCRIPTOR lpsd,
1505 BOOL saclpresent,
1506 PACL lpsacl,
1507 BOOL sacldefaulted)
1509 return set_ntstatus (RtlSetSaclSecurityDescriptor(lpsd, saclpresent, lpsacl, sacldefaulted));
1511 /******************************************************************************
1512 * MakeSelfRelativeSD [ADVAPI32.@]
1514 * PARAMS
1515 * lpabssecdesc []
1516 * lpselfsecdesc []
1517 * lpbuflen []
1519 BOOL WINAPI
1520 MakeSelfRelativeSD(
1521 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
1522 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
1523 IN OUT LPDWORD lpdwBufferLength)
1525 return set_ntstatus( RtlMakeSelfRelativeSD( pAbsoluteSecurityDescriptor,
1526 pSelfRelativeSecurityDescriptor, lpdwBufferLength));
1529 /******************************************************************************
1530 * GetSecurityDescriptorControl [ADVAPI32.@]
1533 BOOL WINAPI GetSecurityDescriptorControl ( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1534 PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD lpdwRevision)
1536 return set_ntstatus( RtlGetControlSecurityDescriptor(pSecurityDescriptor,pControl,lpdwRevision));
1539 /******************************************************************************
1540 * SetSecurityDescriptorControl [ADVAPI32.@]
1542 BOOL WINAPI SetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor,
1543 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1544 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet )
1546 return set_ntstatus( RtlSetControlSecurityDescriptor(
1547 pSecurityDescriptor, ControlBitsOfInterest, ControlBitsToSet ) );
1550 /******************************************************************************
1551 * GetWindowsAccountDomainSid [ADVAPI32.@]
1553 BOOL WINAPI GetWindowsAccountDomainSid( PSID sid, PSID domain_sid, DWORD *size )
1555 SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY };
1556 DWORD required_size;
1557 int i;
1559 FIXME( "(%p %p %p): semi-stub\n", sid, domain_sid, size );
1561 if (!sid || !IsValidSid( sid ))
1563 SetLastError( ERROR_INVALID_SID );
1564 return FALSE;
1567 if (!size)
1569 SetLastError( ERROR_INVALID_PARAMETER );
1570 return FALSE;
1573 if (*GetSidSubAuthorityCount( sid ) < 4)
1575 SetLastError( ERROR_INVALID_SID );
1576 return FALSE;
1579 required_size = GetSidLengthRequired( 4 );
1580 if (*size < required_size || !domain_sid)
1582 *size = required_size;
1583 SetLastError( domain_sid ? ERROR_INSUFFICIENT_BUFFER :
1584 ERROR_INVALID_PARAMETER );
1585 return FALSE;
1588 InitializeSid( domain_sid, &domain_ident, 4 );
1589 for (i = 0; i < 4; i++)
1590 *GetSidSubAuthority( domain_sid, i ) = *GetSidSubAuthority( sid, i );
1592 *size = required_size;
1593 return TRUE;
1596 /* ##############################
1597 ###### ACL FUNCTIONS ######
1598 ##############################
1601 /*************************************************************************
1602 * InitializeAcl [ADVAPI32.@]
1604 BOOL WINAPI InitializeAcl(PACL acl, DWORD size, DWORD rev)
1606 return set_ntstatus( RtlCreateAcl(acl, size, rev));
1609 BOOL WINAPI ImpersonateNamedPipeClient( HANDLE hNamedPipe )
1611 IO_STATUS_BLOCK io_block;
1613 TRACE("(%p)\n", hNamedPipe);
1615 return set_ntstatus( NtFsControlFile(hNamedPipe, NULL, NULL, NULL,
1616 &io_block, FSCTL_PIPE_IMPERSONATE, NULL, 0, NULL, 0) );
1619 /******************************************************************************
1620 * AddAccessAllowedAce [ADVAPI32.@]
1622 BOOL WINAPI AddAccessAllowedAce(
1623 IN OUT PACL pAcl,
1624 IN DWORD dwAceRevision,
1625 IN DWORD AccessMask,
1626 IN PSID pSid)
1628 return set_ntstatus(RtlAddAccessAllowedAce(pAcl, dwAceRevision, AccessMask, pSid));
1631 /******************************************************************************
1632 * AddAccessAllowedAceEx [ADVAPI32.@]
1634 BOOL WINAPI AddAccessAllowedAceEx(
1635 IN OUT PACL pAcl,
1636 IN DWORD dwAceRevision,
1637 IN DWORD AceFlags,
1638 IN DWORD AccessMask,
1639 IN PSID pSid)
1641 return set_ntstatus(RtlAddAccessAllowedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1644 /******************************************************************************
1645 * AddAccessDeniedAce [ADVAPI32.@]
1647 BOOL WINAPI AddAccessDeniedAce(
1648 IN OUT PACL pAcl,
1649 IN DWORD dwAceRevision,
1650 IN DWORD AccessMask,
1651 IN PSID pSid)
1653 return set_ntstatus(RtlAddAccessDeniedAce(pAcl, dwAceRevision, AccessMask, pSid));
1656 /******************************************************************************
1657 * AddAccessDeniedAceEx [ADVAPI32.@]
1659 BOOL WINAPI AddAccessDeniedAceEx(
1660 IN OUT PACL pAcl,
1661 IN DWORD dwAceRevision,
1662 IN DWORD AceFlags,
1663 IN DWORD AccessMask,
1664 IN PSID pSid)
1666 return set_ntstatus(RtlAddAccessDeniedAceEx(pAcl, dwAceRevision, AceFlags, AccessMask, pSid));
1669 /******************************************************************************
1670 * AddAce [ADVAPI32.@]
1672 BOOL WINAPI AddAce(
1673 IN OUT PACL pAcl,
1674 IN DWORD dwAceRevision,
1675 IN DWORD dwStartingAceIndex,
1676 LPVOID pAceList,
1677 DWORD nAceListLength)
1679 return set_ntstatus(RtlAddAce(pAcl, dwAceRevision, dwStartingAceIndex, pAceList, nAceListLength));
1682 BOOL WINAPI AddMandatoryAce(ACL *acl, DWORD ace_revision, DWORD ace_flags, DWORD mandatory_policy, PSID label_sid)
1684 FIXME("%p %x %x %x %p - stub\n", acl, ace_revision, ace_flags, mandatory_policy, label_sid);
1685 return FALSE;
1688 /******************************************************************************
1689 * DeleteAce [ADVAPI32.@]
1691 BOOL WINAPI DeleteAce(PACL pAcl, DWORD dwAceIndex)
1693 return set_ntstatus(RtlDeleteAce(pAcl, dwAceIndex));
1696 /******************************************************************************
1697 * FindFirstFreeAce [ADVAPI32.@]
1699 BOOL WINAPI FindFirstFreeAce(IN PACL pAcl, LPVOID * pAce)
1701 return RtlFirstFreeAce(pAcl, (PACE_HEADER *)pAce);
1704 /******************************************************************************
1705 * GetAce [ADVAPI32.@]
1707 BOOL WINAPI GetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1709 return set_ntstatus(RtlGetAce(pAcl, dwAceIndex, pAce));
1712 /******************************************************************************
1713 * GetAclInformation [ADVAPI32.@]
1715 BOOL WINAPI GetAclInformation(
1716 PACL pAcl,
1717 LPVOID pAclInformation,
1718 DWORD nAclInformationLength,
1719 ACL_INFORMATION_CLASS dwAclInformationClass)
1721 return set_ntstatus(RtlQueryInformationAcl(pAcl, pAclInformation,
1722 nAclInformationLength, dwAclInformationClass));
1725 /******************************************************************************
1726 * IsValidAcl [ADVAPI32.@]
1728 BOOL WINAPI IsValidAcl(IN PACL pAcl)
1730 return RtlValidAcl(pAcl);
1733 /* ##############################
1734 ###### MISC FUNCTIONS ######
1735 ##############################
1738 /******************************************************************************
1739 * AllocateLocallyUniqueId [ADVAPI32.@]
1741 * PARAMS
1742 * lpLuid []
1744 BOOL WINAPI AllocateLocallyUniqueId( PLUID lpLuid )
1746 return set_ntstatus(NtAllocateLocallyUniqueId(lpLuid));
1749 static const WCHAR SE_CREATE_TOKEN_NAME_W[] =
1750 { 'S','e','C','r','e','a','t','e','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 };
1751 static const WCHAR SE_ASSIGNPRIMARYTOKEN_NAME_W[] =
1752 { '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 };
1753 static const WCHAR SE_LOCK_MEMORY_NAME_W[] =
1754 { 'S','e','L','o','c','k','M','e','m','o','r','y','P','r','i','v','i','l','e','g','e',0 };
1755 static const WCHAR SE_INCREASE_QUOTA_NAME_W[] =
1756 { '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 };
1757 static const WCHAR SE_MACHINE_ACCOUNT_NAME_W[] =
1758 { '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 };
1759 static const WCHAR SE_TCB_NAME_W[] =
1760 { 'S','e','T','c','b','P','r','i','v','i','l','e','g','e',0 };
1761 static const WCHAR SE_SECURITY_NAME_W[] =
1762 { 'S','e','S','e','c','u','r','i','t','y','P','r','i','v','i','l','e','g','e',0 };
1763 static const WCHAR SE_TAKE_OWNERSHIP_NAME_W[] =
1764 { '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 };
1765 static const WCHAR SE_LOAD_DRIVER_NAME_W[] =
1766 { 'S','e','L','o','a','d','D','r','i','v','e','r','P','r','i','v','i','l','e','g','e',0 };
1767 static const WCHAR SE_SYSTEM_PROFILE_NAME_W[] =
1768 { '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 };
1769 static const WCHAR SE_SYSTEMTIME_NAME_W[] =
1770 { 'S','e','S','y','s','t','e','m','t','i','m','e','P','r','i','v','i','l','e','g','e',0 };
1771 static const WCHAR SE_PROF_SINGLE_PROCESS_NAME_W[] =
1772 { '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 };
1773 static const WCHAR SE_INC_BASE_PRIORITY_NAME_W[] =
1774 { '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 };
1775 static const WCHAR SE_CREATE_PAGEFILE_NAME_W[] =
1776 { '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 };
1777 static const WCHAR SE_CREATE_PERMANENT_NAME_W[] =
1778 { '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 };
1779 static const WCHAR SE_BACKUP_NAME_W[] =
1780 { 'S','e','B','a','c','k','u','p','P','r','i','v','i','l','e','g','e',0 };
1781 static const WCHAR SE_RESTORE_NAME_W[] =
1782 { 'S','e','R','e','s','t','o','r','e','P','r','i','v','i','l','e','g','e',0 };
1783 static const WCHAR SE_SHUTDOWN_NAME_W[] =
1784 { 'S','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 };
1785 static const WCHAR SE_DEBUG_NAME_W[] =
1786 { 'S','e','D','e','b','u','g','P','r','i','v','i','l','e','g','e',0 };
1787 static const WCHAR SE_AUDIT_NAME_W[] =
1788 { 'S','e','A','u','d','i','t','P','r','i','v','i','l','e','g','e',0 };
1789 static const WCHAR SE_SYSTEM_ENVIRONMENT_NAME_W[] =
1790 { '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 };
1791 static const WCHAR SE_CHANGE_NOTIFY_NAME_W[] =
1792 { 'S','e','C','h','a','n','g','e','N','o','t','i','f','y','P','r','i','v','i','l','e','g','e',0 };
1793 static const WCHAR SE_REMOTE_SHUTDOWN_NAME_W[] =
1794 { '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 };
1795 static const WCHAR SE_UNDOCK_NAME_W[] =
1796 { 'S','e','U','n','d','o','c','k','P','r','i','v','i','l','e','g','e',0 };
1797 static const WCHAR SE_SYNC_AGENT_NAME_W[] =
1798 { 'S','e','S','y','n','c','A','g','e','n','t','P','r','i','v','i','l','e','g','e',0 };
1799 static const WCHAR SE_ENABLE_DELEGATION_NAME_W[] =
1800 { '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 };
1801 static const WCHAR SE_MANAGE_VOLUME_NAME_W[] =
1802 { 'S','e','M','a','n','a','g','e','V','o','l','u','m','e','P','r','i','v','i','l','e','g','e',0 };
1803 static const WCHAR SE_IMPERSONATE_NAME_W[] =
1804 { 'S','e','I','m','p','e','r','s','o','n','a','t','e','P','r','i','v','i','l','e','g','e',0 };
1805 static const WCHAR SE_CREATE_GLOBAL_NAME_W[] =
1806 { 'S','e','C','r','e','a','t','e','G','l','o','b','a','l','P','r','i','v','i','l','e','g','e',0 };
1808 static const WCHAR * const WellKnownPrivNames[SE_MAX_WELL_KNOWN_PRIVILEGE + 1] =
1810 NULL,
1811 NULL,
1812 SE_CREATE_TOKEN_NAME_W,
1813 SE_ASSIGNPRIMARYTOKEN_NAME_W,
1814 SE_LOCK_MEMORY_NAME_W,
1815 SE_INCREASE_QUOTA_NAME_W,
1816 SE_MACHINE_ACCOUNT_NAME_W,
1817 SE_TCB_NAME_W,
1818 SE_SECURITY_NAME_W,
1819 SE_TAKE_OWNERSHIP_NAME_W,
1820 SE_LOAD_DRIVER_NAME_W,
1821 SE_SYSTEM_PROFILE_NAME_W,
1822 SE_SYSTEMTIME_NAME_W,
1823 SE_PROF_SINGLE_PROCESS_NAME_W,
1824 SE_INC_BASE_PRIORITY_NAME_W,
1825 SE_CREATE_PAGEFILE_NAME_W,
1826 SE_CREATE_PERMANENT_NAME_W,
1827 SE_BACKUP_NAME_W,
1828 SE_RESTORE_NAME_W,
1829 SE_SHUTDOWN_NAME_W,
1830 SE_DEBUG_NAME_W,
1831 SE_AUDIT_NAME_W,
1832 SE_SYSTEM_ENVIRONMENT_NAME_W,
1833 SE_CHANGE_NOTIFY_NAME_W,
1834 SE_REMOTE_SHUTDOWN_NAME_W,
1835 SE_UNDOCK_NAME_W,
1836 SE_SYNC_AGENT_NAME_W,
1837 SE_ENABLE_DELEGATION_NAME_W,
1838 SE_MANAGE_VOLUME_NAME_W,
1839 SE_IMPERSONATE_NAME_W,
1840 SE_CREATE_GLOBAL_NAME_W,
1843 /******************************************************************************
1844 * LookupPrivilegeValueW [ADVAPI32.@]
1846 * See LookupPrivilegeValueA.
1848 BOOL WINAPI
1849 LookupPrivilegeValueW( LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid )
1851 UINT i;
1853 TRACE("%s,%s,%p\n",debugstr_w(lpSystemName), debugstr_w(lpName), lpLuid);
1855 if (!ADVAPI_IsLocalComputer(lpSystemName))
1857 SetLastError(RPC_S_SERVER_UNAVAILABLE);
1858 return FALSE;
1860 if (!lpName)
1862 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1863 return FALSE;
1865 for( i=SE_MIN_WELL_KNOWN_PRIVILEGE; i<=SE_MAX_WELL_KNOWN_PRIVILEGE; i++ )
1867 if( !WellKnownPrivNames[i] )
1868 continue;
1869 if( strcmpiW( WellKnownPrivNames[i], lpName) )
1870 continue;
1871 lpLuid->LowPart = i;
1872 lpLuid->HighPart = 0;
1873 TRACE( "%s -> %08x-%08x\n",debugstr_w( lpSystemName ),
1874 lpLuid->HighPart, lpLuid->LowPart );
1875 return TRUE;
1877 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
1878 return FALSE;
1881 /******************************************************************************
1882 * LookupPrivilegeValueA [ADVAPI32.@]
1884 * Retrieves LUID used on a system to represent the privilege name.
1886 * PARAMS
1887 * lpSystemName [I] Name of the system
1888 * lpName [I] Name of the privilege
1889 * lpLuid [O] Destination for the resulting LUID
1891 * RETURNS
1892 * Success: TRUE. lpLuid contains the requested LUID.
1893 * Failure: FALSE.
1895 BOOL WINAPI
1896 LookupPrivilegeValueA( LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid )
1898 UNICODE_STRING lpSystemNameW;
1899 UNICODE_STRING lpNameW;
1900 BOOL ret;
1902 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1903 RtlCreateUnicodeStringFromAsciiz(&lpNameW,lpName);
1904 ret = LookupPrivilegeValueW(lpSystemNameW.Buffer, lpNameW.Buffer, lpLuid);
1905 RtlFreeUnicodeString(&lpNameW);
1906 RtlFreeUnicodeString(&lpSystemNameW);
1907 return ret;
1910 BOOL WINAPI LookupPrivilegeDisplayNameA( LPCSTR lpSystemName, LPCSTR lpName, LPSTR lpDisplayName,
1911 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1913 FIXME("%s %s %s %p %p - stub\n", debugstr_a(lpSystemName), debugstr_a(lpName),
1914 debugstr_a(lpDisplayName), cchDisplayName, lpLanguageId);
1916 return FALSE;
1919 BOOL WINAPI LookupPrivilegeDisplayNameW( LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName,
1920 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
1922 FIXME("%s %s %s %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpName),
1923 debugstr_w(lpDisplayName), cchDisplayName, lpLanguageId);
1925 return FALSE;
1928 /******************************************************************************
1929 * LookupPrivilegeNameA [ADVAPI32.@]
1931 * See LookupPrivilegeNameW.
1933 BOOL WINAPI
1934 LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName,
1935 LPDWORD cchName)
1937 UNICODE_STRING lpSystemNameW;
1938 BOOL ret;
1939 DWORD wLen = 0;
1941 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
1943 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1944 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
1945 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1947 LPWSTR lpNameW = heap_alloc(wLen * sizeof(WCHAR));
1949 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
1950 &wLen);
1951 if (ret)
1953 /* Windows crashes if cchName is NULL, so will I */
1954 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
1955 *cchName, NULL, NULL);
1957 if (len == 0)
1959 /* WideCharToMultiByte failed */
1960 ret = FALSE;
1962 else if (len > *cchName)
1964 *cchName = len;
1965 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1966 ret = FALSE;
1968 else
1970 /* WideCharToMultiByte succeeded, output length needs to be
1971 * length not including NULL terminator
1973 *cchName = len - 1;
1976 heap_free(lpNameW);
1978 RtlFreeUnicodeString(&lpSystemNameW);
1979 return ret;
1982 /******************************************************************************
1983 * LookupPrivilegeNameW [ADVAPI32.@]
1985 * Retrieves the privilege name referred to by the LUID lpLuid.
1987 * PARAMS
1988 * lpSystemName [I] Name of the system
1989 * lpLuid [I] Privilege value
1990 * lpName [O] Name of the privilege
1991 * cchName [I/O] Number of characters in lpName.
1993 * RETURNS
1994 * Success: TRUE. lpName contains the name of the privilege whose value is
1995 * *lpLuid.
1996 * Failure: FALSE.
1998 * REMARKS
1999 * Only well-known privilege names (those defined in winnt.h) can be retrieved
2000 * using this function.
2001 * If the length of lpName is too small, on return *cchName will contain the
2002 * number of WCHARs needed to contain the privilege, including the NULL
2003 * terminator, and GetLastError will return ERROR_INSUFFICIENT_BUFFER.
2004 * On success, *cchName will contain the number of characters stored in
2005 * lpName, NOT including the NULL terminator.
2007 BOOL WINAPI
2008 LookupPrivilegeNameW( LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName,
2009 LPDWORD cchName)
2011 size_t privNameLen;
2013 TRACE("%s,%p,%p,%p\n",debugstr_w(lpSystemName), lpLuid, lpName, cchName);
2015 if (!ADVAPI_IsLocalComputer(lpSystemName))
2017 SetLastError(RPC_S_SERVER_UNAVAILABLE);
2018 return FALSE;
2020 if (lpLuid->HighPart || (lpLuid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
2021 lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
2023 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
2024 return FALSE;
2026 privNameLen = strlenW(WellKnownPrivNames[lpLuid->LowPart]);
2027 /* Windows crashes if cchName is NULL, so will I */
2028 if (*cchName <= privNameLen)
2030 *cchName = privNameLen + 1;
2031 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2032 return FALSE;
2034 else
2036 strcpyW(lpName, WellKnownPrivNames[lpLuid->LowPart]);
2037 *cchName = privNameLen;
2038 return TRUE;
2042 /******************************************************************************
2043 * GetFileSecurityA [ADVAPI32.@]
2045 * Obtains Specified information about the security of a file or directory.
2047 * PARAMS
2048 * lpFileName [I] Name of the file to get info for
2049 * RequestedInformation [I] SE_ flags from "winnt.h"
2050 * pSecurityDescriptor [O] Destination for security information
2051 * nLength [I] Length of pSecurityDescriptor
2052 * lpnLengthNeeded [O] Destination for length of returned security information
2054 * RETURNS
2055 * Success: TRUE. pSecurityDescriptor contains the requested information.
2056 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
2058 * NOTES
2059 * The information returned is constrained by the callers access rights and
2060 * privileges.
2062 BOOL WINAPI
2063 GetFileSecurityA( LPCSTR lpFileName,
2064 SECURITY_INFORMATION RequestedInformation,
2065 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2066 DWORD nLength, LPDWORD lpnLengthNeeded )
2068 BOOL r;
2069 LPWSTR name;
2071 name = SERV_dup(lpFileName);
2072 r = GetFileSecurityW( name, RequestedInformation, pSecurityDescriptor,
2073 nLength, lpnLengthNeeded );
2074 heap_free( name );
2076 return r;
2079 /******************************************************************************
2080 * GetFileSecurityW [ADVAPI32.@]
2082 * See GetFileSecurityA.
2084 BOOL WINAPI
2085 GetFileSecurityW( LPCWSTR lpFileName,
2086 SECURITY_INFORMATION RequestedInformation,
2087 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2088 DWORD nLength, LPDWORD lpnLengthNeeded )
2090 HANDLE hfile;
2091 NTSTATUS status;
2092 DWORD access = 0, err;
2094 TRACE("(%s,%d,%p,%d,%p)\n", debugstr_w(lpFileName),
2095 RequestedInformation, pSecurityDescriptor,
2096 nLength, lpnLengthNeeded);
2098 if (RequestedInformation & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|
2099 DACL_SECURITY_INFORMATION))
2100 access |= READ_CONTROL;
2101 if (RequestedInformation & SACL_SECURITY_INFORMATION)
2102 access |= ACCESS_SYSTEM_SECURITY;
2104 err = get_security_file( lpFileName, access, &hfile);
2105 if (err)
2107 SetLastError(err);
2108 return FALSE;
2111 status = NtQuerySecurityObject( hfile, RequestedInformation, pSecurityDescriptor,
2112 nLength, lpnLengthNeeded );
2113 CloseHandle( hfile );
2114 return set_ntstatus( status );
2118 /******************************************************************************
2119 * LookupAccountSidA [ADVAPI32.@]
2121 BOOL WINAPI
2122 LookupAccountSidA(
2123 IN LPCSTR system,
2124 IN PSID sid,
2125 OUT LPSTR account,
2126 IN OUT LPDWORD accountSize,
2127 OUT LPSTR domain,
2128 IN OUT LPDWORD domainSize,
2129 OUT PSID_NAME_USE name_use )
2131 DWORD len;
2132 BOOL r;
2133 LPWSTR systemW;
2134 LPWSTR accountW = NULL;
2135 LPWSTR domainW = NULL;
2136 DWORD accountSizeW = *accountSize;
2137 DWORD domainSizeW = *domainSize;
2139 systemW = SERV_dup(system);
2140 if (account)
2141 accountW = heap_alloc( accountSizeW * sizeof(WCHAR) );
2142 if (domain)
2143 domainW = heap_alloc( domainSizeW * sizeof(WCHAR) );
2145 r = LookupAccountSidW( systemW, sid, accountW, &accountSizeW, domainW, &domainSizeW, name_use );
2147 if (r) {
2148 if (accountW && *accountSize) {
2149 len = WideCharToMultiByte( CP_ACP, 0, accountW, -1, NULL, 0, NULL, NULL );
2150 WideCharToMultiByte( CP_ACP, 0, accountW, -1, account, len, NULL, NULL );
2151 *accountSize = len;
2152 } else
2153 *accountSize = accountSizeW + 1;
2155 if (domainW && *domainSize) {
2156 len = WideCharToMultiByte( CP_ACP, 0, domainW, -1, NULL, 0, NULL, NULL );
2157 WideCharToMultiByte( CP_ACP, 0, domainW, -1, domain, len, NULL, NULL );
2158 *domainSize = len;
2159 } else
2160 *domainSize = domainSizeW + 1;
2162 else
2164 *accountSize = accountSizeW + 1;
2165 *domainSize = domainSizeW + 1;
2168 heap_free( systemW );
2169 heap_free( accountW );
2170 heap_free( domainW );
2172 return r;
2175 /******************************************************************************
2176 * LookupAccountSidW [ADVAPI32.@]
2178 * PARAMS
2179 * system []
2180 * sid []
2181 * account []
2182 * accountSize []
2183 * domain []
2184 * domainSize []
2185 * name_use []
2188 BOOL WINAPI
2189 LookupAccountSidW(
2190 IN LPCWSTR system,
2191 IN PSID sid,
2192 OUT LPWSTR account,
2193 IN OUT LPDWORD accountSize,
2194 OUT LPWSTR domain,
2195 IN OUT LPDWORD domainSize,
2196 OUT PSID_NAME_USE name_use )
2198 unsigned int i, j;
2199 const WCHAR * ac = NULL;
2200 const WCHAR * dm = NULL;
2201 SID_NAME_USE use = 0;
2202 LPWSTR computer_name = NULL;
2203 LPWSTR account_name = NULL;
2205 TRACE("(%s,sid=%s,%p,%p(%u),%p,%p(%u),%p)\n",
2206 debugstr_w(system),debugstr_sid(sid),
2207 account,accountSize,accountSize?*accountSize:0,
2208 domain,domainSize,domainSize?*domainSize:0,
2209 name_use);
2211 if (!ADVAPI_IsLocalComputer(system)) {
2212 FIXME("Only local computer supported!\n");
2213 SetLastError(RPC_S_SERVER_UNAVAILABLE);
2214 return FALSE;
2217 /* check the well known SIDs first */
2218 for (i = 0; i <= WinAccountProtectedUsersSid; i++) {
2219 if (IsWellKnownSid(sid, i)) {
2220 for (j = 0; j < (sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0])); j++) {
2221 if (ACCOUNT_SIDS[j].type == i) {
2222 ac = ACCOUNT_SIDS[j].account;
2223 dm = ACCOUNT_SIDS[j].domain;
2224 use = ACCOUNT_SIDS[j].name_use;
2227 break;
2231 if (dm == NULL) {
2232 MAX_SID local;
2234 /* check for the local computer next */
2235 if (ADVAPI_GetComputerSid(&local)) {
2236 DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
2237 BOOL result;
2239 computer_name = heap_alloc(size * sizeof(WCHAR));
2240 result = GetComputerNameW(computer_name, &size);
2242 if (result) {
2243 if (EqualSid(sid, &local)) {
2244 dm = computer_name;
2245 ac = Blank;
2246 use = 3;
2247 } else {
2248 local.SubAuthorityCount++;
2250 if (EqualPrefixSid(sid, &local)) {
2251 dm = computer_name;
2252 use = 1;
2253 switch (((MAX_SID *)sid)->SubAuthority[4]) {
2254 case DOMAIN_USER_RID_ADMIN:
2255 ac = Administrator;
2256 break;
2257 case DOMAIN_USER_RID_GUEST:
2258 ac = Guest;
2259 break;
2260 case DOMAIN_GROUP_RID_ADMINS:
2261 ac = Domain_Admins;
2262 break;
2263 case DOMAIN_GROUP_RID_USERS:
2264 ac = Domain_Users;
2265 break;
2266 case DOMAIN_GROUP_RID_GUESTS:
2267 ac = Domain_Guests;
2268 break;
2269 case DOMAIN_GROUP_RID_COMPUTERS:
2270 ac = Domain_Computers;
2271 break;
2272 case DOMAIN_GROUP_RID_CONTROLLERS:
2273 ac = Domain_Controllers;
2274 break;
2275 case DOMAIN_GROUP_RID_CERT_ADMINS:
2276 ac = Cert_Publishers;
2277 break;
2278 case DOMAIN_GROUP_RID_SCHEMA_ADMINS:
2279 ac = Schema_Admins;
2280 break;
2281 case DOMAIN_GROUP_RID_ENTERPRISE_ADMINS:
2282 ac = Enterprise_Admins;
2283 break;
2284 case DOMAIN_GROUP_RID_POLICY_ADMINS:
2285 ac = Group_Policy_Creator_Owners;
2286 break;
2287 case DOMAIN_ALIAS_RID_RAS_SERVERS:
2288 ac = RAS_and_IAS_Servers;
2289 break;
2290 case 1000: /* first user account */
2291 size = UNLEN + 1;
2292 account_name = heap_alloc(size * sizeof(WCHAR));
2293 if (GetUserNameW(account_name, &size))
2294 ac = account_name;
2295 else
2296 dm = NULL;
2298 break;
2299 default:
2300 dm = NULL;
2301 break;
2309 if (dm) {
2310 DWORD ac_len = lstrlenW(ac);
2311 DWORD dm_len = lstrlenW(dm);
2312 BOOL status = TRUE;
2314 if (*accountSize > ac_len) {
2315 if (account)
2316 lstrcpyW(account, ac);
2318 if (*domainSize > dm_len) {
2319 if (domain)
2320 lstrcpyW(domain, dm);
2322 if ((*accountSize && *accountSize < ac_len) ||
2323 (!account && !*accountSize && ac_len) ||
2324 (*domainSize && *domainSize < dm_len) ||
2325 (!domain && !*domainSize && dm_len))
2327 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2328 status = FALSE;
2330 if (*domainSize)
2331 *domainSize = dm_len;
2332 else
2333 *domainSize = dm_len + 1;
2334 if (*accountSize)
2335 *accountSize = ac_len;
2336 else
2337 *accountSize = ac_len + 1;
2339 heap_free(account_name);
2340 heap_free(computer_name);
2341 if (status) *name_use = use;
2342 return status;
2345 heap_free(account_name);
2346 heap_free(computer_name);
2347 SetLastError(ERROR_NONE_MAPPED);
2348 return FALSE;
2351 /******************************************************************************
2352 * SetFileSecurityA [ADVAPI32.@]
2354 * See SetFileSecurityW.
2356 BOOL WINAPI SetFileSecurityA( LPCSTR lpFileName,
2357 SECURITY_INFORMATION RequestedInformation,
2358 PSECURITY_DESCRIPTOR pSecurityDescriptor)
2360 BOOL r;
2361 LPWSTR name;
2363 name = SERV_dup(lpFileName);
2364 r = SetFileSecurityW( name, RequestedInformation, pSecurityDescriptor );
2365 heap_free( name );
2367 return r;
2370 /******************************************************************************
2371 * SetFileSecurityW [ADVAPI32.@]
2373 * Sets the security of a file or directory.
2375 * PARAMS
2376 * lpFileName []
2377 * RequestedInformation []
2378 * pSecurityDescriptor []
2380 * RETURNS
2381 * Success: TRUE.
2382 * Failure: FALSE.
2384 BOOL WINAPI
2385 SetFileSecurityW( LPCWSTR lpFileName,
2386 SECURITY_INFORMATION RequestedInformation,
2387 PSECURITY_DESCRIPTOR pSecurityDescriptor )
2389 HANDLE file;
2390 DWORD access = 0, err;
2391 NTSTATUS status;
2393 TRACE("(%s, 0x%x, %p)\n", debugstr_w(lpFileName), RequestedInformation,
2394 pSecurityDescriptor );
2396 if (RequestedInformation & OWNER_SECURITY_INFORMATION ||
2397 RequestedInformation & GROUP_SECURITY_INFORMATION)
2398 access |= WRITE_OWNER;
2399 if (RequestedInformation & SACL_SECURITY_INFORMATION)
2400 access |= ACCESS_SYSTEM_SECURITY;
2401 if (RequestedInformation & DACL_SECURITY_INFORMATION)
2402 access |= WRITE_DAC;
2404 err = get_security_file( lpFileName, access, &file);
2405 if (err)
2407 SetLastError(err);
2408 return FALSE;
2411 status = NtSetSecurityObject( file, RequestedInformation, pSecurityDescriptor );
2412 CloseHandle( file );
2413 return set_ntstatus( status );
2416 /******************************************************************************
2417 * QueryWindows31FilesMigration [ADVAPI32.@]
2419 * PARAMS
2420 * x1 []
2422 BOOL WINAPI
2423 QueryWindows31FilesMigration( DWORD x1 )
2425 FIXME("(%d):stub\n",x1);
2426 return TRUE;
2429 /******************************************************************************
2430 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
2432 * PARAMS
2433 * x1 []
2434 * x2 []
2435 * x3 []
2436 * x4 []
2438 BOOL WINAPI
2439 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
2440 DWORD x4 )
2442 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
2443 return TRUE;
2446 /******************************************************************************
2447 * NotifyBootConfigStatus [ADVAPI32.@]
2449 * PARAMS
2450 * x1 []
2452 BOOL WINAPI
2453 NotifyBootConfigStatus( BOOL x1 )
2455 FIXME("(0x%08d):stub\n",x1);
2456 return TRUE;
2459 /******************************************************************************
2460 * RevertToSelf [ADVAPI32.@]
2462 * Ends the impersonation of a user.
2464 * PARAMS
2465 * void []
2467 * RETURNS
2468 * Success: TRUE.
2469 * Failure: FALSE.
2471 BOOL WINAPI
2472 RevertToSelf( void )
2474 HANDLE Token = NULL;
2475 return set_ntstatus( NtSetInformationThread( GetCurrentThread(),
2476 ThreadImpersonationToken, &Token, sizeof(Token) ) );
2479 /******************************************************************************
2480 * ImpersonateSelf [ADVAPI32.@]
2482 * Makes an impersonation token that represents the process user and assigns
2483 * to the current thread.
2485 * PARAMS
2486 * ImpersonationLevel [I] Level at which to impersonate.
2488 * RETURNS
2489 * Success: TRUE.
2490 * Failure: FALSE.
2492 BOOL WINAPI
2493 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
2495 return set_ntstatus( RtlImpersonateSelf( ImpersonationLevel ) );
2498 /******************************************************************************
2499 * ImpersonateLoggedOnUser [ADVAPI32.@]
2501 BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken)
2503 DWORD size;
2504 NTSTATUS Status;
2505 HANDLE ImpersonationToken;
2506 TOKEN_TYPE Type;
2507 static BOOL warn = TRUE;
2509 if (warn)
2511 FIXME( "(%p)\n", hToken );
2512 warn = FALSE;
2514 if (!GetTokenInformation( hToken, TokenType, &Type,
2515 sizeof(TOKEN_TYPE), &size ))
2516 return FALSE;
2518 if (Type == TokenPrimary)
2520 OBJECT_ATTRIBUTES ObjectAttributes;
2522 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
2524 Status = NtDuplicateToken( hToken,
2525 TOKEN_IMPERSONATE | TOKEN_QUERY,
2526 &ObjectAttributes,
2527 SecurityImpersonation,
2528 TokenImpersonation,
2529 &ImpersonationToken );
2530 if (Status != STATUS_SUCCESS)
2532 ERR( "NtDuplicateToken failed with error 0x%08x\n", Status );
2533 SetLastError( RtlNtStatusToDosError( Status ) );
2534 return FALSE;
2537 else
2538 ImpersonationToken = hToken;
2540 Status = NtSetInformationThread( GetCurrentThread(),
2541 ThreadImpersonationToken,
2542 &ImpersonationToken,
2543 sizeof(ImpersonationToken) );
2545 if (Type == TokenPrimary)
2546 NtClose( ImpersonationToken );
2548 if (Status != STATUS_SUCCESS)
2550 ERR( "NtSetInformationThread failed with error 0x%08x\n", Status );
2551 SetLastError( RtlNtStatusToDosError( Status ) );
2552 return FALSE;
2555 return TRUE;
2558 /******************************************************************************
2559 * ImpersonateAnonymousToken [ADVAPI32.@]
2561 BOOL WINAPI ImpersonateAnonymousToken( HANDLE thread )
2563 TRACE("(%p)\n", thread);
2564 return set_ntstatus( NtImpersonateAnonymousToken( thread ) );
2567 /******************************************************************************
2568 * AccessCheck [ADVAPI32.@]
2570 BOOL WINAPI
2571 AccessCheck(
2572 PSECURITY_DESCRIPTOR SecurityDescriptor,
2573 HANDLE ClientToken,
2574 DWORD DesiredAccess,
2575 PGENERIC_MAPPING GenericMapping,
2576 PPRIVILEGE_SET PrivilegeSet,
2577 LPDWORD PrivilegeSetLength,
2578 LPDWORD GrantedAccess,
2579 LPBOOL AccessStatus)
2581 NTSTATUS access_status;
2582 BOOL ret = set_ntstatus( NtAccessCheck(SecurityDescriptor, ClientToken, DesiredAccess,
2583 GenericMapping, PrivilegeSet, PrivilegeSetLength,
2584 GrantedAccess, &access_status) );
2585 if (ret) *AccessStatus = set_ntstatus( access_status );
2586 return ret;
2590 /******************************************************************************
2591 * AccessCheckByType [ADVAPI32.@]
2593 BOOL WINAPI AccessCheckByType(
2594 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2595 PSID PrincipalSelfSid,
2596 HANDLE ClientToken,
2597 DWORD DesiredAccess,
2598 POBJECT_TYPE_LIST ObjectTypeList,
2599 DWORD ObjectTypeListLength,
2600 PGENERIC_MAPPING GenericMapping,
2601 PPRIVILEGE_SET PrivilegeSet,
2602 LPDWORD PrivilegeSetLength,
2603 LPDWORD GrantedAccess,
2604 LPBOOL AccessStatus)
2606 FIXME("stub\n");
2608 *AccessStatus = TRUE;
2610 return !*AccessStatus;
2613 /******************************************************************************
2614 * MapGenericMask [ADVAPI32.@]
2616 * Maps generic access rights into specific access rights according to the
2617 * supplied mapping.
2619 * PARAMS
2620 * AccessMask [I/O] Access rights.
2621 * GenericMapping [I] The mapping between generic and specific rights.
2623 * RETURNS
2624 * Nothing.
2626 VOID WINAPI MapGenericMask( PDWORD AccessMask, PGENERIC_MAPPING GenericMapping )
2628 RtlMapGenericMask( AccessMask, GenericMapping );
2631 /*************************************************************************
2632 * SetKernelObjectSecurity [ADVAPI32.@]
2634 BOOL WINAPI SetKernelObjectSecurity (
2635 IN HANDLE Handle,
2636 IN SECURITY_INFORMATION SecurityInformation,
2637 IN PSECURITY_DESCRIPTOR SecurityDescriptor )
2639 return set_ntstatus (NtSetSecurityObject (Handle, SecurityInformation, SecurityDescriptor));
2643 /******************************************************************************
2644 * AddAuditAccessAce [ADVAPI32.@]
2646 BOOL WINAPI AddAuditAccessAce(
2647 IN OUT PACL pAcl,
2648 IN DWORD dwAceRevision,
2649 IN DWORD dwAccessMask,
2650 IN PSID pSid,
2651 IN BOOL bAuditSuccess,
2652 IN BOOL bAuditFailure)
2654 return set_ntstatus( RtlAddAuditAccessAce(pAcl, dwAceRevision, dwAccessMask, pSid,
2655 bAuditSuccess, bAuditFailure) );
2658 /******************************************************************************
2659 * AddAuditAccessAce [ADVAPI32.@]
2661 BOOL WINAPI AddAuditAccessAceEx(
2662 IN OUT PACL pAcl,
2663 IN DWORD dwAceRevision,
2664 IN DWORD dwAceFlags,
2665 IN DWORD dwAccessMask,
2666 IN PSID pSid,
2667 IN BOOL bAuditSuccess,
2668 IN BOOL bAuditFailure)
2670 return set_ntstatus( RtlAddAuditAccessAceEx(pAcl, dwAceRevision, dwAceFlags, dwAccessMask, pSid,
2671 bAuditSuccess, bAuditFailure) );
2674 /******************************************************************************
2675 * LookupAccountNameA [ADVAPI32.@]
2677 BOOL WINAPI
2678 LookupAccountNameA(
2679 IN LPCSTR system,
2680 IN LPCSTR account,
2681 OUT PSID sid,
2682 OUT LPDWORD cbSid,
2683 LPSTR ReferencedDomainName,
2684 IN OUT LPDWORD cbReferencedDomainName,
2685 OUT PSID_NAME_USE name_use )
2687 BOOL ret;
2688 UNICODE_STRING lpSystemW;
2689 UNICODE_STRING lpAccountW;
2690 LPWSTR lpReferencedDomainNameW = NULL;
2692 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, system);
2693 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, account);
2695 if (ReferencedDomainName)
2696 lpReferencedDomainNameW = heap_alloc(*cbReferencedDomainName * sizeof(WCHAR));
2698 ret = LookupAccountNameW(lpSystemW.Buffer, lpAccountW.Buffer, sid, cbSid, lpReferencedDomainNameW,
2699 cbReferencedDomainName, name_use);
2701 if (ret && lpReferencedDomainNameW)
2703 WideCharToMultiByte(CP_ACP, 0, lpReferencedDomainNameW, -1,
2704 ReferencedDomainName, *cbReferencedDomainName+1, NULL, NULL);
2707 RtlFreeUnicodeString(&lpSystemW);
2708 RtlFreeUnicodeString(&lpAccountW);
2709 heap_free(lpReferencedDomainNameW);
2711 return ret;
2714 /******************************************************************************
2715 * lookup_user_account_name
2717 static BOOL lookup_user_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2718 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2720 char buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
2721 DWORD len = sizeof(buffer);
2722 HANDLE token;
2723 BOOL ret;
2724 PSID pSid;
2725 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
2726 DWORD nameLen;
2728 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
2730 if (GetLastError() != ERROR_NO_TOKEN) return FALSE;
2731 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) return FALSE;
2734 ret = GetTokenInformation(token, TokenUser, buffer, len, &len);
2735 CloseHandle( token );
2737 if (!ret) return FALSE;
2739 pSid = ((TOKEN_USER *)buffer)->User.Sid;
2741 if (Sid != NULL && (*cbSid >= GetLengthSid(pSid)))
2742 CopySid(*cbSid, Sid, pSid);
2743 if (*cbSid < GetLengthSid(pSid))
2745 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2746 ret = FALSE;
2748 *cbSid = GetLengthSid(pSid);
2750 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
2751 if (!GetComputerNameW(domainName, &nameLen))
2753 domainName[0] = 0;
2754 nameLen = 0;
2756 if (*cchReferencedDomainName <= nameLen || !ret)
2758 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2759 nameLen += 1;
2760 ret = FALSE;
2762 else if (ReferencedDomainName)
2763 strcpyW(ReferencedDomainName, domainName);
2765 *cchReferencedDomainName = nameLen;
2767 if (ret)
2768 *peUse = SidTypeUser;
2770 return ret;
2773 /******************************************************************************
2774 * lookup_computer_account_name
2776 static BOOL lookup_computer_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
2777 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2779 MAX_SID local;
2780 BOOL ret;
2781 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
2782 DWORD nameLen;
2784 if ((ret = ADVAPI_GetComputerSid(&local)))
2786 if (Sid != NULL && (*cbSid >= GetLengthSid(&local)))
2787 CopySid(*cbSid, Sid, &local);
2788 if (*cbSid < GetLengthSid(&local))
2790 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2791 ret = FALSE;
2793 *cbSid = GetLengthSid(&local);
2796 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
2797 if (!GetComputerNameW(domainName, &nameLen))
2799 domainName[0] = 0;
2800 nameLen = 0;
2802 if (*cchReferencedDomainName <= nameLen || !ret)
2804 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2805 nameLen += 1;
2806 ret = FALSE;
2808 else if (ReferencedDomainName)
2809 strcpyW(ReferencedDomainName, domainName);
2811 *cchReferencedDomainName = nameLen;
2813 if (ret)
2814 *peUse = SidTypeDomain;
2816 return ret;
2819 static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STRING *account,
2820 LSA_UNICODE_STRING *domain )
2822 WCHAR *p = str->Buffer + str->Length / sizeof(WCHAR) - 1;
2824 while (p > str->Buffer && *p != '\\') p--;
2826 if (*p == '\\')
2828 domain->Buffer = str->Buffer;
2829 domain->Length = (p - str->Buffer) * sizeof(WCHAR);
2831 account->Buffer = p + 1;
2832 account->Length = str->Length - ((p - str->Buffer + 1) * sizeof(WCHAR));
2834 else
2836 domain->Buffer = NULL;
2837 domain->Length = 0;
2839 account->Buffer = str->Buffer;
2840 account->Length = str->Length;
2844 static BOOL match_domain( ULONG idx, const LSA_UNICODE_STRING *domain )
2846 ULONG len = strlenW( ACCOUNT_SIDS[idx].domain );
2848 if (len == domain->Length / sizeof(WCHAR) && !strncmpiW( domain->Buffer, ACCOUNT_SIDS[idx].domain, len ))
2849 return TRUE;
2851 return FALSE;
2854 static BOOL match_account( ULONG idx, const LSA_UNICODE_STRING *account )
2856 ULONG len = strlenW( ACCOUNT_SIDS[idx].account );
2858 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].account, len ))
2859 return TRUE;
2861 if (ACCOUNT_SIDS[idx].alias)
2863 len = strlenW( ACCOUNT_SIDS[idx].alias );
2864 if (len == account->Length / sizeof(WCHAR) && !strncmpiW( account->Buffer, ACCOUNT_SIDS[idx].alias, len ))
2865 return TRUE;
2867 return FALSE;
2871 * Helper function for LookupAccountNameW
2873 BOOL lookup_local_wellknown_name( const LSA_UNICODE_STRING *account_and_domain,
2874 PSID Sid, LPDWORD cbSid,
2875 LPWSTR ReferencedDomainName,
2876 LPDWORD cchReferencedDomainName,
2877 PSID_NAME_USE peUse, BOOL *handled )
2879 PSID pSid;
2880 LSA_UNICODE_STRING account, domain;
2881 BOOL ret = TRUE;
2882 ULONG i;
2884 *handled = FALSE;
2885 split_domain_account( account_and_domain, &account, &domain );
2887 for (i = 0; i < sizeof(ACCOUNT_SIDS) / sizeof(ACCOUNT_SIDS[0]); i++)
2889 /* check domain first */
2890 if (domain.Buffer && !match_domain( i, &domain )) continue;
2892 if (match_account( i, &account ))
2894 DWORD len, sidLen = SECURITY_MAX_SID_SIZE;
2896 if (!(pSid = heap_alloc( sidLen ))) return FALSE;
2898 if ((ret = CreateWellKnownSid( ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen )))
2900 if (*cbSid < sidLen)
2902 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2903 ret = FALSE;
2905 else if (Sid)
2907 CopySid(*cbSid, Sid, pSid);
2909 *cbSid = sidLen;
2912 len = strlenW( ACCOUNT_SIDS[i].domain );
2913 if (*cchReferencedDomainName <= len || !ret)
2915 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2916 len++;
2917 ret = FALSE;
2919 else if (ReferencedDomainName)
2921 strcpyW( ReferencedDomainName, ACCOUNT_SIDS[i].domain );
2924 *cchReferencedDomainName = len;
2925 if (ret)
2926 *peUse = ACCOUNT_SIDS[i].name_use;
2928 heap_free(pSid);
2929 *handled = TRUE;
2930 return ret;
2933 return ret;
2936 BOOL lookup_local_user_name( const LSA_UNICODE_STRING *account_and_domain,
2937 PSID Sid, LPDWORD cbSid,
2938 LPWSTR ReferencedDomainName,
2939 LPDWORD cchReferencedDomainName,
2940 PSID_NAME_USE peUse, BOOL *handled )
2942 DWORD nameLen;
2943 LPWSTR userName = NULL;
2944 LSA_UNICODE_STRING account, domain;
2945 BOOL ret = TRUE;
2947 *handled = FALSE;
2948 split_domain_account( account_and_domain, &account, &domain );
2950 /* Let the current Unix user id masquerade as first Windows user account */
2952 nameLen = UNLEN + 1;
2953 if (!(userName = heap_alloc( nameLen * sizeof(WCHAR) ))) return FALSE;
2955 if (domain.Buffer)
2957 /* check to make sure this account is on this computer */
2958 if (GetComputerNameW( userName, &nameLen ) &&
2959 (domain.Length / sizeof(WCHAR) != nameLen || strncmpW( domain.Buffer, userName, nameLen )))
2961 SetLastError(ERROR_NONE_MAPPED);
2962 ret = FALSE;
2964 nameLen = UNLEN + 1;
2967 if (GetUserNameW( userName, &nameLen ) &&
2968 account.Length / sizeof(WCHAR) == nameLen - 1 && !strncmpW( account.Buffer, userName, nameLen - 1 ))
2970 ret = lookup_user_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2971 *handled = TRUE;
2973 else
2975 nameLen = UNLEN + 1;
2976 if (GetComputerNameW( userName, &nameLen ) &&
2977 account.Length / sizeof(WCHAR) == nameLen && !strncmpW( account.Buffer, userName , nameLen ))
2979 ret = lookup_computer_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
2980 *handled = TRUE;
2984 heap_free(userName);
2985 return ret;
2988 /******************************************************************************
2989 * LookupAccountNameW [ADVAPI32.@]
2991 BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
2992 LPDWORD cbSid, LPWSTR ReferencedDomainName,
2993 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
2995 BOOL ret, handled;
2996 LSA_UNICODE_STRING account;
2998 TRACE("%s %s %p %p %p %p %p\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
2999 Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
3001 if (!ADVAPI_IsLocalComputer( lpSystemName ))
3003 FIXME("remote computer not supported\n");
3004 SetLastError( RPC_S_SERVER_UNAVAILABLE );
3005 return FALSE;
3008 if (!lpAccountName || !strcmpW( lpAccountName, Blank ))
3010 lpAccountName = BUILTIN;
3013 RtlInitUnicodeString( &account, lpAccountName );
3015 /* Check well known SIDs first */
3016 ret = lookup_local_wellknown_name( &account, Sid, cbSid, ReferencedDomainName,
3017 cchReferencedDomainName, peUse, &handled );
3018 if (handled)
3019 return ret;
3021 /* Check user names */
3022 ret = lookup_local_user_name( &account, Sid, cbSid, ReferencedDomainName,
3023 cchReferencedDomainName, peUse, &handled);
3024 if (handled)
3025 return ret;
3027 SetLastError( ERROR_NONE_MAPPED );
3028 return FALSE;
3031 /******************************************************************************
3032 * PrivilegeCheck [ADVAPI32.@]
3034 BOOL WINAPI PrivilegeCheck( HANDLE ClientToken, PPRIVILEGE_SET RequiredPrivileges, LPBOOL pfResult)
3036 BOOL ret;
3037 BOOLEAN Result;
3039 TRACE("%p %p %p\n", ClientToken, RequiredPrivileges, pfResult);
3041 ret = set_ntstatus (NtPrivilegeCheck (ClientToken, RequiredPrivileges, &Result));
3042 if (ret)
3043 *pfResult = Result;
3044 return ret;
3047 /******************************************************************************
3048 * AccessCheckAndAuditAlarmA [ADVAPI32.@]
3050 BOOL WINAPI AccessCheckAndAuditAlarmA(LPCSTR Subsystem, LPVOID HandleId, LPSTR ObjectTypeName,
3051 LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
3052 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
3053 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
3055 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_a(Subsystem),
3056 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName),
3057 SecurityDescriptor, DesiredAccess, GenericMapping,
3058 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
3059 return TRUE;
3062 /******************************************************************************
3063 * AccessCheckAndAuditAlarmW [ADVAPI32.@]
3065 BOOL WINAPI AccessCheckAndAuditAlarmW(LPCWSTR Subsystem, LPVOID HandleId, LPWSTR ObjectTypeName,
3066 LPWSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
3067 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
3068 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
3070 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_w(Subsystem),
3071 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName),
3072 SecurityDescriptor, DesiredAccess, GenericMapping,
3073 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
3074 return TRUE;
3077 BOOL WINAPI ObjectCloseAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3079 FIXME("stub (%s,%p,%x)\n", debugstr_a(SubsystemName), HandleId, GenerateOnClose);
3081 return TRUE;
3084 BOOL WINAPI ObjectCloseAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3086 FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
3088 return TRUE;
3091 BOOL WINAPI ObjectDeleteAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
3093 FIXME("stub (%s,%p,%x)\n", debugstr_w(SubsystemName), HandleId, GenerateOnClose);
3095 return TRUE;
3098 BOOL WINAPI ObjectOpenAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName,
3099 LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3100 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3101 LPBOOL GenerateOnClose)
3103 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_a(SubsystemName),
3104 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName), pSecurityDescriptor,
3105 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3106 GenerateOnClose);
3108 return TRUE;
3111 BOOL WINAPI ObjectOpenAuditAlarmW(LPCWSTR SubsystemName, LPVOID HandleId, LPWSTR ObjectTypeName,
3112 LPWSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
3113 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
3114 LPBOOL GenerateOnClose)
3116 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_w(SubsystemName),
3117 HandleId, debugstr_w(ObjectTypeName), debugstr_w(ObjectName), pSecurityDescriptor,
3118 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
3119 GenerateOnClose);
3121 return TRUE;
3124 BOOL WINAPI ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3125 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3127 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_a(SubsystemName), HandleId, ClientToken,
3128 DesiredAccess, Privileges, AccessGranted);
3130 return TRUE;
3133 BOOL WINAPI ObjectPrivilegeAuditAlarmW( LPCWSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
3134 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3136 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_w(SubsystemName), HandleId, ClientToken,
3137 DesiredAccess, Privileges, AccessGranted);
3139 return TRUE;
3142 BOOL WINAPI PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken,
3143 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3145 FIXME("stub (%s,%s,%p,%p,%x)\n", debugstr_a(SubsystemName), debugstr_a(ServiceName),
3146 ClientToken, Privileges, AccessGranted);
3148 return TRUE;
3151 BOOL WINAPI PrivilegedServiceAuditAlarmW( LPCWSTR SubsystemName, LPCWSTR ServiceName, HANDLE ClientToken,
3152 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
3154 FIXME("stub %s,%s,%p,%p,%x)\n", debugstr_w(SubsystemName), debugstr_w(ServiceName),
3155 ClientToken, Privileges, AccessGranted);
3157 return TRUE;
3160 /******************************************************************************
3161 * GetSecurityInfo [ADVAPI32.@]
3163 * Retrieves a copy of the security descriptor associated with an object.
3165 * PARAMS
3166 * hObject [I] A handle for the object.
3167 * ObjectType [I] The type of object.
3168 * SecurityInfo [I] A bitmask indicating what info to retrieve.
3169 * ppsidOwner [O] If non-null, receives a pointer to the owner SID.
3170 * ppsidGroup [O] If non-null, receives a pointer to the group SID.
3171 * ppDacl [O] If non-null, receives a pointer to the DACL.
3172 * ppSacl [O] If non-null, receives a pointer to the SACL.
3173 * ppSecurityDescriptor [O] Receives a pointer to the security descriptor,
3174 * which must be freed with LocalFree.
3176 * RETURNS
3177 * ERROR_SUCCESS if all's well, and a WIN32 error code otherwise.
3179 DWORD WINAPI GetSecurityInfo(
3180 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3181 SECURITY_INFORMATION SecurityInfo, PSID *ppsidOwner,
3182 PSID *ppsidGroup, PACL *ppDacl, PACL *ppSacl,
3183 PSECURITY_DESCRIPTOR *ppSecurityDescriptor
3186 PSECURITY_DESCRIPTOR sd;
3187 NTSTATUS status;
3188 ULONG n1, n2;
3189 BOOL present, defaulted;
3191 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
3192 if (!(ppsidOwner||ppsidGroup||ppDacl||ppSacl||ppSecurityDescriptor)) return ERROR_INVALID_PARAMETER;
3194 /* If no descriptor, we have to check that there's a pointer for the requested information */
3195 if( !ppSecurityDescriptor && (
3196 ((SecurityInfo & OWNER_SECURITY_INFORMATION) && !ppsidOwner)
3197 || ((SecurityInfo & GROUP_SECURITY_INFORMATION) && !ppsidGroup)
3198 || ((SecurityInfo & DACL_SECURITY_INFORMATION) && !ppDacl)
3199 || ((SecurityInfo & SACL_SECURITY_INFORMATION) && !ppSacl) ))
3200 return ERROR_INVALID_PARAMETER;
3202 switch (ObjectType)
3204 case SE_SERVICE:
3205 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, NULL, 0, &n1);
3206 break;
3207 default:
3208 status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1);
3209 break;
3211 if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS)
3212 return RtlNtStatusToDosError(status);
3214 sd = LocalAlloc(0, n1);
3215 if (!sd)
3216 return ERROR_NOT_ENOUGH_MEMORY;
3218 switch (ObjectType)
3220 case SE_SERVICE:
3221 status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, sd, n1, &n2);
3222 break;
3223 default:
3224 status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2);
3225 break;
3227 if (status != STATUS_SUCCESS)
3229 LocalFree(sd);
3230 return RtlNtStatusToDosError(status);
3233 if (ppsidOwner)
3235 *ppsidOwner = NULL;
3236 GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted);
3238 if (ppsidGroup)
3240 *ppsidGroup = NULL;
3241 GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted);
3243 if (ppDacl)
3245 *ppDacl = NULL;
3246 GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted);
3248 if (ppSacl)
3250 *ppSacl = NULL;
3251 GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted);
3253 if (ppSecurityDescriptor)
3254 *ppSecurityDescriptor = sd;
3256 /* The security descriptor (sd) cannot be freed if ppSecurityDescriptor is
3257 * NULL, because native happily returns the SIDs and ACLs that are requested
3258 * in this case.
3261 return ERROR_SUCCESS;
3264 /******************************************************************************
3265 * GetSecurityInfoExA [ADVAPI32.@]
3267 DWORD WINAPI GetSecurityInfoExA(
3268 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3269 SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
3270 LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
3271 PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
3274 FIXME("stub!\n");
3275 return ERROR_BAD_PROVIDER;
3278 /******************************************************************************
3279 * GetSecurityInfoExW [ADVAPI32.@]
3281 DWORD WINAPI GetSecurityInfoExW(
3282 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
3283 SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
3284 LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList,
3285 PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
3288 FIXME("stub!\n");
3289 return ERROR_BAD_PROVIDER;
3292 /******************************************************************************
3293 * BuildExplicitAccessWithNameA [ADVAPI32.@]
3295 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
3296 LPSTR pTrusteeName, DWORD AccessPermissions,
3297 ACCESS_MODE AccessMode, DWORD Inheritance )
3299 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_a(pTrusteeName),
3300 AccessPermissions, AccessMode, Inheritance);
3302 pExplicitAccess->grfAccessPermissions = AccessPermissions;
3303 pExplicitAccess->grfAccessMode = AccessMode;
3304 pExplicitAccess->grfInheritance = Inheritance;
3306 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3307 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3308 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3309 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3310 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3313 /******************************************************************************
3314 * BuildExplicitAccessWithNameW [ADVAPI32.@]
3316 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
3317 LPWSTR pTrusteeName, DWORD AccessPermissions,
3318 ACCESS_MODE AccessMode, DWORD Inheritance )
3320 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_w(pTrusteeName),
3321 AccessPermissions, AccessMode, Inheritance);
3323 pExplicitAccess->grfAccessPermissions = AccessPermissions;
3324 pExplicitAccess->grfAccessMode = AccessMode;
3325 pExplicitAccess->grfInheritance = Inheritance;
3327 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
3328 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3329 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3330 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3331 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
3334 /******************************************************************************
3335 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
3337 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
3338 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
3339 LPSTR InheritedObjectTypeName, LPSTR Name )
3341 DWORD ObjectsPresent = 0;
3343 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3344 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
3346 /* Fill the OBJECTS_AND_NAME structure */
3347 pObjName->ObjectType = ObjectType;
3348 if (ObjectTypeName != NULL)
3350 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3353 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3354 if (InheritedObjectTypeName != NULL)
3356 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3359 pObjName->ObjectsPresent = ObjectsPresent;
3360 pObjName->ptstrName = Name;
3362 /* Fill the TRUSTEE structure */
3363 pTrustee->pMultipleTrustee = NULL;
3364 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3365 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3366 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3367 pTrustee->ptstrName = (LPSTR)pObjName;
3370 /******************************************************************************
3371 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
3373 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
3374 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
3375 LPWSTR InheritedObjectTypeName, LPWSTR Name )
3377 DWORD ObjectsPresent = 0;
3379 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
3380 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
3382 /* Fill the OBJECTS_AND_NAME structure */
3383 pObjName->ObjectType = ObjectType;
3384 if (ObjectTypeName != NULL)
3386 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3389 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
3390 if (InheritedObjectTypeName != NULL)
3392 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3395 pObjName->ObjectsPresent = ObjectsPresent;
3396 pObjName->ptstrName = Name;
3398 /* Fill the TRUSTEE structure */
3399 pTrustee->pMultipleTrustee = NULL;
3400 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3401 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
3402 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3403 pTrustee->ptstrName = (LPWSTR)pObjName;
3406 /******************************************************************************
3407 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
3409 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
3410 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3412 DWORD ObjectsPresent = 0;
3414 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3416 /* Fill the OBJECTS_AND_SID structure */
3417 if (pObjectGuid != NULL)
3419 pObjSid->ObjectTypeGuid = *pObjectGuid;
3420 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3422 else
3424 ZeroMemory(&pObjSid->ObjectTypeGuid,
3425 sizeof(GUID));
3428 if (pInheritedObjectGuid != NULL)
3430 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3431 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3433 else
3435 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3436 sizeof(GUID));
3439 pObjSid->ObjectsPresent = ObjectsPresent;
3440 pObjSid->pSid = pSid;
3442 /* Fill the TRUSTEE structure */
3443 pTrustee->pMultipleTrustee = NULL;
3444 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3445 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3446 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3447 pTrustee->ptstrName = (LPSTR) pObjSid;
3450 /******************************************************************************
3451 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
3453 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
3454 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
3456 DWORD ObjectsPresent = 0;
3458 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
3460 /* Fill the OBJECTS_AND_SID structure */
3461 if (pObjectGuid != NULL)
3463 pObjSid->ObjectTypeGuid = *pObjectGuid;
3464 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
3466 else
3468 ZeroMemory(&pObjSid->ObjectTypeGuid,
3469 sizeof(GUID));
3472 if (pInheritedObjectGuid != NULL)
3474 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
3475 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
3477 else
3479 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
3480 sizeof(GUID));
3483 pObjSid->ObjectsPresent = ObjectsPresent;
3484 pObjSid->pSid = pSid;
3486 /* Fill the TRUSTEE structure */
3487 pTrustee->pMultipleTrustee = NULL;
3488 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3489 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
3490 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3491 pTrustee->ptstrName = (LPWSTR) pObjSid;
3494 /******************************************************************************
3495 * BuildTrusteeWithSidA [ADVAPI32.@]
3497 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid)
3499 TRACE("%p %p\n", pTrustee, pSid);
3501 pTrustee->pMultipleTrustee = NULL;
3502 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3503 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3504 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3505 pTrustee->ptstrName = pSid;
3508 /******************************************************************************
3509 * BuildTrusteeWithSidW [ADVAPI32.@]
3511 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
3513 TRACE("%p %p\n", pTrustee, pSid);
3515 pTrustee->pMultipleTrustee = NULL;
3516 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3517 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
3518 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3519 pTrustee->ptstrName = pSid;
3522 /******************************************************************************
3523 * BuildTrusteeWithNameA [ADVAPI32.@]
3525 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
3527 TRACE("%p %s\n", pTrustee, debugstr_a(name) );
3529 pTrustee->pMultipleTrustee = NULL;
3530 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3531 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3532 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3533 pTrustee->ptstrName = name;
3536 /******************************************************************************
3537 * BuildTrusteeWithNameW [ADVAPI32.@]
3539 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
3541 TRACE("%p %s\n", pTrustee, debugstr_w(name) );
3543 pTrustee->pMultipleTrustee = NULL;
3544 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3545 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
3546 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
3547 pTrustee->ptstrName = name;
3550 /******************************************************************************
3551 * GetTrusteeFormA [ADVAPI32.@]
3553 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee)
3555 TRACE("(%p)\n", pTrustee);
3557 if (!pTrustee)
3558 return TRUSTEE_BAD_FORM;
3560 return pTrustee->TrusteeForm;
3563 /******************************************************************************
3564 * GetTrusteeFormW [ADVAPI32.@]
3566 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee)
3568 TRACE("(%p)\n", pTrustee);
3570 if (!pTrustee)
3571 return TRUSTEE_BAD_FORM;
3573 return pTrustee->TrusteeForm;
3576 /******************************************************************************
3577 * GetTrusteeNameA [ADVAPI32.@]
3579 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee)
3581 TRACE("(%p)\n", pTrustee);
3583 if (!pTrustee)
3584 return NULL;
3586 return pTrustee->ptstrName;
3589 /******************************************************************************
3590 * GetTrusteeNameW [ADVAPI32.@]
3592 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee)
3594 TRACE("(%p)\n", pTrustee);
3596 if (!pTrustee)
3597 return NULL;
3599 return pTrustee->ptstrName;
3602 /******************************************************************************
3603 * GetTrusteeTypeA [ADVAPI32.@]
3605 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee)
3607 TRACE("(%p)\n", pTrustee);
3609 if (!pTrustee)
3610 return TRUSTEE_IS_UNKNOWN;
3612 return pTrustee->TrusteeType;
3615 /******************************************************************************
3616 * GetTrusteeTypeW [ADVAPI32.@]
3618 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee)
3620 TRACE("(%p)\n", pTrustee);
3622 if (!pTrustee)
3623 return TRUSTEE_IS_UNKNOWN;
3625 return pTrustee->TrusteeType;
3628 BOOL WINAPI SetAclInformation( PACL pAcl, LPVOID pAclInformation,
3629 DWORD nAclInformationLength,
3630 ACL_INFORMATION_CLASS dwAclInformationClass )
3632 FIXME("%p %p 0x%08x 0x%08x - stub\n", pAcl, pAclInformation,
3633 nAclInformationLength, dwAclInformationClass);
3635 return TRUE;
3638 static DWORD trustee_name_A_to_W(TRUSTEE_FORM form, char *trustee_nameA, WCHAR **ptrustee_nameW)
3640 switch (form)
3642 case TRUSTEE_IS_NAME:
3644 *ptrustee_nameW = SERV_dup(trustee_nameA);
3645 return ERROR_SUCCESS;
3647 case TRUSTEE_IS_OBJECTS_AND_NAME:
3649 OBJECTS_AND_NAME_A *objA = (OBJECTS_AND_NAME_A *)trustee_nameA;
3650 OBJECTS_AND_NAME_W *objW = NULL;
3652 if (objA)
3654 if (!(objW = heap_alloc( sizeof(OBJECTS_AND_NAME_W) )))
3655 return ERROR_NOT_ENOUGH_MEMORY;
3657 objW->ObjectsPresent = objA->ObjectsPresent;
3658 objW->ObjectType = objA->ObjectType;
3659 objW->ObjectTypeName = SERV_dup(objA->ObjectTypeName);
3660 objW->InheritedObjectTypeName = SERV_dup(objA->InheritedObjectTypeName);
3661 objW->ptstrName = SERV_dup(objA->ptstrName);
3664 *ptrustee_nameW = (WCHAR *)objW;
3665 return ERROR_SUCCESS;
3667 /* These forms do not require conversion. */
3668 case TRUSTEE_IS_SID:
3669 case TRUSTEE_IS_OBJECTS_AND_SID:
3670 *ptrustee_nameW = (WCHAR *)trustee_nameA;
3671 return ERROR_SUCCESS;
3672 default:
3673 return ERROR_INVALID_PARAMETER;
3677 static void free_trustee_name(TRUSTEE_FORM form, WCHAR *trustee_nameW)
3679 switch (form)
3681 case TRUSTEE_IS_NAME:
3682 heap_free( trustee_nameW );
3683 break;
3684 case TRUSTEE_IS_OBJECTS_AND_NAME:
3686 OBJECTS_AND_NAME_W *objW = (OBJECTS_AND_NAME_W *)trustee_nameW;
3688 if (objW)
3690 heap_free( objW->ptstrName );
3691 heap_free( objW->InheritedObjectTypeName );
3692 heap_free( objW->ObjectTypeName );
3693 heap_free( objW );
3696 break;
3698 /* Other forms did not require allocation, so no freeing is necessary. */
3699 default:
3700 break;
3704 /******************************************************************************
3705 * SetEntriesInAclA [ADVAPI32.@]
3707 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
3708 PACL OldAcl, PACL* NewAcl )
3710 DWORD err = ERROR_SUCCESS;
3711 EXPLICIT_ACCESSW *pEntriesW;
3712 UINT alloc_index, free_index;
3714 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3716 if (NewAcl)
3717 *NewAcl = NULL;
3719 if (!count && !OldAcl)
3720 return ERROR_SUCCESS;
3722 pEntriesW = heap_alloc( count * sizeof(EXPLICIT_ACCESSW) );
3723 if (!pEntriesW)
3724 return ERROR_NOT_ENOUGH_MEMORY;
3726 for (alloc_index = 0; alloc_index < count; ++alloc_index)
3728 pEntriesW[alloc_index].grfAccessPermissions = pEntries[alloc_index].grfAccessPermissions;
3729 pEntriesW[alloc_index].grfAccessMode = pEntries[alloc_index].grfAccessMode;
3730 pEntriesW[alloc_index].grfInheritance = pEntries[alloc_index].grfInheritance;
3731 pEntriesW[alloc_index].Trustee.pMultipleTrustee = NULL; /* currently not supported */
3732 pEntriesW[alloc_index].Trustee.MultipleTrusteeOperation = pEntries[alloc_index].Trustee.MultipleTrusteeOperation;
3733 pEntriesW[alloc_index].Trustee.TrusteeForm = pEntries[alloc_index].Trustee.TrusteeForm;
3734 pEntriesW[alloc_index].Trustee.TrusteeType = pEntries[alloc_index].Trustee.TrusteeType;
3736 err = trustee_name_A_to_W( pEntries[alloc_index].Trustee.TrusteeForm,
3737 pEntries[alloc_index].Trustee.ptstrName,
3738 &pEntriesW[alloc_index].Trustee.ptstrName );
3739 if (err != ERROR_SUCCESS)
3741 if (err == ERROR_INVALID_PARAMETER)
3742 WARN("bad trustee form %d for trustee %d\n",
3743 pEntries[alloc_index].Trustee.TrusteeForm, alloc_index);
3745 goto cleanup;
3749 err = SetEntriesInAclW( count, pEntriesW, OldAcl, NewAcl );
3751 cleanup:
3752 /* Free any previously allocated trustee name buffers, taking into account
3753 * a possible out-of-memory condition while building the EXPLICIT_ACCESSW
3754 * list. */
3755 for (free_index = 0; free_index < alloc_index; ++free_index)
3756 free_trustee_name( pEntriesW[free_index].Trustee.TrusteeForm, pEntriesW[free_index].Trustee.ptstrName );
3758 heap_free( pEntriesW );
3759 return err;
3762 /******************************************************************************
3763 * SetEntriesInAclW [ADVAPI32.@]
3765 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
3766 PACL OldAcl, PACL* NewAcl )
3768 ULONG i;
3769 PSID *ppsid;
3770 DWORD ret = ERROR_SUCCESS;
3771 DWORD acl_size = sizeof(ACL);
3772 NTSTATUS status;
3774 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
3776 if (NewAcl)
3777 *NewAcl = NULL;
3779 if (!count && !OldAcl)
3780 return ERROR_SUCCESS;
3782 /* allocate array of maximum sized sids allowed */
3783 ppsid = heap_alloc(count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
3784 if (!ppsid)
3785 return ERROR_OUTOFMEMORY;
3787 for (i = 0; i < count; i++)
3789 ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3791 TRACE("[%d]:\n\tgrfAccessPermissions = 0x%x\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%x\n\t"
3792 "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
3793 "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
3794 pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
3795 pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
3796 pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
3797 pEntries[i].Trustee.ptstrName);
3799 if (pEntries[i].Trustee.MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
3801 WARN("bad multiple trustee operation %d for trustee %d\n", pEntries[i].Trustee.MultipleTrusteeOperation, i);
3802 ret = ERROR_INVALID_PARAMETER;
3803 goto exit;
3806 switch (pEntries[i].Trustee.TrusteeForm)
3808 case TRUSTEE_IS_SID:
3809 if (!CopySid(FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]),
3810 ppsid[i], pEntries[i].Trustee.ptstrName))
3812 WARN("bad sid %p for trustee %d\n", pEntries[i].Trustee.ptstrName, i);
3813 ret = ERROR_INVALID_PARAMETER;
3814 goto exit;
3816 break;
3817 case TRUSTEE_IS_NAME:
3819 DWORD sid_size = FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
3820 DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
3821 SID_NAME_USE use;
3822 if (!strcmpW( pEntries[i].Trustee.ptstrName, CURRENT_USER ))
3824 if (!lookup_user_account_name( ppsid[i], &sid_size, NULL, &domain_size, &use ))
3826 ret = GetLastError();
3827 goto exit;
3830 else if (!LookupAccountNameW(NULL, pEntries[i].Trustee.ptstrName, ppsid[i], &sid_size, NULL, &domain_size, &use))
3832 WARN("bad user name %s for trustee %d\n", debugstr_w(pEntries[i].Trustee.ptstrName), i);
3833 ret = ERROR_INVALID_PARAMETER;
3834 goto exit;
3836 break;
3838 case TRUSTEE_IS_OBJECTS_AND_SID:
3839 FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
3840 break;
3841 case TRUSTEE_IS_OBJECTS_AND_NAME:
3842 FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
3843 break;
3844 default:
3845 WARN("bad trustee form %d for trustee %d\n", pEntries[i].Trustee.TrusteeForm, i);
3846 ret = ERROR_INVALID_PARAMETER;
3847 goto exit;
3850 /* Note: we overestimate the ACL size here as a tradeoff between
3851 * instructions (simplicity) and memory */
3852 switch (pEntries[i].grfAccessMode)
3854 case GRANT_ACCESS:
3855 case SET_ACCESS:
3856 acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3857 break;
3858 case DENY_ACCESS:
3859 acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
3860 break;
3861 case SET_AUDIT_SUCCESS:
3862 case SET_AUDIT_FAILURE:
3863 acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
3864 break;
3865 case REVOKE_ACCESS:
3866 break;
3867 default:
3868 WARN("bad access mode %d for trustee %d\n", pEntries[i].grfAccessMode, i);
3869 ret = ERROR_INVALID_PARAMETER;
3870 goto exit;
3874 if (OldAcl)
3876 ACL_SIZE_INFORMATION size_info;
3878 status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
3879 if (status != STATUS_SUCCESS)
3881 ret = RtlNtStatusToDosError(status);
3882 goto exit;
3884 acl_size += size_info.AclBytesInUse - sizeof(ACL);
3887 *NewAcl = LocalAlloc(0, acl_size);
3888 if (!*NewAcl)
3890 ret = ERROR_OUTOFMEMORY;
3891 goto exit;
3894 status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
3895 if (status != STATUS_SUCCESS)
3897 ret = RtlNtStatusToDosError(status);
3898 goto exit;
3901 for (i = 0; i < count; i++)
3903 switch (pEntries[i].grfAccessMode)
3905 case GRANT_ACCESS:
3906 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3907 pEntries[i].grfInheritance,
3908 pEntries[i].grfAccessPermissions,
3909 ppsid[i]);
3910 break;
3911 case SET_ACCESS:
3913 ULONG j;
3914 BOOL add = TRUE;
3915 if (OldAcl)
3917 for (j = 0; ; j++)
3919 const ACE_HEADER *existing_ace_header;
3920 status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
3921 if (status != STATUS_SUCCESS)
3922 break;
3923 if (pEntries[i].grfAccessMode == SET_ACCESS &&
3924 existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3925 EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
3927 add = FALSE;
3928 break;
3932 if (add)
3933 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
3934 pEntries[i].grfInheritance,
3935 pEntries[i].grfAccessPermissions,
3936 ppsid[i]);
3937 break;
3939 case DENY_ACCESS:
3940 status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
3941 pEntries[i].grfInheritance,
3942 pEntries[i].grfAccessPermissions,
3943 ppsid[i]);
3944 break;
3945 case SET_AUDIT_SUCCESS:
3946 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3947 pEntries[i].grfInheritance,
3948 pEntries[i].grfAccessPermissions,
3949 ppsid[i], TRUE, FALSE);
3950 break;
3951 case SET_AUDIT_FAILURE:
3952 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
3953 pEntries[i].grfInheritance,
3954 pEntries[i].grfAccessPermissions,
3955 ppsid[i], FALSE, TRUE);
3956 break;
3957 default:
3958 FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
3962 if (OldAcl)
3964 for (i = 0; ; i++)
3966 BOOL add = TRUE;
3967 ULONG j;
3968 const ACE_HEADER *old_ace_header;
3969 status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
3970 if (status != STATUS_SUCCESS) break;
3971 for (j = 0; j < count; j++)
3973 if (pEntries[j].grfAccessMode == SET_ACCESS &&
3974 old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
3975 EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3977 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
3978 add = FALSE;
3979 break;
3981 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
3983 switch (old_ace_header->AceType)
3985 case ACCESS_ALLOWED_ACE_TYPE:
3986 if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
3987 add = FALSE;
3988 break;
3989 case ACCESS_DENIED_ACE_TYPE:
3990 if (EqualSid(ppsid[j], &((ACCESS_DENIED_ACE *)old_ace_header)->SidStart))
3991 add = FALSE;
3992 break;
3993 case SYSTEM_AUDIT_ACE_TYPE:
3994 if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
3995 add = FALSE;
3996 break;
3997 case SYSTEM_ALARM_ACE_TYPE:
3998 if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
3999 add = FALSE;
4000 break;
4001 default:
4002 FIXME("unhandled ace type %d\n", old_ace_header->AceType);
4005 if (!add)
4006 break;
4009 if (add)
4010 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
4011 if (status != STATUS_SUCCESS)
4013 WARN("RtlAddAce failed with error 0x%08x\n", status);
4014 ret = RtlNtStatusToDosError(status);
4015 break;
4020 exit:
4021 heap_free(ppsid);
4022 return ret;
4025 /******************************************************************************
4026 * SetNamedSecurityInfoA [ADVAPI32.@]
4028 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
4029 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
4030 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
4032 LPWSTR wstr;
4033 DWORD r;
4035 TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
4036 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
4038 wstr = SERV_dup(pObjectName);
4039 r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
4040 psidGroup, pDacl, pSacl );
4042 heap_free( wstr );
4044 return r;
4047 BOOL WINAPI SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation,
4048 PSECURITY_DESCRIPTOR ModificationDescriptor,
4049 PSECURITY_DESCRIPTOR* ObjectsSecurityDescriptor,
4050 PGENERIC_MAPPING GenericMapping,
4051 HANDLE Token )
4053 FIXME("0x%08x %p %p %p %p - stub\n", SecurityInformation, ModificationDescriptor,
4054 ObjectsSecurityDescriptor, GenericMapping, Token);
4056 return TRUE;
4059 BOOL WINAPI AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
4061 return RtlAreAllAccessesGranted( GrantedAccess, DesiredAccess );
4064 /******************************************************************************
4065 * AreAnyAccessesGranted [ADVAPI32.@]
4067 * Determines whether or not any of a set of specified access permissions have
4068 * been granted or not.
4070 * PARAMS
4071 * GrantedAccess [I] The permissions that have been granted.
4072 * DesiredAccess [I] The permissions that you want to have.
4074 * RETURNS
4075 * Nonzero if any of the permissions have been granted, zero if none of the
4076 * permissions have been granted.
4079 BOOL WINAPI AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess )
4081 return RtlAreAnyAccessesGranted( GrantedAccess, DesiredAccess );
4084 /******************************************************************************
4085 * SetNamedSecurityInfoW [ADVAPI32.@]
4087 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
4088 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
4089 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
4091 DWORD access = 0;
4092 HANDLE handle;
4093 DWORD err;
4095 TRACE( "%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
4096 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
4098 if (!pObjectName) return ERROR_INVALID_PARAMETER;
4100 if (SecurityInfo & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION))
4101 access |= WRITE_OWNER;
4102 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4103 access |= WRITE_DAC;
4104 if (SecurityInfo & SACL_SECURITY_INFORMATION)
4105 access |= ACCESS_SYSTEM_SECURITY;
4107 switch (ObjectType)
4109 case SE_SERVICE:
4110 if (!(err = get_security_service( pObjectName, access, &handle )))
4112 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4113 CloseServiceHandle( handle );
4115 break;
4116 case SE_REGISTRY_KEY:
4117 if (!(err = get_security_regkey( pObjectName, access, &handle )))
4119 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4120 RegCloseKey( handle );
4122 break;
4123 case SE_FILE_OBJECT:
4124 if (SecurityInfo & DACL_SECURITY_INFORMATION)
4125 access |= READ_CONTROL;
4126 if (!(err = get_security_file( pObjectName, access, &handle )))
4128 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
4129 CloseHandle( handle );
4131 break;
4132 default:
4133 FIXME( "Object type %d is not currently supported.\n", ObjectType );
4134 return ERROR_SUCCESS;
4136 return err;
4139 /******************************************************************************
4140 * GetExplicitEntriesFromAclA [ADVAPI32.@]
4142 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
4143 PEXPLICIT_ACCESSA* pListOfExplicitEntries)
4145 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
4146 return ERROR_CALL_NOT_IMPLEMENTED;
4149 /******************************************************************************
4150 * GetExplicitEntriesFromAclW [ADVAPI32.@]
4152 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
4153 PEXPLICIT_ACCESSW* pListOfExplicitEntries)
4155 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
4156 return ERROR_CALL_NOT_IMPLEMENTED;
4159 /******************************************************************************
4160 * GetAuditedPermissionsFromAclA [ADVAPI32.@]
4162 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
4163 PACCESS_MASK pFailedAuditRights)
4165 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
4166 return ERROR_CALL_NOT_IMPLEMENTED;
4170 /******************************************************************************
4171 * GetAuditedPermissionsFromAclW [ADVAPI32.@]
4173 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
4174 PACCESS_MASK pFailedAuditRights)
4176 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
4177 return ERROR_CALL_NOT_IMPLEMENTED;
4181 /******************************************************************************
4182 * ParseAclStringFlags
4184 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
4186 DWORD flags = 0;
4187 LPCWSTR szAcl = *StringAcl;
4189 while (*szAcl != '(')
4191 if (*szAcl == 'P')
4193 flags |= SE_DACL_PROTECTED;
4195 else if (*szAcl == 'A')
4197 szAcl++;
4198 if (*szAcl == 'R')
4199 flags |= SE_DACL_AUTO_INHERIT_REQ;
4200 else if (*szAcl == 'I')
4201 flags |= SE_DACL_AUTO_INHERITED;
4203 szAcl++;
4206 *StringAcl = szAcl;
4207 return flags;
4210 /******************************************************************************
4211 * ParseAceStringType
4213 static const ACEFLAG AceType[] =
4215 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
4216 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
4217 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
4218 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
4219 { SDDL_MANDATORY_LABEL,SYSTEM_MANDATORY_LABEL_ACE_TYPE },
4221 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
4222 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
4223 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
4224 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
4226 { NULL, 0 },
4229 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
4231 UINT len = 0;
4232 LPCWSTR szAcl = *StringAcl;
4233 const ACEFLAG *lpaf = AceType;
4235 while (*szAcl == ' ')
4236 szAcl++;
4238 while (lpaf->wstr &&
4239 (len = strlenW(lpaf->wstr)) &&
4240 strncmpW(lpaf->wstr, szAcl, len))
4241 lpaf++;
4243 if (!lpaf->wstr)
4244 return 0;
4246 *StringAcl = szAcl + len;
4247 return lpaf->value;
4251 /******************************************************************************
4252 * ParseAceStringFlags
4254 static const ACEFLAG AceFlags[] =
4256 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
4257 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
4258 { SDDL_INHERITED, INHERITED_ACE },
4259 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
4260 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
4261 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
4262 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
4263 { NULL, 0 },
4266 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
4268 UINT len = 0;
4269 BYTE flags = 0;
4270 LPCWSTR szAcl = *StringAcl;
4272 while (*szAcl == ' ')
4273 szAcl++;
4275 while (*szAcl != ';')
4277 const ACEFLAG *lpaf = AceFlags;
4279 while (lpaf->wstr &&
4280 (len = strlenW(lpaf->wstr)) &&
4281 strncmpW(lpaf->wstr, szAcl, len))
4282 lpaf++;
4284 if (!lpaf->wstr)
4285 return 0;
4287 flags |= lpaf->value;
4288 szAcl += len;
4291 *StringAcl = szAcl;
4292 return flags;
4296 /******************************************************************************
4297 * ParseAceStringRights
4299 static const ACEFLAG AceRights[] =
4301 { SDDL_GENERIC_ALL, GENERIC_ALL },
4302 { SDDL_GENERIC_READ, GENERIC_READ },
4303 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
4304 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
4306 { SDDL_READ_CONTROL, READ_CONTROL },
4307 { SDDL_STANDARD_DELETE, DELETE },
4308 { SDDL_WRITE_DAC, WRITE_DAC },
4309 { SDDL_WRITE_OWNER, WRITE_OWNER },
4311 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
4312 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
4313 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
4314 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
4315 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
4316 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
4317 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
4318 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
4319 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
4321 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
4322 { SDDL_FILE_READ, FILE_GENERIC_READ },
4323 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
4324 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
4326 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
4327 { SDDL_KEY_READ, KEY_READ },
4328 { SDDL_KEY_WRITE, KEY_WRITE },
4329 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
4331 { SDDL_NO_READ_UP, SYSTEM_MANDATORY_LABEL_NO_READ_UP },
4332 { SDDL_NO_WRITE_UP, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP },
4333 { SDDL_NO_EXECUTE_UP, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP },
4334 { NULL, 0 },
4337 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
4339 UINT len = 0;
4340 DWORD rights = 0;
4341 LPCWSTR szAcl = *StringAcl;
4343 while (*szAcl == ' ')
4344 szAcl++;
4346 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
4348 LPCWSTR p = szAcl;
4350 while (*p && *p != ';')
4351 p++;
4353 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
4355 rights = strtoulW(szAcl, NULL, 16);
4356 szAcl = p;
4358 else
4359 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
4361 else
4363 while (*szAcl != ';')
4365 const ACEFLAG *lpaf = AceRights;
4367 while (lpaf->wstr &&
4368 (len = strlenW(lpaf->wstr)) &&
4369 strncmpW(lpaf->wstr, szAcl, len))
4371 lpaf++;
4374 if (!lpaf->wstr)
4375 return 0;
4377 rights |= lpaf->value;
4378 szAcl += len;
4382 *StringAcl = szAcl;
4383 return rights;
4387 /******************************************************************************
4388 * ParseStringAclToAcl
4390 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
4392 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
4393 PACL pAcl, LPDWORD cBytes)
4395 DWORD val;
4396 DWORD sidlen;
4397 DWORD length = sizeof(ACL);
4398 DWORD acesize = 0;
4399 DWORD acecount = 0;
4400 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
4401 DWORD error = ERROR_INVALID_ACL;
4403 TRACE("%s\n", debugstr_w(StringAcl));
4405 if (!StringAcl)
4406 return FALSE;
4408 if (pAcl) /* pAce is only useful if we're setting values */
4409 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
4411 /* Parse ACL flags */
4412 *lpdwFlags = ParseAclStringFlags(&StringAcl);
4414 /* Parse ACE */
4415 while (*StringAcl == '(')
4417 StringAcl++;
4419 /* Parse ACE type */
4420 val = ParseAceStringType(&StringAcl);
4421 if (pAce)
4422 pAce->Header.AceType = (BYTE) val;
4423 if (*StringAcl != ';')
4425 error = RPC_S_INVALID_STRING_UUID;
4426 goto lerr;
4428 StringAcl++;
4430 /* Parse ACE flags */
4431 val = ParseAceStringFlags(&StringAcl);
4432 if (pAce)
4433 pAce->Header.AceFlags = (BYTE) val;
4434 if (*StringAcl != ';')
4435 goto lerr;
4436 StringAcl++;
4438 /* Parse ACE rights */
4439 val = ParseAceStringRights(&StringAcl);
4440 if (pAce)
4441 pAce->Mask = val;
4442 if (*StringAcl != ';')
4443 goto lerr;
4444 StringAcl++;
4446 /* Parse ACE object guid */
4447 while (*StringAcl == ' ')
4448 StringAcl++;
4449 if (*StringAcl != ';')
4451 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4452 goto lerr;
4454 StringAcl++;
4456 /* Parse ACE inherit object guid */
4457 while (*StringAcl == ' ')
4458 StringAcl++;
4459 if (*StringAcl != ';')
4461 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
4462 goto lerr;
4464 StringAcl++;
4466 /* Parse ACE account sid */
4467 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
4469 while (*StringAcl && *StringAcl != ')')
4470 StringAcl++;
4473 if (*StringAcl != ')')
4474 goto lerr;
4475 StringAcl++;
4477 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
4478 length += acesize;
4479 if (pAce)
4481 pAce->Header.AceSize = acesize;
4482 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
4484 acecount++;
4487 *cBytes = length;
4489 if (length > 0xffff)
4491 ERR("ACL too large\n");
4492 goto lerr;
4495 if (pAcl)
4497 pAcl->AclRevision = ACL_REVISION;
4498 pAcl->Sbz1 = 0;
4499 pAcl->AclSize = length;
4500 pAcl->AceCount = acecount++;
4501 pAcl->Sbz2 = 0;
4503 return TRUE;
4505 lerr:
4506 SetLastError(error);
4507 WARN("Invalid ACE string format\n");
4508 return FALSE;
4512 /******************************************************************************
4513 * ParseStringSecurityDescriptorToSecurityDescriptor
4515 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
4516 LPCWSTR StringSecurityDescriptor,
4517 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
4518 LPDWORD cBytes)
4520 BOOL bret = FALSE;
4521 WCHAR toktype;
4522 WCHAR *tok;
4523 LPCWSTR lptoken;
4524 LPBYTE lpNext = NULL;
4525 DWORD len;
4527 *cBytes = sizeof(SECURITY_DESCRIPTOR);
4529 tok = heap_alloc( (lstrlenW(StringSecurityDescriptor) + 1) * sizeof(WCHAR));
4531 if (SecurityDescriptor)
4532 lpNext = (LPBYTE)(SecurityDescriptor + 1);
4534 while (*StringSecurityDescriptor == ' ')
4535 StringSecurityDescriptor++;
4537 while (*StringSecurityDescriptor)
4539 toktype = *StringSecurityDescriptor;
4541 /* Expect char identifier followed by ':' */
4542 StringSecurityDescriptor++;
4543 if (*StringSecurityDescriptor != ':')
4545 SetLastError(ERROR_INVALID_PARAMETER);
4546 goto lend;
4548 StringSecurityDescriptor++;
4550 /* Extract token */
4551 lptoken = StringSecurityDescriptor;
4552 while (*lptoken && *lptoken != ':')
4553 lptoken++;
4555 if (*lptoken)
4556 lptoken--;
4558 len = lptoken - StringSecurityDescriptor;
4559 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
4560 tok[len] = 0;
4562 switch (toktype)
4564 case 'O':
4566 DWORD bytes;
4568 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4569 goto lend;
4571 if (SecurityDescriptor)
4573 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
4574 lpNext += bytes; /* Advance to next token */
4577 *cBytes += bytes;
4579 break;
4582 case 'G':
4584 DWORD bytes;
4586 if (!ParseStringSidToSid(tok, lpNext, &bytes))
4587 goto lend;
4589 if (SecurityDescriptor)
4591 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
4592 lpNext += bytes; /* Advance to next token */
4595 *cBytes += bytes;
4597 break;
4600 case 'D':
4602 DWORD flags;
4603 DWORD bytes;
4605 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4606 goto lend;
4608 if (SecurityDescriptor)
4610 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
4611 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
4612 lpNext += bytes; /* Advance to next token */
4615 *cBytes += bytes;
4617 break;
4620 case 'S':
4622 DWORD flags;
4623 DWORD bytes;
4625 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
4626 goto lend;
4628 if (SecurityDescriptor)
4630 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
4631 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
4632 lpNext += bytes; /* Advance to next token */
4635 *cBytes += bytes;
4637 break;
4640 default:
4641 FIXME("Unknown token\n");
4642 SetLastError(ERROR_INVALID_PARAMETER);
4643 goto lend;
4646 StringSecurityDescriptor = lptoken;
4649 bret = TRUE;
4651 lend:
4652 heap_free(tok);
4653 return bret;
4656 /******************************************************************************
4657 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
4659 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
4660 LPCSTR StringSecurityDescriptor,
4661 DWORD StringSDRevision,
4662 PSECURITY_DESCRIPTOR* SecurityDescriptor,
4663 PULONG SecurityDescriptorSize)
4665 BOOL ret;
4666 LPWSTR StringSecurityDescriptorW;
4668 if(!StringSecurityDescriptor)
4669 return FALSE;
4671 StringSecurityDescriptorW = SERV_dup(StringSecurityDescriptor);
4672 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
4673 StringSDRevision, SecurityDescriptor,
4674 SecurityDescriptorSize);
4675 heap_free(StringSecurityDescriptorW);
4677 return ret;
4680 /******************************************************************************
4681 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
4683 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
4684 LPCWSTR StringSecurityDescriptor,
4685 DWORD StringSDRevision,
4686 PSECURITY_DESCRIPTOR* SecurityDescriptor,
4687 PULONG SecurityDescriptorSize)
4689 DWORD cBytes;
4690 SECURITY_DESCRIPTOR* psd;
4691 BOOL bret = FALSE;
4693 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
4695 if (GetVersion() & 0x80000000)
4697 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4698 goto lend;
4700 else if (!StringSecurityDescriptor || !SecurityDescriptor)
4702 SetLastError(ERROR_INVALID_PARAMETER);
4703 goto lend;
4705 else if (StringSDRevision != SID_REVISION)
4707 SetLastError(ERROR_UNKNOWN_REVISION);
4708 goto lend;
4711 /* Compute security descriptor length */
4712 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4713 NULL, &cBytes))
4714 goto lend;
4716 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
4717 if (!psd) goto lend;
4719 psd->Revision = SID_REVISION;
4720 psd->Control |= SE_SELF_RELATIVE;
4722 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
4723 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
4725 LocalFree(psd);
4726 goto lend;
4729 if (SecurityDescriptorSize)
4730 *SecurityDescriptorSize = cBytes;
4732 bret = TRUE;
4734 lend:
4735 TRACE(" ret=%d\n", bret);
4736 return bret;
4739 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
4741 if (cch == -1)
4742 cch = strlenW(string);
4744 if (plen)
4745 *plen += cch;
4747 if (pwptr)
4749 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
4750 *pwptr += cch;
4754 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
4756 DWORD i;
4757 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
4758 WCHAR subauthfmt[] = { '-','%','u',0 };
4759 WCHAR buf[26];
4760 SID *pisid = psid;
4762 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
4764 SetLastError(ERROR_INVALID_SID);
4765 return FALSE;
4768 if (pisid->IdentifierAuthority.Value[0] ||
4769 pisid->IdentifierAuthority.Value[1])
4771 FIXME("not matching MS' bugs\n");
4772 SetLastError(ERROR_INVALID_SID);
4773 return FALSE;
4776 sprintfW( buf, fmt, pisid->Revision,
4777 MAKELONG(
4778 MAKEWORD( pisid->IdentifierAuthority.Value[5],
4779 pisid->IdentifierAuthority.Value[4] ),
4780 MAKEWORD( pisid->IdentifierAuthority.Value[3],
4781 pisid->IdentifierAuthority.Value[2] )
4782 ) );
4783 DumpString(buf, -1, pwptr, plen);
4785 for( i=0; i<pisid->SubAuthorityCount; i++ )
4787 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
4788 DumpString(buf, -1, pwptr, plen);
4790 return TRUE;
4793 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
4795 size_t i;
4796 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
4798 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
4800 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
4801 return TRUE;
4805 return DumpSidNumeric(psid, pwptr, plen);
4808 static const LPCWSTR AceRightBitNames[32] = {
4809 SDDL_CREATE_CHILD, /* 0 */
4810 SDDL_DELETE_CHILD,
4811 SDDL_LIST_CHILDREN,
4812 SDDL_SELF_WRITE,
4813 SDDL_READ_PROPERTY, /* 4 */
4814 SDDL_WRITE_PROPERTY,
4815 SDDL_DELETE_TREE,
4816 SDDL_LIST_OBJECT,
4817 SDDL_CONTROL_ACCESS, /* 8 */
4818 NULL,
4819 NULL,
4820 NULL,
4821 NULL, /* 12 */
4822 NULL,
4823 NULL,
4824 NULL,
4825 SDDL_STANDARD_DELETE, /* 16 */
4826 SDDL_READ_CONTROL,
4827 SDDL_WRITE_DAC,
4828 SDDL_WRITE_OWNER,
4829 NULL, /* 20 */
4830 NULL,
4831 NULL,
4832 NULL,
4833 NULL, /* 24 */
4834 NULL,
4835 NULL,
4836 NULL,
4837 SDDL_GENERIC_ALL, /* 28 */
4838 SDDL_GENERIC_EXECUTE,
4839 SDDL_GENERIC_WRITE,
4840 SDDL_GENERIC_READ
4843 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
4845 static const WCHAR fmtW[] = {'0','x','%','x',0};
4846 WCHAR buf[15];
4847 size_t i;
4849 if (mask == 0)
4850 return;
4852 /* first check if the right have name */
4853 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
4855 if (AceRights[i].wstr == NULL)
4856 break;
4857 if (mask == AceRights[i].value)
4859 DumpString(AceRights[i].wstr, -1, pwptr, plen);
4860 return;
4864 /* then check if it can be built from bit names */
4865 for (i = 0; i < 32; i++)
4867 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
4869 /* can't be built from bit names */
4870 sprintfW(buf, fmtW, mask);
4871 DumpString(buf, -1, pwptr, plen);
4872 return;
4876 /* build from bit names */
4877 for (i = 0; i < 32; i++)
4878 if (mask & (1 << i))
4879 DumpString(AceRightBitNames[i], -1, pwptr, plen);
4882 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
4884 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
4885 static const WCHAR openbr = '(';
4886 static const WCHAR closebr = ')';
4887 static const WCHAR semicolon = ';';
4889 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
4891 SetLastError(ERROR_INVALID_ACL);
4892 return FALSE;
4895 piace = pace;
4896 DumpString(&openbr, 1, pwptr, plen);
4897 switch (piace->Header.AceType)
4899 case ACCESS_ALLOWED_ACE_TYPE:
4900 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
4901 break;
4902 case ACCESS_DENIED_ACE_TYPE:
4903 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
4904 break;
4905 case SYSTEM_AUDIT_ACE_TYPE:
4906 DumpString(SDDL_AUDIT, -1, pwptr, plen);
4907 break;
4908 case SYSTEM_ALARM_ACE_TYPE:
4909 DumpString(SDDL_ALARM, -1, pwptr, plen);
4910 break;
4912 DumpString(&semicolon, 1, pwptr, plen);
4914 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
4915 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
4916 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
4917 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
4918 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
4919 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
4920 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
4921 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
4922 if (piace->Header.AceFlags & INHERITED_ACE)
4923 DumpString(SDDL_INHERITED, -1, pwptr, plen);
4924 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
4925 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
4926 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
4927 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
4928 DumpString(&semicolon, 1, pwptr, plen);
4929 DumpRights(piace->Mask, pwptr, plen);
4930 DumpString(&semicolon, 1, pwptr, plen);
4931 /* objects not supported */
4932 DumpString(&semicolon, 1, pwptr, plen);
4933 /* objects not supported */
4934 DumpString(&semicolon, 1, pwptr, plen);
4935 if (!DumpSid(&piace->SidStart, pwptr, plen))
4936 return FALSE;
4937 DumpString(&closebr, 1, pwptr, plen);
4938 return TRUE;
4941 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
4943 WORD count;
4944 UINT i;
4946 if (protected)
4947 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
4948 if (autoInheritReq)
4949 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
4950 if (autoInherited)
4951 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
4953 if (pacl == NULL)
4954 return TRUE;
4956 if (!IsValidAcl(pacl))
4957 return FALSE;
4959 count = pacl->AceCount;
4960 for (i = 0; i < count; i++)
4962 LPVOID ace;
4963 if (!GetAce(pacl, i, &ace))
4964 return FALSE;
4965 if (!DumpAce(ace, pwptr, plen))
4966 return FALSE;
4969 return TRUE;
4972 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4974 static const WCHAR prefix[] = {'O',':',0};
4975 BOOL bDefaulted;
4976 PSID psid;
4978 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
4979 return FALSE;
4981 if (psid == NULL)
4982 return TRUE;
4984 DumpString(prefix, -1, pwptr, plen);
4985 if (!DumpSid(psid, pwptr, plen))
4986 return FALSE;
4987 return TRUE;
4990 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
4992 static const WCHAR prefix[] = {'G',':',0};
4993 BOOL bDefaulted;
4994 PSID psid;
4996 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
4997 return FALSE;
4999 if (psid == NULL)
5000 return TRUE;
5002 DumpString(prefix, -1, pwptr, plen);
5003 if (!DumpSid(psid, pwptr, plen))
5004 return FALSE;
5005 return TRUE;
5008 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
5010 static const WCHAR dacl[] = {'D',':',0};
5011 SECURITY_DESCRIPTOR_CONTROL control;
5012 BOOL present, defaulted;
5013 DWORD revision;
5014 PACL pacl;
5016 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
5017 return FALSE;
5019 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
5020 return FALSE;
5022 if (!present)
5023 return TRUE;
5025 DumpString(dacl, 2, pwptr, plen);
5026 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
5027 return FALSE;
5028 return TRUE;
5031 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
5033 static const WCHAR sacl[] = {'S',':',0};
5034 SECURITY_DESCRIPTOR_CONTROL control;
5035 BOOL present, defaulted;
5036 DWORD revision;
5037 PACL pacl;
5039 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
5040 return FALSE;
5042 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
5043 return FALSE;
5045 if (!present)
5046 return TRUE;
5048 DumpString(sacl, 2, pwptr, plen);
5049 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
5050 return FALSE;
5051 return TRUE;
5054 /******************************************************************************
5055 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
5057 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
5059 ULONG len;
5060 WCHAR *wptr, *wstr;
5062 if (SDRevision != SDDL_REVISION_1)
5064 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
5065 SetLastError(ERROR_UNKNOWN_REVISION);
5066 return FALSE;
5069 len = 0;
5070 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
5071 if (!DumpOwner(SecurityDescriptor, NULL, &len))
5072 return FALSE;
5073 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
5074 if (!DumpGroup(SecurityDescriptor, NULL, &len))
5075 return FALSE;
5076 if (RequestedInformation & DACL_SECURITY_INFORMATION)
5077 if (!DumpDacl(SecurityDescriptor, NULL, &len))
5078 return FALSE;
5079 if (RequestedInformation & SACL_SECURITY_INFORMATION)
5080 if (!DumpSacl(SecurityDescriptor, NULL, &len))
5081 return FALSE;
5083 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
5084 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
5085 if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) {
5086 LocalFree (wstr);
5087 return FALSE;
5089 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
5090 if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) {
5091 LocalFree (wstr);
5092 return FALSE;
5094 if (RequestedInformation & DACL_SECURITY_INFORMATION)
5095 if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) {
5096 LocalFree (wstr);
5097 return FALSE;
5099 if (RequestedInformation & SACL_SECURITY_INFORMATION)
5100 if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) {
5101 LocalFree (wstr);
5102 return FALSE;
5104 *wptr = 0;
5106 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
5107 *OutputString = wstr;
5108 if (OutputLen)
5109 *OutputLen = strlenW(*OutputString)+1;
5110 return TRUE;
5113 /******************************************************************************
5114 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
5116 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
5118 LPWSTR wstr;
5119 ULONG len;
5120 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
5122 int lenA;
5124 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
5125 *OutputString = heap_alloc(lenA);
5126 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
5127 LocalFree(wstr);
5129 if (OutputLen != NULL)
5130 *OutputLen = lenA;
5131 return TRUE;
5133 else
5135 *OutputString = NULL;
5136 if (OutputLen)
5137 *OutputLen = 0;
5138 return FALSE;
5142 /******************************************************************************
5143 * ConvertStringSidToSidW [ADVAPI32.@]
5145 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
5147 BOOL bret = FALSE;
5148 DWORD cBytes;
5150 TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
5151 if (GetVersion() & 0x80000000)
5152 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5153 else if (!StringSid || !Sid)
5154 SetLastError(ERROR_INVALID_PARAMETER);
5155 else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
5157 PSID pSid = *Sid = LocalAlloc(0, cBytes);
5159 bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
5160 if (!bret)
5161 LocalFree(*Sid);
5163 return bret;
5166 /******************************************************************************
5167 * ConvertStringSidToSidA [ADVAPI32.@]
5169 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
5171 BOOL bret = FALSE;
5173 TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
5174 if (GetVersion() & 0x80000000)
5175 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5176 else if (!StringSid || !Sid)
5177 SetLastError(ERROR_INVALID_PARAMETER);
5178 else
5180 WCHAR *wStringSid = SERV_dup(StringSid);
5181 bret = ConvertStringSidToSidW(wStringSid, Sid);
5182 heap_free(wStringSid);
5184 return bret;
5187 /******************************************************************************
5188 * ConvertSidToStringSidW [ADVAPI32.@]
5190 * format of SID string is:
5191 * S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
5192 * where
5193 * <rev> is the revision of the SID encoded as decimal
5194 * <auth> is the identifier authority encoded as hex
5195 * <subauthN> is the subauthority id encoded as decimal
5197 BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
5199 DWORD len = 0;
5200 LPWSTR wstr, wptr;
5202 TRACE("%p %p\n", pSid, pstr );
5204 len = 0;
5205 if (!DumpSidNumeric(pSid, NULL, &len))
5206 return FALSE;
5207 wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
5208 DumpSidNumeric(pSid, &wptr, NULL);
5209 *wptr = 0;
5211 *pstr = wstr;
5212 return TRUE;
5215 /******************************************************************************
5216 * ConvertSidToStringSidA [ADVAPI32.@]
5218 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
5220 LPWSTR wstr = NULL;
5221 LPSTR str;
5222 UINT len;
5224 TRACE("%p %p\n", pSid, pstr );
5226 if( !ConvertSidToStringSidW( pSid, &wstr ) )
5227 return FALSE;
5229 len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
5230 str = LocalAlloc( 0, len );
5231 WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
5232 LocalFree( wstr );
5234 *pstr = str;
5236 return TRUE;
5239 BOOL WINAPI ConvertToAutoInheritPrivateObjectSecurity(
5240 PSECURITY_DESCRIPTOR pdesc,
5241 PSECURITY_DESCRIPTOR cdesc,
5242 PSECURITY_DESCRIPTOR* ndesc,
5243 GUID* objtype,
5244 BOOL isdir,
5245 PGENERIC_MAPPING genmap )
5247 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
5249 return FALSE;
5252 BOOL WINAPI CreatePrivateObjectSecurity(
5253 PSECURITY_DESCRIPTOR ParentDescriptor,
5254 PSECURITY_DESCRIPTOR CreatorDescriptor,
5255 PSECURITY_DESCRIPTOR* NewDescriptor,
5256 BOOL IsDirectoryObject,
5257 HANDLE Token,
5258 PGENERIC_MAPPING GenericMapping )
5260 SECURITY_DESCRIPTOR_RELATIVE *relative;
5261 DWORD needed, offset;
5262 BYTE *buffer;
5264 FIXME("%p %p %p %d %p %p - returns fake SECURITY_DESCRIPTOR\n", ParentDescriptor,
5265 CreatorDescriptor, NewDescriptor, IsDirectoryObject, Token, GenericMapping);
5267 needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5268 needed += sizeof(sidWorld);
5269 needed += sizeof(sidWorld);
5270 needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5271 needed += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5273 if (!(buffer = heap_alloc( needed ))) return FALSE;
5274 relative = (SECURITY_DESCRIPTOR_RELATIVE *)buffer;
5275 if (!InitializeSecurityDescriptor( relative, SECURITY_DESCRIPTOR_REVISION ))
5277 heap_free( buffer );
5278 return FALSE;
5280 relative->Control |= SE_SELF_RELATIVE;
5281 offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
5283 memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5284 relative->Owner = offset;
5285 offset += sizeof(sidWorld);
5287 memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) );
5288 relative->Group = offset;
5289 offset += sizeof(sidWorld);
5291 GetWorldAccessACL( (ACL *)(buffer + offset) );
5292 relative->Dacl = offset;
5293 offset += WINE_SIZE_OF_WORLD_ACCESS_ACL;
5295 GetWorldAccessACL( (ACL *)(buffer + offset) );
5296 relative->Sacl = offset;
5298 *NewDescriptor = relative;
5299 return TRUE;
5302 BOOL WINAPI CreatePrivateObjectSecurityWithMultipleInheritance(
5303 PSECURITY_DESCRIPTOR parent, PSECURITY_DESCRIPTOR creator, PSECURITY_DESCRIPTOR *out,
5304 GUID **types, ULONG count, BOOL is_container, ULONG flags, HANDLE token, PGENERIC_MAPPING mapping)
5306 FIXME(": semi-stub\n");
5307 return CreatePrivateObjectSecurity(parent, creator, out, is_container, token, mapping);
5310 BOOL WINAPI DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR* ObjectDescriptor )
5312 FIXME("%p - stub\n", ObjectDescriptor);
5314 heap_free( *ObjectDescriptor );
5315 return TRUE;
5318 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserA(
5319 HANDLE hToken,
5320 LPCSTR lpApplicationName,
5321 LPSTR lpCommandLine,
5322 LPSECURITY_ATTRIBUTES lpProcessAttributes,
5323 LPSECURITY_ATTRIBUTES lpThreadAttributes,
5324 BOOL bInheritHandles,
5325 DWORD dwCreationFlags,
5326 LPVOID lpEnvironment,
5327 LPCSTR lpCurrentDirectory,
5328 LPSTARTUPINFOA lpStartupInfo,
5329 LPPROCESS_INFORMATION lpProcessInformation )
5331 BOOL ret;
5332 WCHAR *appW, *cmdlnW, *cwdW;
5333 STARTUPINFOW sinfo;
5335 TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_a(lpApplicationName),
5336 debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
5337 dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5339 appW = SERV_dup(lpApplicationName);
5340 cmdlnW = SERV_dup(lpCommandLine);
5341 cwdW = SERV_dup(lpCurrentDirectory);
5342 sinfo.cb = sizeof(sinfo);
5343 sinfo.lpReserved = SERV_dup(lpStartupInfo->lpReserved);
5344 sinfo.lpDesktop = SERV_dup(lpStartupInfo->lpDesktop);
5345 sinfo.lpTitle = SERV_dup(lpStartupInfo->lpTitle);
5346 sinfo.dwX = lpStartupInfo->dwX;
5347 sinfo.dwY = lpStartupInfo->dwY;
5348 sinfo.dwXSize = lpStartupInfo->dwXSize;
5349 sinfo.dwYSize = lpStartupInfo->dwYSize;
5350 sinfo.dwXCountChars = lpStartupInfo->dwXCountChars;
5351 sinfo.dwYCountChars = lpStartupInfo->dwYCountChars;
5352 sinfo.dwFillAttribute = lpStartupInfo->dwFillAttribute;
5353 sinfo.dwFlags = lpStartupInfo->dwFlags;
5354 sinfo.wShowWindow = lpStartupInfo->wShowWindow;
5355 sinfo.cbReserved2 = lpStartupInfo->cbReserved2;
5356 sinfo.lpReserved2 = lpStartupInfo->lpReserved2;
5357 sinfo.hStdInput = lpStartupInfo->hStdInput;
5358 sinfo.hStdOutput = lpStartupInfo->hStdOutput;
5359 sinfo.hStdError = lpStartupInfo->hStdError;
5360 ret = CreateProcessAsUserW(hToken, appW, cmdlnW, lpProcessAttributes,
5361 lpThreadAttributes, bInheritHandles, dwCreationFlags,
5362 lpEnvironment, cwdW, &sinfo, lpProcessInformation);
5363 heap_free(appW);
5364 heap_free(cmdlnW);
5365 heap_free(cwdW);
5366 heap_free(sinfo.lpReserved);
5367 heap_free(sinfo.lpDesktop);
5368 heap_free(sinfo.lpTitle);
5370 return ret;
5373 BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserW(
5374 HANDLE hToken,
5375 LPCWSTR lpApplicationName,
5376 LPWSTR lpCommandLine,
5377 LPSECURITY_ATTRIBUTES lpProcessAttributes,
5378 LPSECURITY_ATTRIBUTES lpThreadAttributes,
5379 BOOL bInheritHandles,
5380 DWORD dwCreationFlags,
5381 LPVOID lpEnvironment,
5382 LPCWSTR lpCurrentDirectory,
5383 LPSTARTUPINFOW lpStartupInfo,
5384 LPPROCESS_INFORMATION lpProcessInformation )
5386 FIXME("%p %s %s %p %p %d 0x%08x %p %s %p %p - semi-stub\n", hToken,
5387 debugstr_w(lpApplicationName), debugstr_w(lpCommandLine), lpProcessAttributes,
5388 lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
5389 debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
5391 /* We should create the process with a suspended main thread */
5392 if (!CreateProcessW (lpApplicationName,
5393 lpCommandLine,
5394 lpProcessAttributes,
5395 lpThreadAttributes,
5396 bInheritHandles,
5397 dwCreationFlags, /* CREATE_SUSPENDED */
5398 lpEnvironment,
5399 lpCurrentDirectory,
5400 lpStartupInfo,
5401 lpProcessInformation))
5403 return FALSE;
5406 return TRUE;
5409 /******************************************************************************
5410 * CreateProcessWithLogonW
5412 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
5413 LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
5414 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
5416 FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
5417 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
5418 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
5419 lpStartupInfo, lpProcessInformation);
5421 return FALSE;
5424 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line,
5425 DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info,
5426 PROCESS_INFORMATION *process_information )
5428 FIXME("%p 0x%08x %s %s 0x%08x %p %s %p %p - semi-stub\n", token,
5429 logon_flags, debugstr_w(application_name), debugstr_w(command_line),
5430 creation_flags, environment, debugstr_w(current_directory),
5431 startup_info, process_information);
5433 /* FIXME: check if handles should be inherited */
5434 return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment,
5435 current_directory, startup_info, process_information );
5438 /******************************************************************************
5439 * DuplicateTokenEx [ADVAPI32.@]
5441 BOOL WINAPI DuplicateTokenEx(
5442 HANDLE ExistingTokenHandle, DWORD dwDesiredAccess,
5443 LPSECURITY_ATTRIBUTES lpTokenAttributes,
5444 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5445 TOKEN_TYPE TokenType,
5446 PHANDLE DuplicateTokenHandle )
5448 OBJECT_ATTRIBUTES ObjectAttributes;
5450 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
5451 ImpersonationLevel, TokenType, DuplicateTokenHandle);
5453 InitializeObjectAttributes(
5454 &ObjectAttributes,
5455 NULL,
5456 (lpTokenAttributes && lpTokenAttributes->bInheritHandle) ? OBJ_INHERIT : 0,
5457 NULL,
5458 lpTokenAttributes ? lpTokenAttributes->lpSecurityDescriptor : NULL );
5460 return set_ntstatus( NtDuplicateToken( ExistingTokenHandle,
5461 dwDesiredAccess,
5462 &ObjectAttributes,
5463 ImpersonationLevel,
5464 TokenType,
5465 DuplicateTokenHandle ) );
5468 BOOL WINAPI DuplicateToken(
5469 HANDLE ExistingTokenHandle,
5470 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
5471 PHANDLE DuplicateTokenHandle )
5473 return DuplicateTokenEx( ExistingTokenHandle, TOKEN_IMPERSONATE | TOKEN_QUERY,
5474 NULL, ImpersonationLevel, TokenImpersonation,
5475 DuplicateTokenHandle );
5478 /******************************************************************************
5479 * ComputeStringSidSize
5481 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
5483 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
5485 int ctok = 0;
5486 while (*StringSid)
5488 if (*StringSid == '-')
5489 ctok++;
5490 StringSid++;
5493 if (ctok >= 3)
5494 return GetSidLengthRequired(ctok - 2);
5496 else /* String constant format - Only available in winxp and above */
5498 unsigned int i;
5500 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5501 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5502 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
5504 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
5505 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
5507 MAX_SID local;
5508 ADVAPI_GetComputerSid(&local);
5509 return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1);
5514 return GetSidLengthRequired(0);
5517 /******************************************************************************
5518 * ParseStringSidToSid
5520 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
5522 BOOL bret = FALSE;
5523 SID* pisid=pSid;
5525 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
5526 if (!StringSid)
5528 SetLastError(ERROR_INVALID_PARAMETER);
5529 TRACE("StringSid is NULL, returning FALSE\n");
5530 return FALSE;
5533 while (*StringSid == ' ')
5534 StringSid++;
5536 *cBytes = ComputeStringSidSize(StringSid);
5537 if (!pisid) /* Simply compute the size */
5539 TRACE("only size requested, returning TRUE with %d\n", *cBytes);
5540 return TRUE;
5543 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
5545 DWORD i = 0, identAuth;
5546 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
5548 StringSid += 2; /* Advance to Revision */
5549 pisid->Revision = atoiW(StringSid);
5551 if (pisid->Revision != SDDL_REVISION)
5553 TRACE("Revision %d is unknown\n", pisid->Revision);
5554 goto lend; /* ERROR_INVALID_SID */
5556 if (csubauth == 0)
5558 TRACE("SubAuthorityCount is 0\n");
5559 goto lend; /* ERROR_INVALID_SID */
5562 pisid->SubAuthorityCount = csubauth;
5564 /* Advance to identifier authority */
5565 while (*StringSid && *StringSid != '-')
5566 StringSid++;
5567 if (*StringSid == '-')
5568 StringSid++;
5570 /* MS' implementation can't handle values greater than 2^32 - 1, so
5571 * we don't either; assume most significant bytes are always 0
5573 pisid->IdentifierAuthority.Value[0] = 0;
5574 pisid->IdentifierAuthority.Value[1] = 0;
5575 identAuth = atoiW(StringSid);
5576 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
5577 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
5578 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
5579 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
5581 /* Advance to first sub authority */
5582 while (*StringSid && *StringSid != '-')
5583 StringSid++;
5584 if (*StringSid == '-')
5585 StringSid++;
5587 while (*StringSid)
5589 pisid->SubAuthority[i++] = atoiW(StringSid);
5591 while (*StringSid && *StringSid != '-')
5592 StringSid++;
5593 if (*StringSid == '-')
5594 StringSid++;
5597 if (i != pisid->SubAuthorityCount)
5598 goto lend; /* ERROR_INVALID_SID */
5600 bret = TRUE;
5602 else /* String constant format - Only available in winxp and above */
5604 unsigned int i;
5605 pisid->Revision = SDDL_REVISION;
5607 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
5608 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
5610 DWORD j;
5611 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
5612 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
5613 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
5614 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
5615 bret = TRUE;
5618 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
5619 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
5621 ADVAPI_GetComputerSid(pisid);
5622 pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid;
5623 pisid->SubAuthorityCount++;
5624 bret = TRUE;
5627 if (!bret)
5628 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
5631 lend:
5632 if (!bret)
5633 SetLastError(ERROR_INVALID_SID);
5635 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
5636 return bret;
5639 /******************************************************************************
5640 * GetNamedSecurityInfoA [ADVAPI32.@]
5642 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
5643 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
5644 PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
5645 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
5647 LPWSTR wstr;
5648 DWORD r;
5650 TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
5651 ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
5653 wstr = SERV_dup(pObjectName);
5654 r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
5655 ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
5657 heap_free( wstr );
5659 return r;
5662 /******************************************************************************
5663 * GetNamedSecurityInfoW [ADVAPI32.@]
5665 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
5666 SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
5667 PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
5669 DWORD access = 0;
5670 HANDLE handle;
5671 DWORD err;
5673 TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
5674 group, dacl, sacl, descriptor );
5676 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
5677 if (!name || !(owner||group||dacl||sacl||descriptor) ) return ERROR_INVALID_PARAMETER;
5679 /* If no descriptor, we have to check that there's a pointer for the requested information */
5680 if( !descriptor && (
5681 ((info & OWNER_SECURITY_INFORMATION) && !owner)
5682 || ((info & GROUP_SECURITY_INFORMATION) && !group)
5683 || ((info & DACL_SECURITY_INFORMATION) && !dacl)
5684 || ((info & SACL_SECURITY_INFORMATION) && !sacl) ))
5685 return ERROR_INVALID_PARAMETER;
5687 if (info & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION))
5688 access |= READ_CONTROL;
5689 if (info & SACL_SECURITY_INFORMATION)
5690 access |= ACCESS_SYSTEM_SECURITY;
5692 switch (type)
5694 case SE_SERVICE:
5695 if (!(err = get_security_service( name, access, &handle )))
5697 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5698 CloseServiceHandle( handle );
5700 break;
5701 case SE_REGISTRY_KEY:
5702 if (!(err = get_security_regkey( name, access, &handle )))
5704 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5705 RegCloseKey( handle );
5707 break;
5708 case SE_FILE_OBJECT:
5709 if (!(err = get_security_file( name, access, &handle )))
5711 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
5712 CloseHandle( handle );
5714 break;
5715 default:
5716 FIXME( "Object type %d is not currently supported.\n", type );
5717 if (owner) *owner = NULL;
5718 if (group) *group = NULL;
5719 if (dacl) *dacl = NULL;
5720 if (sacl) *sacl = NULL;
5721 if (descriptor) *descriptor = NULL;
5722 return ERROR_SUCCESS;
5724 return err;
5727 /******************************************************************************
5728 * GetNamedSecurityInfoExW [ADVAPI32.@]
5730 DWORD WINAPI GetNamedSecurityInfoExW( LPCWSTR object, SE_OBJECT_TYPE type,
5731 SECURITY_INFORMATION info, LPCWSTR provider, LPCWSTR property,
5732 PACTRL_ACCESSW* access_list, PACTRL_AUDITW* audit_list, LPWSTR* owner, LPWSTR* group )
5734 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_w(object), type, info,
5735 debugstr_w(provider), debugstr_w(property), access_list, audit_list, owner, group);
5736 return ERROR_CALL_NOT_IMPLEMENTED;
5739 /******************************************************************************
5740 * GetNamedSecurityInfoExA [ADVAPI32.@]
5742 DWORD WINAPI GetNamedSecurityInfoExA( LPCSTR object, SE_OBJECT_TYPE type,
5743 SECURITY_INFORMATION info, LPCSTR provider, LPCSTR property,
5744 PACTRL_ACCESSA* access_list, PACTRL_AUDITA* audit_list, LPSTR* owner, LPSTR* group )
5746 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_a(object), type, info,
5747 debugstr_a(provider), debugstr_a(property), access_list, audit_list, owner, group);
5748 return ERROR_CALL_NOT_IMPLEMENTED;
5751 /******************************************************************************
5752 * DecryptFileW [ADVAPI32.@]
5754 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
5756 FIXME("(%s, %08x): stub\n", debugstr_w(lpFileName), dwReserved);
5757 return TRUE;
5760 /******************************************************************************
5761 * DecryptFileA [ADVAPI32.@]
5763 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
5765 FIXME("(%s, %08x): stub\n", debugstr_a(lpFileName), dwReserved);
5766 return TRUE;
5769 /******************************************************************************
5770 * EncryptFileW [ADVAPI32.@]
5772 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
5774 FIXME("(%s): stub\n", debugstr_w(lpFileName));
5775 return TRUE;
5778 /******************************************************************************
5779 * EncryptFileA [ADVAPI32.@]
5781 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
5783 FIXME("(%s): stub\n", debugstr_a(lpFileName));
5784 return TRUE;
5787 /******************************************************************************
5788 * FileEncryptionStatusW [ADVAPI32.@]
5790 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
5792 FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
5793 if (!lpStatus)
5794 return FALSE;
5795 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5796 return TRUE;
5799 /******************************************************************************
5800 * FileEncryptionStatusA [ADVAPI32.@]
5802 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
5804 FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
5805 if (!lpStatus)
5806 return FALSE;
5807 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
5808 return TRUE;
5811 /******************************************************************************
5812 * SetSecurityInfo [ADVAPI32.@]
5814 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType,
5815 SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
5816 PSID psidGroup, PACL pDacl, PACL pSacl)
5818 SECURITY_DESCRIPTOR sd;
5819 PACL dacl = pDacl;
5820 NTSTATUS status;
5822 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
5823 return ERROR_INVALID_SECURITY_DESCR;
5825 if (SecurityInfo & OWNER_SECURITY_INFORMATION)
5826 SetSecurityDescriptorOwner(&sd, psidOwner, FALSE);
5827 if (SecurityInfo & GROUP_SECURITY_INFORMATION)
5828 SetSecurityDescriptorGroup(&sd, psidGroup, FALSE);
5829 if (SecurityInfo & DACL_SECURITY_INFORMATION)
5831 if (ObjectType == SE_FILE_OBJECT && pDacl)
5833 SECURITY_DESCRIPTOR_CONTROL control;
5834 PSECURITY_DESCRIPTOR psd;
5835 OBJECT_NAME_INFORMATION *name_info;
5836 DWORD size, rev;
5838 status = NtQuerySecurityObject(handle, SecurityInfo, NULL, 0, &size);
5839 if (status != STATUS_BUFFER_TOO_SMALL)
5840 return RtlNtStatusToDosError(status);
5842 psd = heap_alloc(size);
5843 if (!psd)
5844 return ERROR_NOT_ENOUGH_MEMORY;
5846 status = NtQuerySecurityObject(handle, SecurityInfo, psd, size, &size);
5847 if (status)
5849 heap_free(psd);
5850 return RtlNtStatusToDosError(status);
5853 status = RtlGetControlSecurityDescriptor(psd, &control, &rev);
5854 heap_free(psd);
5855 if (status)
5856 return RtlNtStatusToDosError(status);
5857 /* TODO: copy some control flags to new sd */
5859 /* inherit parent directory DACL */
5860 if (!(control & SE_DACL_PROTECTED))
5862 status = NtQueryObject(handle, ObjectNameInformation, NULL, 0, &size);
5863 if (status != STATUS_INFO_LENGTH_MISMATCH)
5864 return RtlNtStatusToDosError(status);
5866 name_info = heap_alloc(size);
5867 if (!name_info)
5868 return ERROR_NOT_ENOUGH_MEMORY;
5870 status = NtQueryObject(handle, ObjectNameInformation, name_info, size, NULL);
5871 if (status)
5873 heap_free(name_info);
5874 return RtlNtStatusToDosError(status);
5877 for (name_info->Name.Length-=2; name_info->Name.Length>0; name_info->Name.Length-=2)
5878 if (name_info->Name.Buffer[name_info->Name.Length/2-1]=='\\' ||
5879 name_info->Name.Buffer[name_info->Name.Length/2-1]=='/')
5880 break;
5881 if (name_info->Name.Length)
5883 OBJECT_ATTRIBUTES attr;
5884 IO_STATUS_BLOCK io;
5885 HANDLE parent;
5886 PSECURITY_DESCRIPTOR parent_sd;
5887 ACL *parent_dacl;
5888 DWORD err = ERROR_ACCESS_DENIED;
5890 name_info->Name.Buffer[name_info->Name.Length/2] = 0;
5892 attr.Length = sizeof(attr);
5893 attr.RootDirectory = 0;
5894 attr.Attributes = 0;
5895 attr.ObjectName = &name_info->Name;
5896 attr.SecurityDescriptor = NULL;
5897 status = NtOpenFile(&parent, READ_CONTROL|SYNCHRONIZE, &attr, &io,
5898 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5899 FILE_OPEN_FOR_BACKUP_INTENT);
5900 heap_free(name_info);
5901 if (!status)
5903 err = GetSecurityInfo(parent, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
5904 NULL, NULL, &parent_dacl, NULL, &parent_sd);
5905 CloseHandle(parent);
5908 if (!err)
5910 int i;
5912 dacl = heap_alloc_zero(pDacl->AclSize+parent_dacl->AclSize);
5913 if (!dacl)
5915 LocalFree(parent_sd);
5916 return ERROR_NOT_ENOUGH_MEMORY;
5918 memcpy(dacl, pDacl, pDacl->AclSize);
5919 dacl->AclSize = pDacl->AclSize+parent_dacl->AclSize;
5921 for (i=0; i<parent_dacl->AceCount; i++)
5923 ACE_HEADER *ace;
5925 if (!GetAce(parent_dacl, i, (void*)&ace))
5926 continue;
5927 if (!(ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)))
5928 continue;
5929 if ((ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) !=
5930 (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE))
5932 FIXME("unsupported flags: %x\n", ace->AceFlags);
5933 continue;
5936 if (ace->AceFlags & NO_PROPAGATE_INHERIT_ACE)
5937 ace->AceFlags &= ~(OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE|NO_PROPAGATE_INHERIT_ACE);
5938 ace->AceFlags &= ~INHERIT_ONLY_ACE;
5939 ace->AceFlags |= INHERITED_ACE;
5941 if(!AddAce(dacl, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
5942 WARN("error adding inherited ACE\n");
5944 LocalFree(parent_sd);
5947 else
5948 heap_free(name_info);
5952 SetSecurityDescriptorDacl(&sd, TRUE, dacl, FALSE);
5954 if (SecurityInfo & SACL_SECURITY_INFORMATION)
5955 SetSecurityDescriptorSacl(&sd, TRUE, pSacl, FALSE);
5957 switch (ObjectType)
5959 case SE_SERVICE:
5960 FIXME("stub: Service objects are not supported at this time.\n");
5961 status = STATUS_SUCCESS; /* Implement SetServiceObjectSecurity */
5962 break;
5963 default:
5964 status = NtSetSecurityObject(handle, SecurityInfo, &sd);
5965 break;
5967 if (dacl != pDacl)
5968 heap_free(dacl);
5969 return RtlNtStatusToDosError(status);
5972 /******************************************************************************
5973 * SaferCreateLevel [ADVAPI32.@]
5975 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
5976 SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
5978 FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
5980 *LevelHandle = (SAFER_LEVEL_HANDLE)0xdeadbeef;
5981 return TRUE;
5984 /******************************************************************************
5985 * SaferComputeTokenFromLevel [ADVAPI32.@]
5987 BOOL WINAPI SaferComputeTokenFromLevel(SAFER_LEVEL_HANDLE handle, HANDLE token, PHANDLE access_token,
5988 DWORD flags, LPVOID reserved)
5990 FIXME("(%p, %p, %p, %x, %p) stub\n", handle, token, access_token, flags, reserved);
5992 *access_token = (HANDLE)0xdeadbeef;
5993 return TRUE;
5996 /******************************************************************************
5997 * SaferCloseLevel [ADVAPI32.@]
5999 BOOL WINAPI SaferCloseLevel(SAFER_LEVEL_HANDLE handle)
6001 FIXME("(%p) stub\n", handle);
6002 return TRUE;
6005 DWORD WINAPI TreeResetNamedSecurityInfoW( LPWSTR pObjectName,
6006 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
6007 PSID pOwner, PSID pGroup, PACL pDacl, PACL pSacl,
6008 BOOL KeepExplicit, FN_PROGRESS fnProgress,
6009 PROG_INVOKE_SETTING ProgressInvokeSetting, PVOID Args)
6011 FIXME("(%s, %i, %i, %p, %p, %p, %p, %i, %p, %i, %p) stub\n",
6012 debugstr_w(pObjectName), ObjectType, SecurityInfo, pOwner, pGroup,
6013 pDacl, pSacl, KeepExplicit, fnProgress, ProgressInvokeSetting, Args);
6015 return ERROR_SUCCESS;
6018 /******************************************************************************
6019 * SaferGetPolicyInformation [ADVAPI32.@]
6021 BOOL WINAPI SaferGetPolicyInformation(DWORD scope, SAFER_POLICY_INFO_CLASS class, DWORD size,
6022 PVOID buffer, PDWORD required, LPVOID lpReserved)
6024 FIXME("(%u %u %u %p %p %p) stub\n", scope, class, size, buffer, required, lpReserved);
6025 return FALSE;
6028 /******************************************************************************
6029 * SaferSetLevelInformation [ADVAPI32.@]
6031 BOOL WINAPI SaferSetLevelInformation(SAFER_LEVEL_HANDLE handle, SAFER_OBJECT_INFO_CLASS infotype,
6032 LPVOID buffer, DWORD size)
6034 FIXME("(%p %u %p %u) stub\n", handle, infotype, buffer, size);
6035 return FALSE;