1 /* Copyright (C) 2004 Juan Lang
3 * This file implements loading of SSP DLLs.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include <lsass/lsass.h>
25 #include <wine/debug.h>
26 WINE_DEFAULT_DEBUG_CHANNEL(secur32
);
30 typedef struct _SecurePackageTable
37 typedef struct _SecureProviderTable
42 } SecureProviderTable
;
44 static void SECUR32_initializeProviders(void);
45 /* static */ void SECUR32_freeProviders(void);
47 static CRITICAL_SECTION cs
;
48 static CRITICAL_SECTION_DEBUG cs_debug
=
51 { &cs_debug
.ProcessLocksList
, &cs_debug
.ProcessLocksList
},
52 0, 0, { (DWORD_PTR
)(__FILE__
": cs") }
54 static CRITICAL_SECTION cs
= { &cs_debug
, -1, 0, 0, 0, 0 };
55 static SecurePackageTable
*packageTable
= NULL
;
56 static SecureProviderTable
*providerTable
= NULL
;
58 static SecurityFunctionTableA securityFunctionTableA
= {
59 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
60 EnumerateSecurityPackagesA
,
61 QueryCredentialsAttributesA
,
62 AcquireCredentialsHandleA
,
63 FreeCredentialsHandle
,
65 InitializeSecurityContextA
,
66 AcceptSecurityContext
,
68 DeleteSecurityContext
,
70 QueryContextAttributesA
,
71 ImpersonateSecurityContext
,
72 RevertSecurityContext
,
76 QuerySecurityPackageInfoA
,
77 EncryptMessage
, /* Reserved3 */
78 DecryptMessage
, /* Reserved4 */
79 ExportSecurityContext
,
80 ImportSecurityContextA
,
83 QuerySecurityContextToken
,
89 static SecurityFunctionTableW securityFunctionTableW
= {
90 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
91 EnumerateSecurityPackagesW
,
92 QueryCredentialsAttributesW
,
93 AcquireCredentialsHandleW
,
94 FreeCredentialsHandle
,
96 InitializeSecurityContextW
,
97 AcceptSecurityContext
,
99 DeleteSecurityContext
,
101 QueryContextAttributesW
,
102 ImpersonateSecurityContext
,
103 RevertSecurityContext
,
107 QuerySecurityPackageInfoW
,
108 EncryptMessage
, /* Reserved3 */
109 DecryptMessage
, /* Reserved4 */
110 ExportSecurityContext
,
111 ImportSecurityContextW
,
113 NULL
, /* Reserved8 */
114 QuerySecurityContextToken
,
120 /***********************************************************************
121 * InitSecurityInterfaceA (SECUR32.@)
123 PSecurityFunctionTableA WINAPI
InitSecurityInterfaceA(void)
125 TRACE("InitSecurityInterfaceA() called\n");
126 return &securityFunctionTableA
;
129 /***********************************************************************
130 * InitSecurityInterfaceW (SECUR32.@)
132 PSecurityFunctionTableW WINAPI
InitSecurityInterfaceW(void)
134 TRACE("InitSecurityInterfaceW() called\n");
135 return &securityFunctionTableW
;
138 static PWSTR
SECUR32_strdupW(PCWSTR str
)
144 ret
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str
) + 1) * sizeof(WCHAR
));
153 PWSTR
SECUR32_AllocWideFromMultiByte(PCSTR str
)
159 int charsNeeded
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
163 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
* sizeof(WCHAR
));
165 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, charsNeeded
);
175 PSTR
SECUR32_AllocMultiByteFromWide(PCWSTR str
)
181 int charsNeeded
= WideCharToMultiByte(CP_ACP
, 0, str
, -1, NULL
, 0,
186 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
);
188 WideCharToMultiByte(CP_ACP
, 0, str
, -1, ret
, charsNeeded
,
199 static void _makeFnTableA(PSecurityFunctionTableA fnTableA
,
200 const SecurityFunctionTableA
*inFnTableA
,
201 const SecurityFunctionTableW
*inFnTableW
)
207 /* The size of the version 1 table is based on platform sdk's
208 * sspi.h, though the sample ssp also provided with platform sdk
209 * implies only functions through QuerySecurityPackageInfoA are
210 * implemented (yikes)
212 size_t tableSize
= inFnTableA
->dwVersion
== 1 ?
213 (const BYTE
*)&inFnTableA
->SetContextAttributesA
-
214 (const BYTE
*)inFnTableA
: sizeof(SecurityFunctionTableA
);
216 memcpy(fnTableA
, inFnTableA
, tableSize
);
217 /* override this, since we can do it internally anyway */
218 fnTableA
->QuerySecurityPackageInfoA
=
219 QuerySecurityPackageInfoA
;
223 /* functions with thunks */
224 if (inFnTableW
->AcquireCredentialsHandleW
)
225 fnTableA
->AcquireCredentialsHandleA
=
226 thunk_AcquireCredentialsHandleA
;
227 if (inFnTableW
->InitializeSecurityContextW
)
228 fnTableA
->InitializeSecurityContextA
=
229 thunk_InitializeSecurityContextA
;
230 if (inFnTableW
->ImportSecurityContextW
)
231 fnTableA
->ImportSecurityContextA
=
232 thunk_ImportSecurityContextA
;
233 if (inFnTableW
->AddCredentialsW
)
234 fnTableA
->AddCredentialsA
=
235 thunk_AddCredentialsA
;
236 if (inFnTableW
->QueryCredentialsAttributesW
)
237 fnTableA
->QueryCredentialsAttributesA
=
238 thunk_QueryCredentialsAttributesA
;
239 if (inFnTableW
->QueryContextAttributesW
)
240 fnTableA
->QueryContextAttributesA
=
241 thunk_QueryContextAttributesA
;
242 if (inFnTableW
->SetContextAttributesW
)
243 fnTableA
->SetContextAttributesA
=
244 thunk_SetContextAttributesA
;
245 /* this can't be thunked, there's no extra param to know which
246 * package to forward to */
247 fnTableA
->EnumerateSecurityPackagesA
= NULL
;
248 /* functions with no thunks needed */
249 fnTableA
->AcceptSecurityContext
= inFnTableW
->AcceptSecurityContext
;
250 fnTableA
->CompleteAuthToken
= inFnTableW
->CompleteAuthToken
;
251 fnTableA
->DeleteSecurityContext
= inFnTableW
->DeleteSecurityContext
;
252 fnTableA
->ImpersonateSecurityContext
=
253 inFnTableW
->ImpersonateSecurityContext
;
254 fnTableA
->RevertSecurityContext
= inFnTableW
->RevertSecurityContext
;
255 fnTableA
->MakeSignature
= inFnTableW
->MakeSignature
;
256 fnTableA
->VerifySignature
= inFnTableW
->VerifySignature
;
257 fnTableA
->FreeContextBuffer
= inFnTableW
->FreeContextBuffer
;
258 fnTableA
->QuerySecurityPackageInfoA
=
259 QuerySecurityPackageInfoA
;
260 fnTableA
->ExportSecurityContext
=
261 inFnTableW
->ExportSecurityContext
;
262 fnTableA
->QuerySecurityContextToken
=
263 inFnTableW
->QuerySecurityContextToken
;
264 fnTableA
->EncryptMessage
= inFnTableW
->EncryptMessage
;
265 fnTableA
->DecryptMessage
= inFnTableW
->DecryptMessage
;
270 static void _makeFnTableW(PSecurityFunctionTableW fnTableW
,
271 const SecurityFunctionTableA
*inFnTableA
,
272 const SecurityFunctionTableW
*inFnTableW
)
278 /* The size of the version 1 table is based on platform sdk's
279 * sspi.h, though the sample ssp also provided with platform sdk
280 * implies only functions through QuerySecurityPackageInfoA are
281 * implemented (yikes)
283 size_t tableSize
= inFnTableW
->dwVersion
== 1 ?
284 (const BYTE
*)&inFnTableW
->SetContextAttributesW
-
285 (const BYTE
*)inFnTableW
: sizeof(SecurityFunctionTableW
);
287 memcpy(fnTableW
, inFnTableW
, tableSize
);
288 /* override this, since we can do it internally anyway */
289 fnTableW
->QuerySecurityPackageInfoW
=
290 QuerySecurityPackageInfoW
;
294 /* functions with thunks */
295 if (inFnTableA
->AcquireCredentialsHandleA
)
296 fnTableW
->AcquireCredentialsHandleW
=
297 thunk_AcquireCredentialsHandleW
;
298 if (inFnTableA
->InitializeSecurityContextA
)
299 fnTableW
->InitializeSecurityContextW
=
300 thunk_InitializeSecurityContextW
;
301 if (inFnTableA
->ImportSecurityContextA
)
302 fnTableW
->ImportSecurityContextW
=
303 thunk_ImportSecurityContextW
;
304 if (inFnTableA
->AddCredentialsA
)
305 fnTableW
->AddCredentialsW
=
306 thunk_AddCredentialsW
;
307 if (inFnTableA
->QueryCredentialsAttributesA
)
308 fnTableW
->QueryCredentialsAttributesW
=
309 thunk_QueryCredentialsAttributesW
;
310 if (inFnTableA
->QueryContextAttributesA
)
311 fnTableW
->QueryContextAttributesW
=
312 thunk_QueryContextAttributesW
;
313 if (inFnTableA
->SetContextAttributesA
)
314 fnTableW
->SetContextAttributesW
=
315 thunk_SetContextAttributesW
;
316 /* this can't be thunked, there's no extra param to know which
317 * package to forward to */
318 fnTableW
->EnumerateSecurityPackagesW
= NULL
;
319 /* functions with no thunks needed */
320 fnTableW
->AcceptSecurityContext
= inFnTableA
->AcceptSecurityContext
;
321 fnTableW
->CompleteAuthToken
= inFnTableA
->CompleteAuthToken
;
322 fnTableW
->DeleteSecurityContext
= inFnTableA
->DeleteSecurityContext
;
323 fnTableW
->ImpersonateSecurityContext
=
324 inFnTableA
->ImpersonateSecurityContext
;
325 fnTableW
->RevertSecurityContext
= inFnTableA
->RevertSecurityContext
;
326 fnTableW
->MakeSignature
= inFnTableA
->MakeSignature
;
327 fnTableW
->VerifySignature
= inFnTableA
->VerifySignature
;
328 fnTableW
->FreeContextBuffer
= inFnTableA
->FreeContextBuffer
;
329 fnTableW
->QuerySecurityPackageInfoW
=
330 QuerySecurityPackageInfoW
;
331 fnTableW
->ExportSecurityContext
=
332 inFnTableA
->ExportSecurityContext
;
333 fnTableW
->QuerySecurityContextToken
=
334 inFnTableA
->QuerySecurityContextToken
;
335 fnTableW
->EncryptMessage
= inFnTableA
->EncryptMessage
;
336 fnTableW
->DecryptMessage
= inFnTableA
->DecryptMessage
;
341 static void _copyPackageInfo(PSecPkgInfoW info
, const SecPkgInfoA
*inInfoA
,
342 const SecPkgInfoW
*inInfoW
)
344 if (info
&& (inInfoA
|| inInfoW
))
346 /* odd, I know, but up until Name and Comment the structures are
349 memcpy(info
, inInfoW
? inInfoW
: (const SecPkgInfoW
*)inInfoA
, sizeof(*info
));
352 info
->Name
= SECUR32_strdupW(inInfoW
->Name
);
353 info
->Comment
= SECUR32_strdupW(inInfoW
->Comment
);
357 info
->Name
= SECUR32_AllocWideFromMultiByte(inInfoA
->Name
);
358 info
->Comment
= SECUR32_AllocWideFromMultiByte(inInfoA
->Comment
);
364 SecureProvider
*SECUR32_addProvider(const SecurityFunctionTableA
*fnTableA
,
365 const SecurityFunctionTableW
*fnTableW
, PCWSTR moduleName
)
369 EnterCriticalSection(&cs
);
373 providerTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable
));
376 LeaveCriticalSection(&cs
);
380 list_init(&providerTable
->table
);
383 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider
));
386 LeaveCriticalSection(&cs
);
390 list_add_tail(&providerTable
->table
, &ret
->entry
);
393 if (fnTableA
|| fnTableW
)
395 ret
->moduleName
= moduleName
? SECUR32_strdupW(moduleName
) : NULL
;
396 _makeFnTableA(&ret
->fnTableA
, fnTableA
, fnTableW
);
397 _makeFnTableW(&ret
->fnTableW
, fnTableA
, fnTableW
);
398 ret
->loaded
= !moduleName
;
402 ret
->moduleName
= SECUR32_strdupW(moduleName
);
406 LeaveCriticalSection(&cs
);
411 void SECUR32_addPackages(SecureProvider
*provider
, ULONG toAdd
,
412 const SecPkgInfoA
*infoA
, const SecPkgInfoW
*infoW
)
417 assert(infoA
|| infoW
);
419 EnterCriticalSection(&cs
);
423 packageTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable
));
426 LeaveCriticalSection(&cs
);
430 packageTable
->numPackages
= 0;
431 list_init(&packageTable
->table
);
434 for (i
= 0; i
< toAdd
; i
++)
436 SecurePackage
*package
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage
));
440 list_add_tail(&packageTable
->table
, &package
->entry
);
442 package
->provider
= provider
;
443 _copyPackageInfo(&package
->infoW
,
444 infoA
? &infoA
[i
] : NULL
,
445 infoW
? &infoW
[i
] : NULL
);
447 packageTable
->numPackages
+= toAdd
;
449 LeaveCriticalSection(&cs
);
452 static void _tryLoadProvider(PWSTR moduleName
)
454 HMODULE lib
= LoadLibraryW(moduleName
);
458 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
459 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(lib
,
460 SECURITY_ENTRYPOINT_ANSIW
);
461 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
462 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(lib
,
463 SECURITY_ENTRYPOINT_ANSIA
);
465 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
466 debugstr_w(moduleName
), pInitSecurityInterfaceA
,
467 pInitSecurityInterfaceW
);
468 if (pInitSecurityInterfaceW
|| pInitSecurityInterfaceA
)
470 PSecurityFunctionTableA fnTableA
= NULL
;
471 PSecurityFunctionTableW fnTableW
= NULL
;
473 PSecPkgInfoA infoA
= NULL
;
474 PSecPkgInfoW infoW
= NULL
;
475 SECURITY_STATUS ret
= SEC_E_OK
;
477 if (pInitSecurityInterfaceA
)
478 fnTableA
= pInitSecurityInterfaceA();
479 if (pInitSecurityInterfaceW
)
480 fnTableW
= pInitSecurityInterfaceW();
481 if (fnTableW
&& fnTableW
->EnumerateSecurityPackagesW
)
483 if (fnTableW
!= &securityFunctionTableW
)
484 ret
= fnTableW
->EnumerateSecurityPackagesW(&toAdd
, &infoW
);
486 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
488 else if (fnTableA
&& fnTableA
->EnumerateSecurityPackagesA
)
490 if (fnTableA
!= &securityFunctionTableA
)
491 ret
= fnTableA
->EnumerateSecurityPackagesA(&toAdd
, &infoA
);
493 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
495 if (ret
== SEC_E_OK
&& toAdd
> 0 && (infoW
|| infoA
))
497 SecureProvider
*provider
= SECUR32_addProvider(NULL
, NULL
,
501 SECUR32_addPackages(provider
, toAdd
, infoA
, infoW
);
503 fnTableW
->FreeContextBuffer(infoW
);
505 fnTableA
->FreeContextBuffer(infoA
);
511 WARN("failed to load %s\n", debugstr_w(moduleName
));
514 static const WCHAR securityProvidersKeyW
[] = {
515 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
516 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
517 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
519 static const WCHAR securityProvidersW
[] = {
520 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
523 static void SECUR32_initializeProviders(void)
528 /* Now load providers from registry */
529 apiRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, securityProvidersKeyW
, 0,
531 if (apiRet
== ERROR_SUCCESS
)
533 WCHAR securityPkgNames
[MAX_PATH
]; /* arbitrary len */
534 DWORD size
= sizeof(securityPkgNames
), type
;
536 apiRet
= RegQueryValueExW(key
, securityProvidersW
, NULL
, &type
,
537 (PBYTE
)securityPkgNames
, &size
);
538 if (apiRet
== ERROR_SUCCESS
&& type
== REG_SZ
)
542 size
= size
/ sizeof(WCHAR
);
543 for (ptr
= securityPkgNames
;
544 ptr
< securityPkgNames
+ size
; )
548 for (comma
= ptr
; *comma
&& *comma
!= ','; comma
++)
552 for (; *ptr
&& isspace(*ptr
) && ptr
< securityPkgNames
+ size
;
556 _tryLoadProvider(ptr
);
557 ptr
+= lstrlenW(ptr
) + 1;
563 /* Now load the built-in providers (in Wine, this is done before the registry loading) */
565 /// FIXME: Interim Wine code until we get Samuel's rewrite!
566 /* First load built-in providers */
567 SECUR32_initNTLMSP();
568 SECUR32_initKerberosSP();
569 /* Load the Negotiate provider last so apps stumble over the working NTLM
570 * provider first. Attempting to fix bug #16905 while keeping the
571 * application reported on wine-users on 2006-09-12 working. */
572 SECUR32_initNegotiateSP();
577 SecurePackage
*SECUR32_findPackageW(PCWSTR packageName
)
579 SecurePackage
*ret
= NULL
;
580 BOOL matched
= FALSE
;
584 SECUR32_initializeProviders();
587 if (packageTable
&& packageName
)
589 LIST_FOR_EACH_ENTRY(ret
, &packageTable
->table
, SecurePackage
, entry
)
591 matched
= !lstrcmpiW(ret
->infoW
.Name
, packageName
);
599 if (ret
->provider
&& !ret
->provider
->loaded
)
601 ret
->provider
->lib
= LoadLibraryW(ret
->provider
->moduleName
);
602 if (ret
->provider
->lib
)
604 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
605 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(ret
->provider
->lib
,
606 SECURITY_ENTRYPOINT_ANSIW
);
607 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
608 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(ret
->provider
->lib
,
609 SECURITY_ENTRYPOINT_ANSIA
);
610 PSecurityFunctionTableA fnTableA
= NULL
;
611 PSecurityFunctionTableW fnTableW
= NULL
;
613 if (pInitSecurityInterfaceA
)
614 fnTableA
= pInitSecurityInterfaceA();
615 if (pInitSecurityInterfaceW
)
616 fnTableW
= pInitSecurityInterfaceW();
617 /* don't update built-in SecurityFunctionTable */
618 if (fnTableA
!= &securityFunctionTableA
)
619 _makeFnTableA(&ret
->provider
->fnTableA
, fnTableA
, fnTableW
);
620 if (fnTableW
!= &securityFunctionTableW
)
621 _makeFnTableW(&ret
->provider
->fnTableW
, fnTableA
, fnTableW
);
622 ret
->provider
->loaded
= TRUE
;
631 SecurePackage
*SECUR32_findPackageA(PCSTR packageName
)
637 UNICODE_STRING package
;
639 RtlCreateUnicodeStringFromAsciiz(&package
, packageName
);
640 ret
= SECUR32_findPackageW(package
.Buffer
);
641 RtlFreeUnicodeString(&package
);
648 /* static */ void SECUR32_freeProviders(void)
651 EnterCriticalSection(&cs
);
654 SECUR32_deinitSchannelSP();
659 SecurePackage
*package
, *package_next
;
660 LIST_FOR_EACH_ENTRY_SAFE(package
, package_next
, &packageTable
->table
,
661 SecurePackage
, entry
)
663 HeapFree(GetProcessHeap(), 0, package
->infoW
.Name
);
664 HeapFree(GetProcessHeap(), 0, package
->infoW
.Comment
);
665 HeapFree(GetProcessHeap(), 0, package
);
668 HeapFree(GetProcessHeap(), 0, packageTable
);
674 SecureProvider
*provider
, *provider_next
;
675 LIST_FOR_EACH_ENTRY_SAFE(provider
, provider_next
, &providerTable
->table
,
676 SecureProvider
, entry
)
678 HeapFree(GetProcessHeap(), 0, provider
->moduleName
);
680 FreeLibrary(provider
->lib
);
681 HeapFree(GetProcessHeap(), 0, provider
);
684 HeapFree(GetProcessHeap(), 0, providerTable
);
685 providerTable
= NULL
;
688 LeaveCriticalSection(&cs
);
689 DeleteCriticalSection(&cs
);
692 /***********************************************************************
693 * FreeContextBuffer (SECUR32.@)
695 * Doh--if pv was allocated by a crypto package, this may not be correct.
696 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
697 * be any guarantee, nor is there an alloc function in secur32.
699 SECURITY_STATUS WINAPI
FreeContextBuffer(PVOID pv
)
701 HeapFree(GetProcessHeap(), 0, pv
);
706 /***********************************************************************
707 * EnumerateSecurityPackagesW (SECUR32.@)
709 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesW(PULONG pcPackages
,
710 PSecPkgInfoW
*ppPackageInfo
)
712 SECURITY_STATUS ret
= SEC_E_OK
;
714 TRACE("(%p, %p)\n", pcPackages
, ppPackageInfo
);
718 SECUR32_initializeProviders();
721 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
723 EnterCriticalSection(&cs
);
726 SecurePackage
*package
;
729 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
730 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
732 if (package
->infoW
.Name
)
733 bytesNeeded
+= (lstrlenW(package
->infoW
.Name
) + 1) * sizeof(WCHAR
);
734 if (package
->infoW
.Comment
)
735 bytesNeeded
+= (lstrlenW(package
->infoW
.Comment
) + 1) * sizeof(WCHAR
);
739 *ppPackageInfo
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
745 *pcPackages
= packageTable
->numPackages
;
746 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
747 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
748 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
750 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
++;
752 *pkgInfo
= package
->infoW
;
753 if (package
->infoW
.Name
)
755 TRACE("Name[%d] = %s\n", i
- 1, debugstr_w(package
->infoW
.Name
));
756 pkgInfo
->Name
= nextString
;
757 lstrcpyW(nextString
, package
->infoW
.Name
);
758 nextString
+= lstrlenW(nextString
) + 1;
761 pkgInfo
->Name
= NULL
;
762 if (package
->infoW
.Comment
)
764 TRACE("Comment[%d] = %s\n", i
- 1, debugstr_w(package
->infoW
.Comment
));
765 pkgInfo
->Comment
= nextString
;
766 lstrcpyW(nextString
, package
->infoW
.Comment
);
767 nextString
+= lstrlenW(nextString
) + 1;
770 pkgInfo
->Comment
= NULL
;
774 ret
= SEC_E_INSUFFICIENT_MEMORY
;
777 LeaveCriticalSection(&cs
);
778 TRACE("<-- 0x%08x\n", ret
);
782 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
783 * structures) into an array of SecPkgInfoA structures, which it returns.
785 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
786 const SecPkgInfoW
*info
)
792 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
795 for (i
= 0; i
< cPackages
; i
++)
798 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
799 -1, NULL
, 0, NULL
, NULL
);
801 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
802 -1, NULL
, 0, NULL
, NULL
);
804 ret
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
809 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
810 for (i
= 0; i
< cPackages
; i
++)
812 PSecPkgInfoA pkgInfo
= ret
+ i
;
815 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
818 pkgInfo
->Name
= nextString
;
819 /* just repeat back to WideCharToMultiByte how many bytes
820 * it requires, since we asked it earlier
822 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
823 NULL
, 0, NULL
, NULL
);
824 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
825 pkgInfo
->Name
, bytes
, NULL
, NULL
);
826 nextString
+= lstrlenA(nextString
) + 1;
829 pkgInfo
->Name
= NULL
;
832 pkgInfo
->Comment
= nextString
;
833 /* just repeat back to WideCharToMultiByte how many bytes
834 * it requires, since we asked it earlier
836 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
837 NULL
, 0, NULL
, NULL
);
838 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
839 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
840 nextString
+= lstrlenA(nextString
) + 1;
843 pkgInfo
->Comment
= NULL
;
852 /***********************************************************************
853 * EnumerateSecurityPackagesA (SECUR32.@)
855 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesA(PULONG pcPackages
,
856 PSecPkgInfoA
*ppPackageInfo
)
861 ret
= EnumerateSecurityPackagesW(pcPackages
, &info
);
862 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
864 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
865 if (*pcPackages
&& !*ppPackageInfo
)
868 ret
= SEC_E_INSUFFICIENT_MEMORY
;
870 FreeContextBuffer(info
);
875 /***********************************************************************
876 * GetComputerObjectNameA (SECUR32.@)
878 * Get the local computer's name using the format specified.
881 * NameFormat [I] The format for the name.
882 * lpNameBuffer [O] Pointer to buffer to receive the name.
883 * nSize [I/O] Size in characters of buffer.
886 * TRUE If the name was written to lpNameBuffer.
887 * FALSE If the name couldn't be written.
890 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
891 * name will be returned in *nSize.
893 * nSize returns the number of characters written when lpNameBuffer is not
894 * NULL or the size of the buffer needed to hold the name when the buffer
895 * is too short or lpNameBuffer is NULL.
897 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
899 BOOLEAN WINAPI
GetComputerObjectNameA(
900 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
903 LPWSTR bufferW
= NULL
;
904 ULONG sizeW
= *nSize
;
905 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
907 bufferW
= HeapAlloc(GetProcessHeap(), 0, sizeW
* sizeof(WCHAR
));
908 if (bufferW
== NULL
) {
909 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
913 rc
= GetComputerObjectNameW(NameFormat
, bufferW
, &sizeW
);
915 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
916 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
921 HeapFree(GetProcessHeap(), 0, bufferW
);
925 /***********************************************************************
926 * GetComputerObjectNameW (SECUR32.@)
928 BOOLEAN WINAPI
GetComputerObjectNameW(
929 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
931 LSA_HANDLE policyHandle
;
932 LSA_OBJECT_ATTRIBUTES objectAttributes
;
933 PPOLICY_DNS_DOMAIN_INFO domainInfo
;
936 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
938 if (NameFormat
== NameUnknown
)
940 SetLastError(ERROR_INVALID_PARAMETER
);
944 ZeroMemory(&objectAttributes
, sizeof(objectAttributes
));
945 objectAttributes
.Length
= sizeof(objectAttributes
);
947 ntStatus
= LsaOpenPolicy(NULL
, &objectAttributes
,
948 POLICY_VIEW_LOCAL_INFORMATION
,
950 if (ntStatus
!= STATUS_SUCCESS
)
952 SetLastError(LsaNtStatusToWinError(ntStatus
));
953 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
957 ntStatus
= LsaQueryInformationPolicy(policyHandle
,
958 PolicyDnsDomainInformation
,
959 (PVOID
*)&domainInfo
);
960 if (ntStatus
!= STATUS_SUCCESS
)
962 SetLastError(LsaNtStatusToWinError(ntStatus
));
963 WARN("LsaQueryInformationPolicy failed with NT status %u\n",
965 LsaClose(policyHandle
);
973 case NameSamCompatible
:
975 WCHAR name
[MAX_COMPUTERNAME_LENGTH
+ 1];
976 DWORD size
= sizeof(name
)/sizeof(name
[0]);
977 if (GetComputerNameW(name
, &size
))
979 DWORD len
= domainInfo
->Name
.Length
+ size
+ 3;
985 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
990 WCHAR bs
[] = { '\\', 0 };
991 WCHAR ds
[] = { '$', 0 };
992 lstrcpyW(lpNameBuffer
, domainInfo
->Name
.Buffer
);
993 lstrcatW(lpNameBuffer
, bs
);
994 lstrcatW(lpNameBuffer
, name
);
995 lstrcatW(lpNameBuffer
, ds
);
999 else /* just requesting length required */
1007 SetLastError(ERROR_INTERNAL_ERROR
);
1012 case NameFullyQualifiedDN
:
1016 case NameUserPrincipal
:
1017 case NameCanonicalEx
:
1018 case NameServicePrincipal
:
1020 FIXME("NameFormat %d not implemented\n", NameFormat
);
1021 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
1025 SetLastError(ERROR_INVALID_PARAMETER
);
1031 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
1035 LsaFreeMemory(domainInfo
);
1036 LsaClose(policyHandle
);
1041 /***********************************************************************
1042 * GetUserNameExA (SECUR32.@)
1044 BOOLEAN WINAPI
GetUserNameExA(
1045 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
1048 LPWSTR bufferW
= NULL
;
1049 ULONG sizeW
= *nSize
;
1050 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
1052 bufferW
= HeapAlloc(GetProcessHeap(), 0, sizeW
* sizeof(WCHAR
));
1053 if (bufferW
== NULL
) {
1054 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1058 rc
= GetUserNameExW(NameFormat
, bufferW
, &sizeW
);
1060 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
1063 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
1070 SetLastError(ERROR_MORE_DATA
);
1075 HeapFree(GetProcessHeap(), 0, bufferW
);
1079 BOOLEAN WINAPI
GetUserNameExW(
1080 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
1082 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
1086 case NameSamCompatible
:
1088 WCHAR samname
[UNLEN
+ 1 + MAX_COMPUTERNAME_LENGTH
+ 1];
1092 /* This assumes the current user is always a local account */
1093 len
= MAX_COMPUTERNAME_LENGTH
+ 1;
1094 if (GetComputerNameW(samname
, &len
))
1096 out
= samname
+ lstrlenW(samname
);
1099 if (GetUserNameW(out
, &len
))
1101 if (lstrlenW(samname
) < *nSize
)
1103 lstrcpyW(lpNameBuffer
, samname
);
1104 *nSize
= lstrlenW(samname
);
1108 SetLastError(ERROR_MORE_DATA
);
1109 *nSize
= lstrlenW(samname
) + 1;
1116 case NameFullyQualifiedDN
:
1120 case NameUserPrincipal
:
1121 case NameCanonicalEx
:
1122 case NameServicePrincipal
:
1124 SetLastError(ERROR_NONE_MAPPED
);
1128 SetLastError(ERROR_INVALID_PARAMETER
);
1133 BOOLEAN WINAPI
TranslateNameA(
1134 LPCSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1135 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPSTR lpTranslatedName
,
1138 FIXME("%p %d %d %p %p\n", lpAccountName
, AccountNameFormat
,
1139 DesiredNameFormat
, lpTranslatedName
, nSize
);
1143 BOOLEAN WINAPI
TranslateNameW(
1144 LPCWSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1145 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPWSTR lpTranslatedName
,
1148 FIXME("%p %d %d %p %p\n", lpAccountName
, AccountNameFormat
,
1149 DesiredNameFormat
, lpTranslatedName
, nSize
);