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
24 #include <wine/debug.h>
25 WINE_DEFAULT_DEBUG_CHANNEL(secur32
);
27 typedef struct _SecurePackageTable
34 typedef struct _SecureProviderTable
39 } SecureProviderTable
;
41 static void SECUR32_initializeProviders(void);
43 static CRITICAL_SECTION cs
;
44 static CRITICAL_SECTION_DEBUG cs_debug
=
47 { &cs_debug
.ProcessLocksList
, &cs_debug
.ProcessLocksList
},
48 0, 0, { (DWORD_PTR
)(__FILE__
": cs") }
50 static CRITICAL_SECTION cs
= { &cs_debug
, -1, 0, 0, 0, 0 };
51 static SecurePackageTable
*packageTable
= NULL
;
52 static SecureProviderTable
*providerTable
= NULL
;
54 static SecurityFunctionTableA securityFunctionTableA
=
56 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
57 EnumerateSecurityPackagesA
,
58 QueryCredentialsAttributesA
,
59 AcquireCredentialsHandleA
,
60 FreeCredentialsHandle
,
62 InitializeSecurityContextA
,
63 AcceptSecurityContext
,
65 DeleteSecurityContext
,
67 QueryContextAttributesA
,
68 ImpersonateSecurityContext
,
69 RevertSecurityContext
,
73 QuerySecurityPackageInfoA
,
74 EncryptMessage
, /* Reserved3 */
75 DecryptMessage
, /* Reserved4 */
76 ExportSecurityContext
,
77 ImportSecurityContextA
,
80 QuerySecurityContextToken
,
86 static SecurityFunctionTableW securityFunctionTableW
=
88 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
89 EnumerateSecurityPackagesW
,
90 QueryCredentialsAttributesW
,
91 AcquireCredentialsHandleW
,
92 FreeCredentialsHandle
,
94 InitializeSecurityContextW
,
95 AcceptSecurityContext
,
97 DeleteSecurityContext
,
99 QueryContextAttributesW
,
100 ImpersonateSecurityContext
,
101 RevertSecurityContext
,
105 QuerySecurityPackageInfoW
,
106 EncryptMessage
, /* Reserved3 */
107 DecryptMessage
, /* Reserved4 */
108 ExportSecurityContext
,
109 ImportSecurityContextW
,
111 NULL
, /* Reserved8 */
112 QuerySecurityContextToken
,
118 /***********************************************************************
119 * EnumerateSecurityPackagesW (SECUR32.@)
121 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesW(PULONG pcPackages
,
122 PSecPkgInfoW
*ppPackageInfo
)
124 SECURITY_STATUS ret
= SEC_E_OK
;
126 TRACE("(%p, %p)\n", pcPackages
, ppPackageInfo
);
130 SECUR32_initializeProviders();
133 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
135 EnterCriticalSection(&cs
);
138 SecurePackage
*package
;
141 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
142 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
144 if (package
->infoW
.Name
)
145 bytesNeeded
+= (lstrlenW(package
->infoW
.Name
) + 1) * sizeof(WCHAR
);
146 if (package
->infoW
.Comment
)
147 bytesNeeded
+= (lstrlenW(package
->infoW
.Comment
) + 1) * sizeof(WCHAR
);
151 *ppPackageInfo
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
157 *pcPackages
= packageTable
->numPackages
;
158 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
159 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
160 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
162 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
++;
164 *pkgInfo
= package
->infoW
;
165 if (package
->infoW
.Name
)
167 TRACE("Name[%d] = %S\n", i
- 1, package
->infoW
.Name
);
168 pkgInfo
->Name
= nextString
;
169 lstrcpyW(nextString
, package
->infoW
.Name
);
170 nextString
+= lstrlenW(nextString
) + 1;
173 pkgInfo
->Name
= NULL
;
174 if (package
->infoW
.Comment
)
176 TRACE("Comment[%d] = %S\n", i
- 1, package
->infoW
.Comment
);
177 pkgInfo
->Comment
= nextString
;
178 lstrcpyW(nextString
, package
->infoW
.Comment
);
179 nextString
+= lstrlenW(nextString
) + 1;
182 pkgInfo
->Comment
= NULL
;
186 ret
= SEC_E_INSUFFICIENT_MEMORY
;
189 LeaveCriticalSection(&cs
);
190 TRACE("<-- 0x%08x\n", ret
);
194 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
195 * structures) into an array of SecPkgInfoA structures, which it returns.
197 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
198 const SecPkgInfoW
*info
)
204 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
207 for (i
= 0; i
< cPackages
; i
++)
210 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
211 -1, NULL
, 0, NULL
, NULL
);
213 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
214 -1, NULL
, 0, NULL
, NULL
);
216 ret
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
221 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
222 for (i
= 0; i
< cPackages
; i
++)
224 PSecPkgInfoA pkgInfo
= ret
+ i
;
227 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
230 pkgInfo
->Name
= nextString
;
231 /* just repeat back to WideCharToMultiByte how many bytes
232 * it requires, since we asked it earlier
234 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
235 NULL
, 0, NULL
, NULL
);
236 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
237 pkgInfo
->Name
, bytes
, NULL
, NULL
);
238 nextString
+= lstrlenA(nextString
) + 1;
241 pkgInfo
->Name
= NULL
;
244 pkgInfo
->Comment
= nextString
;
245 /* just repeat back to WideCharToMultiByte how many bytes
246 * it requires, since we asked it earlier
248 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
249 NULL
, 0, NULL
, NULL
);
250 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
251 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
252 nextString
+= lstrlenA(nextString
) + 1;
255 pkgInfo
->Comment
= NULL
;
264 /***********************************************************************
265 * EnumerateSecurityPackagesA (SECUR32.@)
267 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesA(PULONG pcPackages
,
268 PSecPkgInfoA
*ppPackageInfo
)
273 ret
= EnumerateSecurityPackagesW(pcPackages
, &info
);
274 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
276 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
277 if (*pcPackages
&& !*ppPackageInfo
)
280 ret
= SEC_E_INSUFFICIENT_MEMORY
;
282 FreeContextBuffer(info
);
293 HeapFree(GetProcessHeap(), 0, pvoid
);
297 PSecurityFunctionTableW
299 InitSecurityInterfaceW(VOID
)
301 TRACE("InitSecurityInterfaceW() called\n");
302 return &securityFunctionTableW
;
305 PSecurityFunctionTableA
307 InitSecurityInterfaceA(VOID
)
309 TRACE("InitSecurityInterfaceA() called\n");
310 return &securityFunctionTableA
;
316 LPCSTR lpAccountName
,
317 EXTENDED_NAME_FORMAT AccountNameFormat
,
318 EXTENDED_NAME_FORMAT DesiredNameFormat
,
319 LPSTR lpTranslatedName
,
330 LPCWSTR lpAccountName
,
331 EXTENDED_NAME_FORMAT AccountNameFormat
,
332 EXTENDED_NAME_FORMAT DesiredNameFormat
,
333 LPWSTR lpTranslatedName
,
341 /*** PRIVATE FUNCTIONS ***************************************************************************/
343 static PWSTR
SECUR32_strdupW(PCWSTR str
)
349 ret
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str
) + 1) * sizeof(WCHAR
));
358 PWSTR
SECUR32_AllocWideFromMultiByte(PCSTR str
)
364 int charsNeeded
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
368 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
* sizeof(WCHAR
));
370 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, charsNeeded
);
380 PSTR
SECUR32_AllocMultiByteFromWide(PCWSTR str
)
386 int charsNeeded
= WideCharToMultiByte(CP_ACP
, 0, str
, -1, NULL
, 0,
391 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
);
393 WideCharToMultiByte(CP_ACP
, 0, str
, -1, ret
, charsNeeded
,
404 static void _makeFnTableA(PSecurityFunctionTableA fnTableA
,
405 const SecurityFunctionTableA
*inFnTableA
,
406 const SecurityFunctionTableW
*inFnTableW
)
412 /* The size of the version 1 table is based on platform sdk's
413 * sspi.h, though the sample ssp also provided with platform sdk
414 * implies only functions through QuerySecurityPackageInfoA are
415 * implemented (yikes)
417 size_t tableSize
= inFnTableA
->dwVersion
== 1 ?
418 (const BYTE
*)&inFnTableA
->SetContextAttributesA
-
419 (const BYTE
*)inFnTableA
: sizeof(SecurityFunctionTableA
);
421 memcpy(fnTableA
, inFnTableA
, tableSize
);
422 /* override this, since we can do it internally anyway */
423 fnTableA
->QuerySecurityPackageInfoA
=
424 QuerySecurityPackageInfoA
;
428 /* functions with thunks */
429 if (inFnTableW
->AcquireCredentialsHandleW
)
430 fnTableA
->AcquireCredentialsHandleA
=
431 thunk_AcquireCredentialsHandleA
;
432 if (inFnTableW
->InitializeSecurityContextW
)
433 fnTableA
->InitializeSecurityContextA
=
434 thunk_InitializeSecurityContextA
;
435 if (inFnTableW
->ImportSecurityContextW
)
436 fnTableA
->ImportSecurityContextA
=
437 thunk_ImportSecurityContextA
;
438 if (inFnTableW
->AddCredentialsW
)
439 fnTableA
->AddCredentialsA
=
440 thunk_AddCredentialsA
;
441 if (inFnTableW
->QueryCredentialsAttributesW
)
442 fnTableA
->QueryCredentialsAttributesA
=
443 thunk_QueryCredentialsAttributesA
;
444 if (inFnTableW
->QueryContextAttributesW
)
445 fnTableA
->QueryContextAttributesA
=
446 thunk_QueryContextAttributesA
;
447 if (inFnTableW
->SetContextAttributesW
)
448 fnTableA
->SetContextAttributesA
=
449 thunk_SetContextAttributesA
;
450 /* this can't be thunked, there's no extra param to know which
451 * package to forward to */
452 fnTableA
->EnumerateSecurityPackagesA
= NULL
;
453 /* functions with no thunks needed */
454 fnTableA
->AcceptSecurityContext
= inFnTableW
->AcceptSecurityContext
;
455 fnTableA
->CompleteAuthToken
= inFnTableW
->CompleteAuthToken
;
456 fnTableA
->DeleteSecurityContext
= inFnTableW
->DeleteSecurityContext
;
457 fnTableA
->ImpersonateSecurityContext
=
458 inFnTableW
->ImpersonateSecurityContext
;
459 fnTableA
->RevertSecurityContext
= inFnTableW
->RevertSecurityContext
;
460 fnTableA
->MakeSignature
= inFnTableW
->MakeSignature
;
461 fnTableA
->VerifySignature
= inFnTableW
->VerifySignature
;
462 fnTableA
->FreeContextBuffer
= inFnTableW
->FreeContextBuffer
;
463 fnTableA
->QuerySecurityPackageInfoA
=
464 QuerySecurityPackageInfoA
;
465 fnTableA
->ExportSecurityContext
=
466 inFnTableW
->ExportSecurityContext
;
467 fnTableA
->QuerySecurityContextToken
=
468 inFnTableW
->QuerySecurityContextToken
;
469 fnTableA
->EncryptMessage
= inFnTableW
->EncryptMessage
;
470 fnTableA
->DecryptMessage
= inFnTableW
->DecryptMessage
;
475 static void _makeFnTableW(PSecurityFunctionTableW fnTableW
,
476 const SecurityFunctionTableA
*inFnTableA
,
477 const SecurityFunctionTableW
*inFnTableW
)
483 /* The size of the version 1 table is based on platform sdk's
484 * sspi.h, though the sample ssp also provided with platform sdk
485 * implies only functions through QuerySecurityPackageInfoA are
486 * implemented (yikes)
488 size_t tableSize
= inFnTableW
->dwVersion
== 1 ?
489 (const BYTE
*)&inFnTableW
->SetContextAttributesW
-
490 (const BYTE
*)inFnTableW
: sizeof(SecurityFunctionTableW
);
492 memcpy(fnTableW
, inFnTableW
, tableSize
);
493 /* override this, since we can do it internally anyway */
494 fnTableW
->QuerySecurityPackageInfoW
=
495 QuerySecurityPackageInfoW
;
499 /* functions with thunks */
500 if (inFnTableA
->AcquireCredentialsHandleA
)
501 fnTableW
->AcquireCredentialsHandleW
=
502 thunk_AcquireCredentialsHandleW
;
503 if (inFnTableA
->InitializeSecurityContextA
)
504 fnTableW
->InitializeSecurityContextW
=
505 thunk_InitializeSecurityContextW
;
506 if (inFnTableA
->ImportSecurityContextA
)
507 fnTableW
->ImportSecurityContextW
=
508 thunk_ImportSecurityContextW
;
509 if (inFnTableA
->AddCredentialsA
)
510 fnTableW
->AddCredentialsW
=
511 thunk_AddCredentialsW
;
512 if (inFnTableA
->QueryCredentialsAttributesA
)
513 fnTableW
->QueryCredentialsAttributesW
=
514 thunk_QueryCredentialsAttributesW
;
515 if (inFnTableA
->QueryContextAttributesA
)
516 fnTableW
->QueryContextAttributesW
=
517 thunk_QueryContextAttributesW
;
518 if (inFnTableA
->SetContextAttributesA
)
519 fnTableW
->SetContextAttributesW
=
520 thunk_SetContextAttributesW
;
521 /* this can't be thunked, there's no extra param to know which
522 * package to forward to */
523 fnTableW
->EnumerateSecurityPackagesW
= NULL
;
524 /* functions with no thunks needed */
525 fnTableW
->AcceptSecurityContext
= inFnTableA
->AcceptSecurityContext
;
526 fnTableW
->CompleteAuthToken
= inFnTableA
->CompleteAuthToken
;
527 fnTableW
->DeleteSecurityContext
= inFnTableA
->DeleteSecurityContext
;
528 fnTableW
->ImpersonateSecurityContext
=
529 inFnTableA
->ImpersonateSecurityContext
;
530 fnTableW
->RevertSecurityContext
= inFnTableA
->RevertSecurityContext
;
531 fnTableW
->MakeSignature
= inFnTableA
->MakeSignature
;
532 fnTableW
->VerifySignature
= inFnTableA
->VerifySignature
;
533 fnTableW
->FreeContextBuffer
= inFnTableA
->FreeContextBuffer
;
534 fnTableW
->QuerySecurityPackageInfoW
=
535 QuerySecurityPackageInfoW
;
536 fnTableW
->ExportSecurityContext
=
537 inFnTableA
->ExportSecurityContext
;
538 fnTableW
->QuerySecurityContextToken
=
539 inFnTableA
->QuerySecurityContextToken
;
540 fnTableW
->EncryptMessage
= inFnTableA
->EncryptMessage
;
541 fnTableW
->DecryptMessage
= inFnTableA
->DecryptMessage
;
546 static void _copyPackageInfo(PSecPkgInfoW info
, const SecPkgInfoA
*inInfoA
,
547 const SecPkgInfoW
*inInfoW
)
549 if (info
&& (inInfoA
|| inInfoW
))
551 /* odd, I know, but up until Name and Comment the structures are
554 memcpy(info
, inInfoW
? inInfoW
: (const SecPkgInfoW
*)inInfoA
, sizeof(*info
));
557 info
->Name
= SECUR32_strdupW(inInfoW
->Name
);
558 info
->Comment
= SECUR32_strdupW(inInfoW
->Comment
);
562 info
->Name
= SECUR32_AllocWideFromMultiByte(inInfoA
->Name
);
563 info
->Comment
= SECUR32_AllocWideFromMultiByte(inInfoA
->Comment
);
569 SecureProvider
*SECUR32_addProvider(const SecurityFunctionTableA
*fnTableA
,
570 const SecurityFunctionTableW
*fnTableW
, PCWSTR moduleName
)
574 EnterCriticalSection(&cs
);
578 providerTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable
));
581 LeaveCriticalSection(&cs
);
585 list_init(&providerTable
->table
);
588 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider
));
591 LeaveCriticalSection(&cs
);
595 list_add_tail(&providerTable
->table
, &ret
->entry
);
598 if (fnTableA
|| fnTableW
)
600 ret
->moduleName
= moduleName
? SECUR32_strdupW(moduleName
) : NULL
;
601 _makeFnTableA(&ret
->fnTableA
, fnTableA
, fnTableW
);
602 _makeFnTableW(&ret
->fnTableW
, fnTableA
, fnTableW
);
603 ret
->loaded
= !moduleName
;
607 ret
->moduleName
= SECUR32_strdupW(moduleName
);
611 LeaveCriticalSection(&cs
);
616 void SECUR32_addPackages(SecureProvider
*provider
, ULONG toAdd
,
617 const SecPkgInfoA
*infoA
, const SecPkgInfoW
*infoW
)
622 assert(infoA
|| infoW
);
624 EnterCriticalSection(&cs
);
628 packageTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable
));
631 LeaveCriticalSection(&cs
);
635 packageTable
->numPackages
= 0;
636 list_init(&packageTable
->table
);
639 for (i
= 0; i
< toAdd
; i
++)
641 SecurePackage
*package
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage
));
645 list_add_tail(&packageTable
->table
, &package
->entry
);
647 package
->provider
= provider
;
648 _copyPackageInfo(&package
->infoW
,
649 infoA
? &infoA
[i
] : NULL
,
650 infoW
? &infoW
[i
] : NULL
);
652 packageTable
->numPackages
+= toAdd
;
654 LeaveCriticalSection(&cs
);
657 static void _tryLoadProvider(PWSTR moduleName
)
659 HMODULE lib
= LoadLibraryW(moduleName
);
663 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
664 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(lib
,
665 SECURITY_ENTRYPOINT_ANSIW
);
666 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
667 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(lib
,
668 SECURITY_ENTRYPOINT_ANSIA
);
670 TRACE("loaded %S, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
671 moduleName
, pInitSecurityInterfaceA
,
672 pInitSecurityInterfaceW
);
673 if (pInitSecurityInterfaceW
|| pInitSecurityInterfaceA
)
675 PSecurityFunctionTableA fnTableA
= NULL
;
676 PSecurityFunctionTableW fnTableW
= NULL
;
678 PSecPkgInfoA infoA
= NULL
;
679 PSecPkgInfoW infoW
= NULL
;
680 SECURITY_STATUS ret
= SEC_E_OK
;
682 if (pInitSecurityInterfaceA
)
683 fnTableA
= pInitSecurityInterfaceA();
684 if (pInitSecurityInterfaceW
)
685 fnTableW
= pInitSecurityInterfaceW();
686 if (fnTableW
&& fnTableW
->EnumerateSecurityPackagesW
)
688 if (fnTableW
!= &securityFunctionTableW
)
689 ret
= fnTableW
->EnumerateSecurityPackagesW(&toAdd
, &infoW
);
691 TRACE("%S has built-in providers, skip adding\n", moduleName
);
693 else if (fnTableA
&& fnTableA
->EnumerateSecurityPackagesA
)
695 if (fnTableA
!= &securityFunctionTableA
)
696 ret
= fnTableA
->EnumerateSecurityPackagesA(&toAdd
, &infoA
);
698 TRACE("%S has built-in providers, skip adding\n", moduleName
);
700 if (ret
== SEC_E_OK
&& toAdd
> 0 && (infoW
|| infoA
))
702 SecureProvider
*provider
= SECUR32_addProvider(NULL
, NULL
,
706 SECUR32_addPackages(provider
, toAdd
, infoA
, infoW
);
708 fnTableW
->FreeContextBuffer(infoW
);
710 fnTableA
->FreeContextBuffer(infoA
);
716 WARN("failed to load %S\n", moduleName
);
719 static const WCHAR securityProvidersKeyW
[] = {
720 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
721 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
722 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
724 static const WCHAR securityProvidersW
[] = {
725 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
728 /* FIXME: we're missing SECUR32_freeProviders, so all of this gets leaked */
729 static void SECUR32_initializeProviders(void)
734 /* Now load providers from registry */
735 apiRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, securityProvidersKeyW
, 0,
737 if (apiRet
== ERROR_SUCCESS
)
739 WCHAR securityPkgNames
[MAX_PATH
]; /* arbitrary len */
740 DWORD size
= sizeof(securityPkgNames
) / sizeof(WCHAR
), type
;
742 apiRet
= RegQueryValueExW(key
, securityProvidersW
, NULL
, &type
,
743 (PBYTE
)securityPkgNames
, &size
);
744 if (apiRet
== ERROR_SUCCESS
&& type
== REG_SZ
)
748 size
= size
/ sizeof(WCHAR
);
749 for (ptr
= securityPkgNames
;
750 ptr
< securityPkgNames
+ size
; )
754 for (comma
= ptr
; *comma
&& *comma
!= ','; comma
++)
758 for (; *ptr
&& isspace(*ptr
) && ptr
< securityPkgNames
+ size
;
762 _tryLoadProvider(ptr
);
763 ptr
+= lstrlenW(ptr
) + 1;
770 SecurePackage
*SECUR32_findPackageW(PCWSTR packageName
)
772 SecurePackage
*ret
= NULL
;
773 BOOL matched
= FALSE
;
777 SECUR32_initializeProviders();
780 if (packageTable
&& packageName
)
782 LIST_FOR_EACH_ENTRY(ret
, &packageTable
->table
, SecurePackage
, entry
)
784 matched
= !lstrcmpiW(ret
->infoW
.Name
, packageName
);
792 if (ret
->provider
&& !ret
->provider
->loaded
)
794 ret
->provider
->lib
= LoadLibraryW(ret
->provider
->moduleName
);
795 if (ret
->provider
->lib
)
797 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
798 (INIT_SECURITY_INTERFACE_W
) GetProcAddress(ret
->provider
->lib
,
799 SECURITY_ENTRYPOINT_ANSIW
);
800 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
801 (INIT_SECURITY_INTERFACE_A
) GetProcAddress(ret
->provider
->lib
,
802 SECURITY_ENTRYPOINT_ANSIA
);
803 PSecurityFunctionTableA fnTableA
= NULL
;
804 PSecurityFunctionTableW fnTableW
= NULL
;
806 if (pInitSecurityInterfaceA
)
807 fnTableA
= pInitSecurityInterfaceA();
808 if (pInitSecurityInterfaceW
)
809 fnTableW
= pInitSecurityInterfaceW();
810 /* don't update built-in SecurityFunctionTable */
811 if (fnTableA
!= &securityFunctionTableA
)
812 _makeFnTableA(&ret
->provider
->fnTableA
, fnTableA
, fnTableW
);
813 if (fnTableW
!= &securityFunctionTableW
)
814 _makeFnTableW(&ret
->provider
->fnTableW
, fnTableA
, fnTableW
);
815 ret
->provider
->loaded
= TRUE
;
824 SecurePackage
*SECUR32_findPackageA(PCSTR packageName
)
830 UNICODE_STRING package
;
832 RtlCreateUnicodeStringFromAsciiz(&package
, packageName
);
833 ret
= SECUR32_findPackageW(package
.Buffer
);
834 RtlFreeUnicodeString(&package
);