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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "secur32_priv.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(secur32
);
38 typedef struct _SecurePackageTable
42 SecurePackage table
[1];
45 typedef struct _SecureProviderTable
49 SecureProvider table
[1];
50 } SecureProviderTable
;
56 /* Makes sure table has space for at least howBig entries. If table is NULL,
57 * returns a newly allocated table. Otherwise returns the address of the
58 * modified table, which may not be the same was when called.
60 static SecurePackageTable
*_resizePackageTable(SecurePackageTable
*table
,
63 /* Makes sure table has space for at least howBig entries. If table is NULL,
64 * returns a newly allocated table. Otherwise returns the address of the
65 * modified table, which may not be the same was when called.
67 static SecureProviderTable
*_resizeProviderTable(SecureProviderTable
*table
,
70 /* Tries to load moduleName as a provider. If successful, enumerates what
71 * packages it can and adds them to the package and provider tables. Resizes
72 * tables as necessary.
74 static void _tryLoadProvider(PWSTR moduleName
);
76 /* Initialization: read securityproviders value and attempt to open each dll
77 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
78 * Two undocumented functions, AddSecurityPackage(A/W) and
79 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
80 * unregister a dll, but I'm not sure.
82 static void SECUR32_initializeProviders(void);
84 /* Frees all loaded packages and providers */
85 static void SECUR32_freeProviders(void);
91 static CRITICAL_SECTION cs
;
92 static SecurePackageTable
*packageTable
= NULL
;
93 static SecureProviderTable
*providerTable
= NULL
;
95 static SecurityFunctionTableA securityFunctionTableA
= {
96 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2
,
97 EnumerateSecurityPackagesA
,
98 QueryCredentialsAttributesA
,
99 AcquireCredentialsHandleA
,
100 FreeCredentialsHandle
,
101 NULL
, /* Reserved2 */
102 InitializeSecurityContextA
,
103 AcceptSecurityContext
,
105 DeleteSecurityContext
,
107 QueryContextAttributesA
,
108 ImpersonateSecurityContext
,
109 RevertSecurityContext
,
113 QuerySecurityPackageInfoA
,
114 NULL
, /* Reserved3 */
115 NULL
, /* Reserved4 */
116 ExportSecurityContext
,
117 ImportSecurityContextA
,
119 NULL
, /* Reserved8 */
120 QuerySecurityContextToken
,
123 SetContextAttributesA
126 static SecurityFunctionTableW securityFunctionTableW
= {
127 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2
,
128 EnumerateSecurityPackagesW
,
129 QueryCredentialsAttributesW
,
130 AcquireCredentialsHandleW
,
131 FreeCredentialsHandle
,
132 NULL
, /* Reserved2 */
133 InitializeSecurityContextW
,
134 AcceptSecurityContext
,
136 DeleteSecurityContext
,
138 QueryContextAttributesW
,
139 ImpersonateSecurityContext
,
140 RevertSecurityContext
,
144 QuerySecurityPackageInfoW
,
145 NULL
, /* Reserved3 */
146 NULL
, /* Reserved4 */
147 ExportSecurityContext
,
148 ImportSecurityContextW
,
150 NULL
, /* Reserved8 */
151 QuerySecurityContextToken
,
154 SetContextAttributesW
157 PSecurityFunctionTableA SEC_ENTRY
InitSecurityInterfaceA(void)
159 return &securityFunctionTableA
;
162 PSecurityFunctionTableW SEC_ENTRY
InitSecurityInterfaceW(void)
164 return &securityFunctionTableW
;
167 /* Allocates or resizes table to have space for at least howBig packages.
168 * Uses Heap functions, because needs to be able to reallocate.
170 static SecurePackageTable
*_resizePackageTable(SecurePackageTable
*table
,
173 SecurePackageTable
*ret
;
175 EnterCriticalSection(&cs
);
178 if (table
->numAllocated
< howBig
)
180 ret
= (SecurePackageTable
*)HeapReAlloc(GetProcessHeap(), 0, table
,
181 sizeof(SecurePackageTable
) + (howBig
- 1) * sizeof(SecurePackage
));
184 ret
->numAllocated
= howBig
;
193 DWORD numAllocated
= (howBig
> 1 ? howBig
: 1);
195 ret
= (SecurePackageTable
*)HeapAlloc(GetProcessHeap(), 0,
196 sizeof(SecurePackageTable
) +
197 (numAllocated
- 1) * sizeof(SecurePackage
));
200 ret
->numAllocated
= numAllocated
;
201 ret
->numPackages
= 0;
204 LeaveCriticalSection(&cs
);
208 /* Allocates or resizes table to have space for at least howBig providers.
209 * Uses Heap functions, because needs to be able to reallocate.
211 static SecureProviderTable
*_resizeProviderTable(SecureProviderTable
*table
,
214 SecureProviderTable
*ret
;
216 EnterCriticalSection(&cs
);
219 if (table
->numAllocated
< howBig
)
221 ret
= (SecureProviderTable
*)HeapReAlloc(GetProcessHeap(), 0, table
,
222 sizeof(SecureProviderTable
) +
223 (howBig
- 1) * sizeof(SecureProvider
));
226 ret
->numAllocated
= howBig
;
235 DWORD numAllocated
= (howBig
> 1 ? howBig
: 1);
237 ret
= (SecureProviderTable
*)HeapAlloc(GetProcessHeap(), 0,
238 sizeof(SecureProviderTable
) +
239 (numAllocated
- 1) * sizeof(SecureProvider
));
242 ret
->numAllocated
= numAllocated
;
243 ret
->numProviders
= 0;
246 LeaveCriticalSection(&cs
);
250 PWSTR
SECUR32_strdupW(PCWSTR str
)
256 ret
= (PWSTR
)SECUR32_ALLOC((lstrlenW(str
) + 1) * sizeof(WCHAR
));
265 PWSTR
SECUR32_AllocWideFromMultiByte(PCSTR str
)
271 int charsNeeded
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
275 ret
= (PWSTR
)SECUR32_ALLOC(charsNeeded
* sizeof(WCHAR
));
277 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, charsNeeded
);
287 PSTR
SECUR32_AllocMultiByteFromWide(PCWSTR str
)
293 int charsNeeded
= WideCharToMultiByte(CP_ACP
, 0, str
, -1, NULL
, 0,
298 ret
= (PSTR
)SECUR32_ALLOC(charsNeeded
);
300 WideCharToMultiByte(CP_ACP
, 0, str
, -1, ret
, charsNeeded
,
311 static void _makeFnTableA(PSecurityFunctionTableA fnTableA
,
312 const PSecurityFunctionTableA inFnTableA
,
313 const PSecurityFunctionTableW inFnTableW
)
319 /* The size of the version 1 table is based on platform sdk's
320 * sspi.h, though the sample ssp also provided with platform sdk
321 * implies only functions through QuerySecurityPackageInfoA are
322 * implemented (yikes)
324 size_t tableSize
= inFnTableA
->dwVersion
== 1 ?
325 (LPBYTE
)&inFnTableA
->SetContextAttributesA
-
326 (LPBYTE
)inFnTableA
: sizeof(SecurityFunctionTableA
);
328 memcpy(fnTableA
, inFnTableA
, tableSize
);
329 /* override this, since we can do it internally anyway */
330 fnTableA
->QuerySecurityPackageInfoA
=
331 QuerySecurityPackageInfoA
;
335 /* functions with thunks */
336 if (inFnTableW
->AcquireCredentialsHandleW
)
337 fnTableA
->AcquireCredentialsHandleA
=
338 thunk_AcquireCredentialsHandleA
;
339 if (inFnTableW
->InitializeSecurityContextW
)
340 fnTableA
->InitializeSecurityContextA
=
341 thunk_InitializeSecurityContextA
;
342 if (inFnTableW
->ImportSecurityContextW
)
343 fnTableA
->ImportSecurityContextA
=
344 thunk_ImportSecurityContextA
;
345 if (inFnTableW
->AddCredentialsW
)
346 fnTableA
->AddCredentialsA
=
347 thunk_AddCredentialsA
;
348 if (inFnTableW
->QueryCredentialsAttributesW
)
349 fnTableA
->QueryCredentialsAttributesA
=
350 thunk_QueryCredentialsAttributesA
;
351 if (inFnTableW
->QueryContextAttributesW
)
352 fnTableA
->QueryContextAttributesA
=
353 thunk_QueryContextAttributesA
;
354 if (inFnTableW
->SetContextAttributesW
)
355 fnTableA
->SetContextAttributesA
=
356 thunk_SetContextAttributesA
;
357 /* this can't be thunked, there's no extra param to know which
358 * package to forward to */
359 fnTableA
->EnumerateSecurityPackagesA
= NULL
;
360 /* functions with no thunks needed */
361 fnTableA
->AcceptSecurityContext
= inFnTableW
->AcceptSecurityContext
;
362 fnTableA
->CompleteAuthToken
= inFnTableW
->CompleteAuthToken
;
363 fnTableA
->DeleteSecurityContext
= inFnTableW
->DeleteSecurityContext
;
364 fnTableA
->ImpersonateSecurityContext
=
365 inFnTableW
->ImpersonateSecurityContext
;
366 fnTableA
->RevertSecurityContext
= inFnTableW
->RevertSecurityContext
;
367 fnTableA
->MakeSignature
= inFnTableW
->MakeSignature
;
368 fnTableA
->VerifySignature
= inFnTableW
->VerifySignature
;
369 fnTableA
->FreeContextBuffer
= inFnTableW
->FreeContextBuffer
;
370 fnTableA
->QuerySecurityPackageInfoA
=
371 QuerySecurityPackageInfoA
;
372 fnTableA
->ExportSecurityContext
=
373 inFnTableW
->ExportSecurityContext
;
374 fnTableA
->QuerySecurityContextToken
=
375 inFnTableW
->QuerySecurityContextToken
;
376 fnTableA
->EncryptMessage
= inFnTableW
->EncryptMessage
;
377 fnTableA
->DecryptMessage
= inFnTableW
->DecryptMessage
;
382 static void _makeFnTableW(PSecurityFunctionTableW fnTableW
,
383 const PSecurityFunctionTableA inFnTableA
,
384 const PSecurityFunctionTableW inFnTableW
)
390 /* The size of the version 1 table is based on platform sdk's
391 * sspi.h, though the sample ssp also provided with platform sdk
392 * implies only functions through QuerySecurityPackageInfoA are
393 * implemented (yikes)
395 size_t tableSize
= inFnTableW
->dwVersion
== 1 ?
396 (LPBYTE
)&inFnTableW
->SetContextAttributesW
-
397 (LPBYTE
)inFnTableW
: sizeof(SecurityFunctionTableW
);
399 memcpy(fnTableW
, inFnTableW
, tableSize
);
400 /* override this, since we can do it internally anyway */
401 fnTableW
->QuerySecurityPackageInfoW
=
402 QuerySecurityPackageInfoW
;
406 /* functions with thunks */
407 if (inFnTableA
->AcquireCredentialsHandleA
)
408 fnTableW
->AcquireCredentialsHandleW
=
409 thunk_AcquireCredentialsHandleW
;
410 if (inFnTableA
->InitializeSecurityContextA
)
411 fnTableW
->InitializeSecurityContextW
=
412 thunk_InitializeSecurityContextW
;
413 if (inFnTableA
->ImportSecurityContextA
)
414 fnTableW
->ImportSecurityContextW
=
415 thunk_ImportSecurityContextW
;
416 if (inFnTableA
->AddCredentialsA
)
417 fnTableW
->AddCredentialsW
=
418 thunk_AddCredentialsW
;
419 if (inFnTableA
->QueryCredentialsAttributesA
)
420 fnTableW
->QueryCredentialsAttributesW
=
421 thunk_QueryCredentialsAttributesW
;
422 if (inFnTableA
->QueryContextAttributesA
)
423 fnTableW
->QueryContextAttributesW
=
424 thunk_QueryContextAttributesW
;
425 if (inFnTableA
->SetContextAttributesA
)
426 fnTableW
->SetContextAttributesW
=
427 thunk_SetContextAttributesW
;
428 /* this can't be thunked, there's no extra param to know which
429 * package to forward to */
430 fnTableW
->EnumerateSecurityPackagesW
= NULL
;
431 /* functions with no thunks needed */
432 fnTableW
->AcceptSecurityContext
= inFnTableA
->AcceptSecurityContext
;
433 fnTableW
->CompleteAuthToken
= inFnTableA
->CompleteAuthToken
;
434 fnTableW
->DeleteSecurityContext
= inFnTableA
->DeleteSecurityContext
;
435 fnTableW
->ImpersonateSecurityContext
=
436 inFnTableA
->ImpersonateSecurityContext
;
437 fnTableW
->RevertSecurityContext
= inFnTableA
->RevertSecurityContext
;
438 fnTableW
->MakeSignature
= inFnTableA
->MakeSignature
;
439 fnTableW
->VerifySignature
= inFnTableA
->VerifySignature
;
440 fnTableW
->FreeContextBuffer
= inFnTableA
->FreeContextBuffer
;
441 fnTableW
->QuerySecurityPackageInfoW
=
442 QuerySecurityPackageInfoW
;
443 fnTableW
->ExportSecurityContext
=
444 inFnTableA
->ExportSecurityContext
;
445 fnTableW
->QuerySecurityContextToken
=
446 inFnTableA
->QuerySecurityContextToken
;
447 fnTableW
->EncryptMessage
= inFnTableA
->EncryptMessage
;
448 fnTableW
->DecryptMessage
= inFnTableA
->DecryptMessage
;
453 static void _copyPackageInfo(PSecPkgInfoW info
, PSecPkgInfoA inInfoA
,
454 PSecPkgInfoW inInfoW
)
456 if (info
&& (inInfoA
|| inInfoW
))
458 /* odd, I know, but up until Name and Comment the structures are
461 memcpy(info
, inInfoW
? inInfoW
: (PSecPkgInfoW
)inInfoA
, sizeof(*info
));
464 info
->Name
= SECUR32_strdupW(inInfoW
->Name
);
465 info
->Comment
= SECUR32_strdupW(inInfoW
->Comment
);
469 info
->Name
= SECUR32_AllocWideFromMultiByte(inInfoA
->Name
);
470 info
->Comment
= SECUR32_AllocWideFromMultiByte(inInfoA
->Comment
);
475 static void _tryLoadProvider(PWSTR moduleName
)
477 HMODULE lib
= LoadLibraryW(moduleName
);
481 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
482 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(lib
,
483 SECURITY_ENTRYPOINT_ANSIW
);
484 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
485 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(lib
,
486 SECURITY_ENTRYPOINT_ANSIA
);
488 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
489 debugstr_w(moduleName
), pInitSecurityInterfaceA
,
490 pInitSecurityInterfaceW
);
491 if (pInitSecurityInterfaceW
|| pInitSecurityInterfaceA
)
493 PSecurityFunctionTableA fnTableA
= NULL
;
494 PSecurityFunctionTableW fnTableW
= NULL
;
496 PSecPkgInfoA infoA
= NULL
;
497 PSecPkgInfoW infoW
= NULL
;
498 SECURITY_STATUS ret
= SEC_E_OK
;
500 if (pInitSecurityInterfaceA
)
501 fnTableA
= pInitSecurityInterfaceA();
502 if (pInitSecurityInterfaceW
)
503 fnTableW
= pInitSecurityInterfaceW();
504 if (fnTableW
&& fnTableW
->EnumerateSecurityPackagesW
)
505 ret
= fnTableW
->EnumerateSecurityPackagesW(&toAdd
, &infoW
);
506 else if (fnTableA
&& fnTableA
->EnumerateSecurityPackagesA
)
507 ret
= fnTableA
->EnumerateSecurityPackagesA(&toAdd
, &infoA
);
508 if (ret
== SEC_E_OK
&& toAdd
> 0 && (infoW
|| infoA
))
510 providerTable
= _resizeProviderTable(providerTable
,
511 providerTable
? providerTable
->numProviders
+ 1 : 1);
512 packageTable
= _resizePackageTable(packageTable
,
513 packageTable
? packageTable
->numPackages
+ toAdd
: toAdd
);
514 if (providerTable
&& packageTable
)
517 SecureProvider
*provider
=
518 &providerTable
->table
[providerTable
->numProviders
];
520 EnterCriticalSection(&cs
);
521 provider
->moduleName
= SECUR32_strdupW(moduleName
);
522 provider
->lib
= NULL
;
523 for (i
= 0; i
< toAdd
; i
++)
525 SecurePackage
*package
=
526 &packageTable
->table
[packageTable
->numPackages
+ i
];
528 package
->provider
= provider
;
529 _copyPackageInfo(&package
->infoW
,
530 infoA
? &infoA
[i
] : NULL
,
531 infoW
? &infoW
[i
] : NULL
);
533 packageTable
->numPackages
+= toAdd
;
534 providerTable
->numProviders
++;
535 LeaveCriticalSection(&cs
);
538 fnTableW
->FreeContextBuffer(infoW
);
540 fnTableA
->FreeContextBuffer(infoA
);
546 WARN("failed to load %s\n", debugstr_w(moduleName
));
549 static WCHAR securityProvidersKeyW
[] = {
550 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
551 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
552 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
554 static const WCHAR securityProvidersW
[] = {
555 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
558 static void SECUR32_initializeProviders(void)
564 InitializeCriticalSection(&cs
);
565 apiRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, securityProvidersKeyW
, 0,
567 if (apiRet
== ERROR_SUCCESS
)
569 WCHAR securityPkgNames
[MAX_PATH
]; /* arbitrary len */
570 DWORD size
= sizeof(securityPkgNames
) / sizeof(WCHAR
), type
;
572 apiRet
= RegQueryValueExW(key
, securityProvidersW
, NULL
, &type
,
573 (PBYTE
)securityPkgNames
, &size
);
574 if (apiRet
== ERROR_SUCCESS
&& type
== REG_SZ
)
578 for (ptr
= securityPkgNames
;
579 ptr
< (PWSTR
)((PBYTE
)securityPkgNames
+ size
); )
583 for (comma
= ptr
; *comma
&& *comma
!= ','; comma
++)
587 for (; *ptr
&& isspace(*ptr
) && ptr
< securityPkgNames
+ size
;
591 _tryLoadProvider(ptr
);
592 ptr
+= lstrlenW(ptr
) + 1;
599 SecurePackage
*SECUR32_findPackageW(PWSTR packageName
)
603 if (packageTable
&& packageName
)
607 for (i
= 0, ret
= NULL
; !ret
&& i
< packageTable
->numPackages
; i
++)
608 if (!lstrcmpiW(packageTable
->table
[i
].infoW
.Name
, packageName
))
609 ret
= &packageTable
->table
[i
];
610 if (ret
&& ret
->provider
&& !ret
->provider
->lib
)
612 ret
->provider
->lib
= LoadLibraryW(ret
->provider
->moduleName
);
613 if (ret
->provider
->lib
)
615 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
616 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(ret
->provider
->lib
,
617 SECURITY_ENTRYPOINT_ANSIW
);
618 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
619 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(ret
->provider
->lib
,
620 SECURITY_ENTRYPOINT_ANSIA
);
621 PSecurityFunctionTableA fnTableA
= NULL
;
622 PSecurityFunctionTableW fnTableW
= NULL
;
624 if (pInitSecurityInterfaceA
)
625 fnTableA
= pInitSecurityInterfaceA();
626 if (pInitSecurityInterfaceW
)
627 fnTableW
= pInitSecurityInterfaceW();
628 _makeFnTableA(&ret
->provider
->fnTableA
, fnTableA
, fnTableW
);
629 _makeFnTableW(&ret
->provider
->fnTableW
, fnTableA
, fnTableW
);
640 SecurePackage
*SECUR32_findPackageA(PSTR packageName
)
644 if (packageTable
&& packageName
)
646 UNICODE_STRING package
;
648 RtlCreateUnicodeStringFromAsciiz(&package
, packageName
);
649 ret
= SECUR32_findPackageW(package
.Buffer
);
650 RtlFreeUnicodeString(&package
);
657 static void SECUR32_freeProviders(void)
662 EnterCriticalSection(&cs
);
665 for (i
= 0; i
< packageTable
->numPackages
; i
++)
667 SECUR32_FREE(packageTable
->table
[i
].infoW
.Name
);
668 SECUR32_FREE(packageTable
->table
[i
].infoW
.Comment
);
670 HeapFree(GetProcessHeap(), 0, packageTable
);
675 for (i
= 0; i
< providerTable
->numProviders
; i
++)
677 if (providerTable
->table
[i
].moduleName
)
678 SECUR32_FREE(providerTable
->table
[i
].moduleName
);
679 if (providerTable
->table
[i
].lib
)
680 FreeLibrary(providerTable
->table
[i
].lib
);
682 HeapFree(GetProcessHeap(), 0, providerTable
);
683 providerTable
= NULL
;
685 LeaveCriticalSection(&cs
);
686 DeleteCriticalSection(&cs
);
689 /* Doh--if pv was allocated by a crypto package, this may not be correct.
690 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
691 * be any guarantee, nor is there an alloc function in secur32.
693 SECURITY_STATUS SEC_ENTRY
FreeContextBuffer(PVOID pv
)
697 /* as it turns out, SECURITY_STATUSes are actually HRESULTS */
700 if (SECUR32_FREE(pv
) == NULL
)
703 ret
= HRESULT_FROM_WIN32(GetLastError());
706 ret
= HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
);
710 SECURITY_STATUS SEC_ENTRY
EnumerateSecurityPackagesW(PULONG pcPackages
,
711 PSecPkgInfoW
*ppPackageInfo
)
713 SECURITY_STATUS ret
= SEC_E_OK
;
715 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
717 EnterCriticalSection(&cs
);
723 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
724 for (i
= 0; i
< packageTable
->numPackages
; i
++)
726 if (packageTable
->table
[i
].infoW
.Name
)
728 (lstrlenW(packageTable
->table
[i
].infoW
.Name
) + 1) *
730 if (packageTable
->table
[i
].infoW
.Comment
)
732 (lstrlenW(packageTable
->table
[i
].infoW
.Comment
) + 1) *
737 *ppPackageInfo
= (PSecPkgInfoW
)SECUR32_ALLOC(bytesNeeded
);
742 *pcPackages
= packageTable
->numPackages
;
743 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
744 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
745 for (i
= 0; i
< packageTable
->numPackages
; i
++)
747 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
;
749 memcpy(pkgInfo
, &packageTable
->table
[i
].infoW
,
750 sizeof(SecPkgInfoW
));
751 if (packageTable
->table
[i
].infoW
.Name
)
753 pkgInfo
->Name
= nextString
;
754 lstrcpyW(nextString
, packageTable
->table
[i
].infoW
.Name
);
755 nextString
+= lstrlenW(nextString
) + 1;
758 pkgInfo
->Name
= NULL
;
759 if (packageTable
->table
[i
].infoW
.Comment
)
761 pkgInfo
->Comment
= nextString
;
763 packageTable
->table
[i
].infoW
.Comment
);
764 nextString
+= lstrlenW(nextString
) + 1;
767 pkgInfo
->Comment
= NULL
;
771 ret
= SEC_E_INSUFFICIENT_MEMORY
;
774 LeaveCriticalSection(&cs
);
778 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
779 * structures) into an array of SecPkgInfoA structures, which it returns.
781 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
782 const PSecPkgInfoW info
)
788 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
791 for (i
= 0; i
< cPackages
; i
++)
794 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
795 -1, NULL
, 0, NULL
, NULL
);
797 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
798 -1, NULL
, 0, NULL
, NULL
);
800 ret
= (PSecPkgInfoA
)SECUR32_ALLOC(bytesNeeded
);
805 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
806 for (i
= 0; i
< cPackages
; i
++)
808 PSecPkgInfoA pkgInfo
= ret
+ i
;
811 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
814 pkgInfo
->Name
= nextString
;
815 /* just repeat back to WideCharToMultiByte how many bytes
816 * it requires, since we asked it earlier
818 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
819 NULL
, 0, NULL
, NULL
);
820 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
821 pkgInfo
->Name
, bytes
, NULL
, NULL
);
822 nextString
+= lstrlenA(nextString
) + 1;
825 pkgInfo
->Name
= NULL
;
828 pkgInfo
->Comment
= nextString
;
829 /* just repeat back to WideCharToMultiByte how many bytes
830 * it requires, since we asked it earlier
832 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
833 NULL
, 0, NULL
, NULL
);
834 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
835 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
836 nextString
+= lstrlenA(nextString
) + 1;
839 pkgInfo
->Comment
= NULL
;
848 SECURITY_STATUS SEC_ENTRY
EnumerateSecurityPackagesA(PULONG pcPackages
,
849 PSecPkgInfoA
*ppPackageInfo
)
854 ret
= EnumerateSecurityPackagesW(pcPackages
, &info
);
855 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
857 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
858 if (*pcPackages
&& !*ppPackageInfo
)
861 ret
= SEC_E_INSUFFICIENT_MEMORY
;
863 FreeContextBuffer(info
);
868 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
870 if (fdwReason
== DLL_PROCESS_ATTACH
)
872 DisableThreadLibraryCalls(hinstDLL
);
873 SECUR32_initializeProviders();
875 else if (fdwReason
== DLL_PROCESS_DETACH
)
877 SECUR32_freeProviders();