2 * Copyright (C) 2004 Juan Lang
3 * Copyright (C) 2007 Kai Blin
4 * Copyright (C) 2017, 2018 Dmitry Timoshkov
6 * Local Security Authority functions, as far as secur32 has them.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define WIN32_NO_STATUS
35 #include "secur32_priv.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(secur32
);
41 #define LSA_MAGIC ('L' << 24 | 'S' << 16 | 'A' << 8 | ' ')
48 ULONG lsa_api_version
, lsa_table_count
, user_api_version
, user_table_count
;
49 SECPKG_FUNCTION_TABLE
*lsa_api
;
50 SECPKG_USER_FUNCTION_TABLE
*user_api
;
53 static struct lsa_package
*loaded_packages
;
54 static ULONG loaded_packages_count
;
61 NTSTATUS WINAPI
LsaCallAuthenticationPackage(HANDLE lsa_handle
, ULONG package_id
,
62 PVOID in_buffer
, ULONG in_buffer_length
,
63 PVOID
*out_buffer
, PULONG out_buffer_length
, PNTSTATUS status
)
67 TRACE("%p,%u,%p,%u,%p,%p,%p\n", lsa_handle
, package_id
, in_buffer
,
68 in_buffer_length
, out_buffer
, out_buffer_length
, status
);
70 for (i
= 0; i
< loaded_packages_count
; i
++)
72 if (loaded_packages
[i
].package_id
== package_id
)
74 if (loaded_packages
[i
].lsa_api
->CallPackageUntrusted
)
75 return loaded_packages
[i
].lsa_api
->CallPackageUntrusted(NULL
/* FIXME*/,
76 in_buffer
, NULL
, in_buffer_length
, out_buffer
, out_buffer_length
, status
);
78 return SEC_E_UNSUPPORTED_FUNCTION
;
82 return STATUS_INVALID_PARAMETER
;
85 NTSTATUS WINAPI
LsaConnectUntrusted(PHANDLE LsaHandle
)
87 struct lsa_connection
*lsa_conn
;
89 TRACE("%p\n", LsaHandle
);
91 lsa_conn
= HeapAlloc(GetProcessHeap(), 0, sizeof(*lsa_conn
));
92 if (!lsa_conn
) return STATUS_NO_MEMORY
;
94 lsa_conn
->magic
= LSA_MAGIC
;
95 *LsaHandle
= lsa_conn
;
97 return STATUS_SUCCESS
;
100 NTSTATUS WINAPI
LsaDeregisterLogonProcess(HANDLE LsaHandle
)
102 FIXME("%p stub\n", LsaHandle
);
103 return STATUS_SUCCESS
;
106 NTSTATUS WINAPI
LsaEnumerateLogonSessions(PULONG LogonSessionCount
,
107 PLUID
* LogonSessionList
)
109 FIXME("%p %p stub\n", LogonSessionCount
, LogonSessionList
);
110 *LogonSessionCount
= 0;
111 *LogonSessionList
= NULL
;
113 return STATUS_SUCCESS
;
116 NTSTATUS WINAPI
LsaFreeReturnBuffer(PVOID Buffer
)
118 FIXME("%p stub\n", Buffer
);
119 return STATUS_SUCCESS
;
122 NTSTATUS WINAPI
LsaGetLogonSessionData(PLUID LogonId
,
123 PSECURITY_LOGON_SESSION_DATA
* ppLogonSessionData
)
125 FIXME("%p %p stub\n", LogonId
, ppLogonSessionData
);
126 *ppLogonSessionData
= NULL
;
127 return STATUS_NOT_IMPLEMENTED
;
130 NTSTATUS WINAPI
LsaLogonUser(HANDLE LsaHandle
, PLSA_STRING OriginName
,
131 SECURITY_LOGON_TYPE LogonType
, ULONG AuthenticationPackage
,
132 PVOID AuthenticationInformation
, ULONG AuthenticationInformationLength
,
133 PTOKEN_GROUPS LocalGroups
, PTOKEN_SOURCE SourceContext
,
134 PVOID
* ProfileBuffer
, PULONG ProfileBufferLength
, PLUID LogonId
,
135 PHANDLE Token
, PQUOTA_LIMITS Quotas
, PNTSTATUS SubStatus
)
137 FIXME("%p %p %d %d %p %d %p %p %p %p %p %p %p %p stub\n", LsaHandle
,
138 OriginName
, LogonType
, AuthenticationPackage
,
139 AuthenticationInformation
, AuthenticationInformationLength
,
140 LocalGroups
, SourceContext
, ProfileBuffer
, ProfileBufferLength
,
141 LogonId
, Token
, Quotas
, SubStatus
);
142 return STATUS_SUCCESS
;
145 static NTSTATUS NTAPI
lsa_CreateLogonSession(LUID
*logon_id
)
147 FIXME("%p: stub\n", logon_id
);
148 return STATUS_NOT_IMPLEMENTED
;
151 static NTSTATUS NTAPI
lsa_DeleteLogonSession(LUID
*logon_id
)
153 FIXME("%p: stub\n", logon_id
);
154 return STATUS_NOT_IMPLEMENTED
;
157 static NTSTATUS NTAPI
lsa_AddCredential(LUID
*logon_id
, ULONG package_id
,
158 LSA_STRING
*primary_key
, LSA_STRING
*credentials
)
160 FIXME("%p,%u,%p,%p: stub\n", logon_id
, package_id
, primary_key
, credentials
);
161 return STATUS_NOT_IMPLEMENTED
;
164 static NTSTATUS NTAPI
lsa_GetCredentials(LUID
*logon_id
, ULONG package_id
, ULONG
*context
,
165 BOOLEAN retrieve_all
, LSA_STRING
*primary_key
, ULONG
*primary_key_len
, LSA_STRING
*credentials
)
167 FIXME("%p,%#x,%p,%d,%p,%p,%p: stub\n", logon_id
, package_id
, context
,
168 retrieve_all
, primary_key
, primary_key_len
, credentials
);
169 return STATUS_NOT_IMPLEMENTED
;
172 static NTSTATUS NTAPI
lsa_DeleteCredential(LUID
*logon_id
, ULONG package_id
, LSA_STRING
*primary_key
)
174 FIXME("%p,%#x,%p: stub\n", logon_id
, package_id
, primary_key
);
175 return STATUS_NOT_IMPLEMENTED
;
178 static void * NTAPI
lsa_AllocateLsaHeap(ULONG size
)
181 return HeapAlloc(GetProcessHeap(), 0, size
);
184 static void NTAPI
lsa_FreeLsaHeap(void *p
)
187 HeapFree(GetProcessHeap(), 0, p
);
190 static NTSTATUS NTAPI
lsa_AllocateClientBuffer(PLSA_CLIENT_REQUEST req
, ULONG size
, void **p
)
192 TRACE("%p,%u,%p\n", req
, size
, p
);
193 *p
= HeapAlloc(GetProcessHeap(), 0, size
);
194 return *p
? STATUS_SUCCESS
: STATUS_NO_MEMORY
;
197 static NTSTATUS NTAPI
lsa_FreeClientBuffer(PLSA_CLIENT_REQUEST req
, void *p
)
199 TRACE("%p,%p\n", req
, p
);
200 HeapFree(GetProcessHeap(), 0, p
);
201 return STATUS_SUCCESS
;
204 static NTSTATUS NTAPI
lsa_CopyToClientBuffer(PLSA_CLIENT_REQUEST req
, ULONG size
, void *client
, void *buf
)
206 TRACE("%p,%u,%p,%p\n", req
, size
, client
, buf
);
207 memcpy(client
, buf
, size
);
208 return STATUS_SUCCESS
;
211 static NTSTATUS NTAPI
lsa_CopyFromClientBuffer(PLSA_CLIENT_REQUEST req
, ULONG size
, void *buf
, void *client
)
213 TRACE("%p,%u,%p,%p\n", req
, size
, buf
, client
);
214 memcpy(buf
, client
, size
);
215 return STATUS_SUCCESS
;
218 static LSA_DISPATCH_TABLE lsa_dispatch
=
220 lsa_CreateLogonSession
,
221 lsa_DeleteLogonSession
,
224 lsa_DeleteCredential
,
227 lsa_AllocateClientBuffer
,
228 lsa_FreeClientBuffer
,
229 lsa_CopyToClientBuffer
,
230 lsa_CopyFromClientBuffer
233 static NTSTATUS NTAPI
lsa_RegisterCallback(ULONG callback_id
, PLSA_CALLBACK_FUNCTION callback
)
235 FIXME("%u,%p: stub\n", callback_id
, callback
);
236 return STATUS_NOT_IMPLEMENTED
;
239 static SECPKG_DLL_FUNCTIONS lsa_dll_dispatch
=
246 static SECURITY_STATUS
lsa_lookup_package(SEC_WCHAR
*nameW
, struct lsa_package
**lsa_package
)
249 UNICODE_STRING package_name
, name
;
251 for (i
= 0; i
< loaded_packages_count
; i
++)
253 if (RtlAnsiStringToUnicodeString(&package_name
, loaded_packages
[i
].name
, TRUE
))
254 return SEC_E_INSUFFICIENT_MEMORY
;
256 RtlInitUnicodeString(&name
, nameW
);
258 if (RtlEqualUnicodeString(&package_name
, &name
, TRUE
))
260 RtlFreeUnicodeString(&package_name
);
261 *lsa_package
= &loaded_packages
[i
];
265 RtlFreeUnicodeString(&package_name
);
268 return SEC_E_SECPKG_NOT_FOUND
;
271 static SECURITY_STATUS WINAPI
lsa_AcquireCredentialsHandleW(
272 SEC_WCHAR
*principal
, SEC_WCHAR
*package
, ULONG credentials_use
,
273 LUID
*logon_id
, void *auth_data
, SEC_GET_KEY_FN get_key_fn
,
274 void *get_key_arg
, CredHandle
*credential
, TimeStamp
*ts_expiry
)
276 SECURITY_STATUS status
;
277 struct lsa_package
*lsa_package
;
278 UNICODE_STRING principal_us
;
279 LSA_SEC_HANDLE lsa_credential
;
281 TRACE("%s %s %#x %p %p %p %p %p\n", debugstr_w(principal
), debugstr_w(package
),
282 credentials_use
, auth_data
, get_key_fn
, get_key_arg
, credential
, ts_expiry
);
284 if (!credential
) return SEC_E_INVALID_HANDLE
;
285 if (!package
) return SEC_E_SECPKG_NOT_FOUND
;
287 status
= lsa_lookup_package(package
, &lsa_package
);
288 if (status
!= SEC_E_OK
) return status
;
290 if (!lsa_package
->lsa_api
|| !lsa_package
->lsa_api
->SpAcquireCredentialsHandle
)
291 return SEC_E_UNSUPPORTED_FUNCTION
;
294 RtlInitUnicodeString(&principal_us
, principal
);
296 status
= lsa_package
->lsa_api
->SpAcquireCredentialsHandle(principal
? &principal_us
: NULL
,
297 credentials_use
, logon_id
, auth_data
, get_key_fn
, get_key_arg
, &lsa_credential
, ts_expiry
);
298 if (status
== SEC_E_OK
)
300 credential
->dwLower
= (ULONG_PTR
)lsa_credential
;
301 credential
->dwUpper
= (ULONG_PTR
)lsa_package
;
306 static SECURITY_STATUS WINAPI
lsa_AcquireCredentialsHandleA(
307 SEC_CHAR
*principal
, SEC_CHAR
*package
, ULONG credentials_use
,
308 LUID
*logon_id
, void *auth_data
, SEC_GET_KEY_FN get_key_fn
,
309 void *get_key_arg
, CredHandle
*credential
, TimeStamp
*ts_expiry
)
311 SECURITY_STATUS status
= SEC_E_INSUFFICIENT_MEMORY
;
312 int len_user
= 0, len_domain
= 0, len_passwd
= 0;
313 SEC_WCHAR
*principalW
= NULL
, *packageW
= NULL
, *user
= NULL
, *domain
= NULL
, *passwd
= NULL
;
314 SEC_WINNT_AUTH_IDENTITY_W
*auth_dataW
= NULL
;
315 SEC_WINNT_AUTH_IDENTITY_A
*id
= NULL
;
317 TRACE("%s %s %#x %p %p %p %p %p\n", debugstr_a(principal
), debugstr_a(package
),
318 credentials_use
, auth_data
, get_key_fn
, get_key_arg
, credential
, ts_expiry
);
322 int len
= MultiByteToWideChar( CP_ACP
, 0, principal
, -1, NULL
, 0 );
323 if (!(principalW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(SEC_WCHAR
) ))) goto done
;
324 MultiByteToWideChar( CP_ACP
, 0, principal
, -1, principalW
, len
);
328 int len
= MultiByteToWideChar( CP_ACP
, 0, package
, -1, NULL
, 0 );
329 if (!(packageW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(SEC_WCHAR
) ))) goto done
;
330 MultiByteToWideChar( CP_ACP
, 0, package
, -1, packageW
, len
);
334 id
= (PSEC_WINNT_AUTH_IDENTITY_A
)auth_data
;
336 if (id
->Flags
== SEC_WINNT_AUTH_IDENTITY_ANSI
)
338 if (!(auth_dataW
= HeapAlloc( GetProcessHeap(), 0, sizeof(SEC_WINNT_AUTH_IDENTITY_W
) ))) goto done
;
341 len_user
= MultiByteToWideChar( CP_ACP
, 0, (char *)id
->User
, id
->UserLength
, NULL
, 0 );
342 if (!(user
= HeapAlloc( GetProcessHeap(), 0, len_user
* sizeof(SEC_WCHAR
) ))) goto done
;
343 MultiByteToWideChar( CP_ACP
, 0, (char *)id
->User
, id
->UserLength
, user
, len_user
);
345 if (id
->DomainLength
)
347 len_domain
= MultiByteToWideChar( CP_ACP
, 0, (char *)id
->Domain
, id
->DomainLength
, NULL
, 0 );
348 if (!(domain
= HeapAlloc( GetProcessHeap(), 0, len_domain
* sizeof(SEC_WCHAR
) ))) goto done
;
349 MultiByteToWideChar( CP_ACP
, 0, (char *)id
->Domain
, id
->DomainLength
, domain
, len_domain
);
351 if (id
->PasswordLength
)
353 len_passwd
= MultiByteToWideChar( CP_ACP
, 0, (char *)id
->Password
, id
->PasswordLength
, NULL
, 0 );
354 if (!(passwd
= HeapAlloc( GetProcessHeap(), 0, len_passwd
* sizeof(SEC_WCHAR
) ))) goto done
;
355 MultiByteToWideChar( CP_ACP
, 0, (char *)id
->Password
, id
->PasswordLength
, passwd
, len_passwd
);
357 auth_dataW
->Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
358 auth_dataW
->User
= user
;
359 auth_dataW
->UserLength
= len_user
;
360 auth_dataW
->Domain
= domain
;
361 auth_dataW
->DomainLength
= len_domain
;
362 auth_dataW
->Password
= passwd
;
363 auth_dataW
->PasswordLength
= len_passwd
;
365 else auth_dataW
= (PSEC_WINNT_AUTH_IDENTITY_W
)auth_data
;
368 status
= lsa_AcquireCredentialsHandleW( principalW
, packageW
, credentials_use
, logon_id
, auth_dataW
, get_key_fn
,
369 get_key_arg
, credential
, ts_expiry
);
371 if (auth_dataW
!= (SEC_WINNT_AUTH_IDENTITY_W
*)id
) HeapFree( GetProcessHeap(), 0, auth_dataW
);
372 HeapFree( GetProcessHeap(), 0, packageW
);
373 HeapFree( GetProcessHeap(), 0, principalW
);
374 HeapFree( GetProcessHeap(), 0, user
);
375 HeapFree( GetProcessHeap(), 0, domain
);
376 HeapFree( GetProcessHeap(), 0, passwd
);
380 static const SecurityFunctionTableW lsa_sspi_tableW
=
383 NULL
, /* EnumerateSecurityPackagesW */
384 NULL
, /* QueryCredentialsAttributesW */
385 lsa_AcquireCredentialsHandleW
,
386 NULL
, /* FreeCredentialsHandle */
387 NULL
, /* Reserved2 */
388 NULL
, /* InitializeSecurityContextW */
389 NULL
, /* AcceptSecurityContext */
390 NULL
, /* CompleteAuthToken */
391 NULL
, /* DeleteSecurityContext */
392 NULL
, /* ApplyControlToken */
393 NULL
, /* QueryContextAttributesW */
394 NULL
, /* ImpersonateSecurityContext */
395 NULL
, /* RevertSecurityContext */
396 NULL
, /* MakeSignature */
397 NULL
, /* VerifySignature */
398 NULL
, /* FreeContextBuffer */
399 NULL
, /* QuerySecurityPackageInfoW */
400 NULL
, /* Reserved3 */
401 NULL
, /* Reserved4 */
402 NULL
, /* ExportSecurityContext */
403 NULL
, /* ImportSecurityContextW */
404 NULL
, /* AddCredentialsW */
405 NULL
, /* Reserved8 */
406 NULL
, /* QuerySecurityContextToken */
407 NULL
, /* EncryptMessage */
408 NULL
, /* DecryptMessage */
409 NULL
, /* SetContextAttributesW */
412 static const SecurityFunctionTableA lsa_sspi_tableA
=
415 NULL
, /* EnumerateSecurityPackagesA */
416 NULL
, /* QueryCredentialsAttributesA */
417 lsa_AcquireCredentialsHandleA
,
418 NULL
, /* FreeCredentialsHandle */
419 NULL
, /* Reserved2 */
420 NULL
, /* InitializeSecurityContextA */
421 NULL
, /* AcceptSecurityContext */
422 NULL
, /* CompleteAuthToken */
423 NULL
, /* DeleteSecurityContext */
424 NULL
, /* ApplyControlToken */
425 NULL
, /* QueryContextAttributesA */
426 NULL
, /* ImpersonateSecurityContext */
427 NULL
, /* RevertSecurityContext */
428 NULL
, /* MakeSignature */
429 NULL
, /* VerifySignature */
430 NULL
, /* FreeContextBuffer */
431 NULL
, /* QuerySecurityPackageInfoA */
432 NULL
, /* Reserved3 */
433 NULL
, /* Reserved4 */
434 NULL
, /* ExportSecurityContext */
435 NULL
, /* ImportSecurityContextA */
436 NULL
, /* AddCredentialsA */
437 NULL
, /* Reserved8 */
438 NULL
, /* QuerySecurityContextToken */
439 NULL
, /* EncryptMessage */
440 NULL
, /* DecryptMessage */
441 NULL
, /* SetContextAttributesA */
444 static void add_package(struct lsa_package
*package
)
446 struct lsa_package
*new_loaded_packages
;
448 if (!loaded_packages
)
449 new_loaded_packages
= HeapAlloc(GetProcessHeap(), 0, sizeof(*new_loaded_packages
));
451 new_loaded_packages
= HeapReAlloc(GetProcessHeap(), 0, loaded_packages
, sizeof(*new_loaded_packages
) * (loaded_packages_count
+ 1));
453 if (new_loaded_packages
)
455 loaded_packages
= new_loaded_packages
;
456 loaded_packages
[loaded_packages_count
] = *package
;
457 loaded_packages_count
++;
461 static BOOL
load_package(const WCHAR
*name
, struct lsa_package
*package
, ULONG package_id
)
463 NTSTATUS (NTAPI
*pSpLsaModeInitialize
)(ULONG
, PULONG
, PSECPKG_FUNCTION_TABLE
*, PULONG
);
464 NTSTATUS (NTAPI
*pSpUserModeInitialize
)(ULONG
, PULONG
, PSECPKG_USER_FUNCTION_TABLE
*, PULONG
);
466 memset(package
, 0, sizeof(*package
));
468 package
->mod
= LoadLibraryW(name
);
469 if (!package
->mod
) return FALSE
;
471 pSpLsaModeInitialize
= (void *)GetProcAddress(package
->mod
, "SpLsaModeInitialize");
472 if (pSpLsaModeInitialize
)
476 status
= pSpLsaModeInitialize(SECPKG_INTERFACE_VERSION
, &package
->lsa_api_version
, &package
->lsa_api
, &package
->lsa_table_count
);
477 if (status
== STATUS_SUCCESS
)
479 status
= package
->lsa_api
->InitializePackage(package_id
, &lsa_dispatch
, NULL
, NULL
, &package
->name
);
480 if (status
== STATUS_SUCCESS
)
482 TRACE("%s => %p, name %s, version %#x, api table %p, table count %u\n",
483 debugstr_w(name
), package
->mod
, debugstr_an(package
->name
->Buffer
, package
->name
->Length
),
484 package
->lsa_api_version
, package
->lsa_api
, package
->lsa_table_count
);
485 package
->package_id
= package_id
;
487 status
= package
->lsa_api
->Initialize(package_id
, NULL
/* FIXME: params */, NULL
);
488 if (status
== STATUS_SUCCESS
)
490 pSpUserModeInitialize
= (void *)GetProcAddress(package
->mod
, "SpUserModeInitialize");
491 if (pSpUserModeInitialize
)
493 status
= pSpUserModeInitialize(SECPKG_INTERFACE_VERSION
, &package
->user_api_version
, &package
->user_api
, &package
->user_table_count
);
494 if (status
== STATUS_SUCCESS
)
495 package
->user_api
->InstanceInit(SECPKG_INTERFACE_VERSION
, &lsa_dll_dispatch
, NULL
);
503 FreeLibrary(package
->mod
);
507 #define MAX_SERVICE_NAME 260
509 void load_auth_packages(void)
511 static const WCHAR LSA_KEY
[] = { 'S','y','s','t','e','m','\\',
512 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
513 'C','o','n','t','r','o','l','\\','L','s','a',0 };
516 SecureProvider
*provider
;
518 err
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, LSA_KEY
, 0, KEY_READ
, &root
);
519 if (err
!= ERROR_SUCCESS
) return;
524 WCHAR name
[MAX_SERVICE_NAME
];
525 struct lsa_package package
;
527 err
= RegEnumKeyW(root
, i
++, name
, MAX_SERVICE_NAME
);
528 if (err
== ERROR_NO_MORE_ITEMS
)
531 if (err
!= ERROR_SUCCESS
)
534 if (!load_package(name
, &package
, i
))
537 add_package(&package
);
542 if (!loaded_packages_count
) return;
544 provider
= SECUR32_addProvider(&lsa_sspi_tableA
, &lsa_sspi_tableW
, NULL
);
547 ERR("Failed to add SSP/AP provider\n");
551 for (i
= 0; i
< loaded_packages_count
; i
++)
555 info
= HeapAlloc(GetProcessHeap(), 0, loaded_packages
[i
].lsa_table_count
* sizeof(*info
));
560 status
= loaded_packages
[i
].lsa_api
->GetInfo(info
);
561 if (status
== STATUS_SUCCESS
)
562 SECUR32_addPackages(provider
, loaded_packages
[i
].lsa_table_count
, NULL
, info
);
564 HeapFree(GetProcessHeap(), 0, info
);
569 NTSTATUS WINAPI
LsaLookupAuthenticationPackage(HANDLE lsa_handle
,
570 PLSA_STRING package_name
, PULONG package_id
)
574 TRACE("%p %p %p\n", lsa_handle
, package_name
, package_id
);
576 for (i
= 0; i
< loaded_packages_count
; i
++)
578 if (!RtlCompareString(loaded_packages
[i
].name
, package_name
, FALSE
))
580 *package_id
= loaded_packages
[i
].package_id
;
581 return STATUS_SUCCESS
;
585 return STATUS_UNSUCCESSFUL
; /* FIXME */
588 NTSTATUS WINAPI
LsaRegisterLogonProcess(PLSA_STRING LogonProcessName
,
589 PHANDLE LsaHandle
, PLSA_OPERATIONAL_MODE SecurityMode
)
591 FIXME("%p %p %p stub\n", LogonProcessName
, LsaHandle
, SecurityMode
);
592 return STATUS_SUCCESS
;