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"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(secur32
);
39 typedef struct _SecurePackageTable
43 SecurePackage table
[1];
46 typedef struct _SecureProviderTable
50 SecureProvider table
[1];
51 } SecureProviderTable
;
57 /* Makes sure table has space for at least howBig entries. If table is NULL,
58 * returns a newly allocated table. Otherwise returns the address of the
59 * modified table, which may not be the same was when called.
61 static SecurePackageTable
*_resizePackageTable(SecurePackageTable
*table
,
64 /* Makes sure table has space for at least howBig entries. If table is NULL,
65 * returns a newly allocated table. Otherwise returns the address of the
66 * modified table, which may not be the same was when called.
68 static SecureProviderTable
*_resizeProviderTable(SecureProviderTable
*table
,
71 /* Tries to load moduleName as a provider. If successful, enumerates what
72 * packages it can and adds them to the package and provider tables. Resizes
73 * tables as necessary.
75 static void _tryLoadProvider(PWSTR moduleName
);
77 /* Initialization: read securityproviders value and attempt to open each dll
78 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
79 * Two undocumented functions, AddSecurityPackage(A/W) and
80 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
81 * unregister a dll, but I'm not sure.
83 static void SECUR32_initializeProviders(void);
85 /* Frees all loaded packages and providers */
86 static void SECUR32_freeProviders(void);
92 static CRITICAL_SECTION cs
;
93 static SecurePackageTable
*packageTable
= NULL
;
94 static SecureProviderTable
*providerTable
= NULL
;
96 static SecurityFunctionTableA securityFunctionTableA
= {
97 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2
,
98 EnumerateSecurityPackagesA
,
99 QueryCredentialsAttributesA
,
100 AcquireCredentialsHandleA
,
101 FreeCredentialsHandle
,
102 NULL
, /* Reserved2 */
103 InitializeSecurityContextA
,
104 AcceptSecurityContext
,
106 DeleteSecurityContext
,
108 QueryContextAttributesA
,
109 ImpersonateSecurityContext
,
110 RevertSecurityContext
,
114 QuerySecurityPackageInfoA
,
115 NULL
, /* Reserved3 */
116 NULL
, /* Reserved4 */
117 ExportSecurityContext
,
118 ImportSecurityContextA
,
120 NULL
, /* Reserved8 */
121 QuerySecurityContextToken
,
124 SetContextAttributesA
127 static SecurityFunctionTableW securityFunctionTableW
= {
128 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2
,
129 EnumerateSecurityPackagesW
,
130 QueryCredentialsAttributesW
,
131 AcquireCredentialsHandleW
,
132 FreeCredentialsHandle
,
133 NULL
, /* Reserved2 */
134 InitializeSecurityContextW
,
135 AcceptSecurityContext
,
137 DeleteSecurityContext
,
139 QueryContextAttributesW
,
140 ImpersonateSecurityContext
,
141 RevertSecurityContext
,
145 QuerySecurityPackageInfoW
,
146 NULL
, /* Reserved3 */
147 NULL
, /* Reserved4 */
148 ExportSecurityContext
,
149 ImportSecurityContextW
,
151 NULL
, /* Reserved8 */
152 QuerySecurityContextToken
,
155 SetContextAttributesW
158 /***********************************************************************
159 * InitSecurityInterfaceA (SECUR32.@)
161 PSecurityFunctionTableA WINAPI
InitSecurityInterfaceA(void)
163 return &securityFunctionTableA
;
166 /***********************************************************************
167 * InitSecurityInterfaceW (SECUR32.@)
169 PSecurityFunctionTableW WINAPI
InitSecurityInterfaceW(void)
171 return &securityFunctionTableW
;
174 /* Allocates or resizes table to have space for at least howBig packages.
175 * Uses Heap functions, because needs to be able to reallocate.
177 static SecurePackageTable
*_resizePackageTable(SecurePackageTable
*table
,
180 SecurePackageTable
*ret
;
182 EnterCriticalSection(&cs
);
185 if (table
->numAllocated
< howBig
)
187 ret
= (SecurePackageTable
*)HeapReAlloc(GetProcessHeap(), 0, table
,
188 sizeof(SecurePackageTable
) + (howBig
- 1) * sizeof(SecurePackage
));
191 ret
->numAllocated
= howBig
;
200 DWORD numAllocated
= (howBig
> 1 ? howBig
: 1);
202 ret
= (SecurePackageTable
*)HeapAlloc(GetProcessHeap(), 0,
203 sizeof(SecurePackageTable
) +
204 (numAllocated
- 1) * sizeof(SecurePackage
));
207 ret
->numAllocated
= numAllocated
;
208 ret
->numPackages
= 0;
211 LeaveCriticalSection(&cs
);
215 /* Allocates or resizes table to have space for at least howBig providers.
216 * Uses Heap functions, because needs to be able to reallocate.
218 static SecureProviderTable
*_resizeProviderTable(SecureProviderTable
*table
,
221 SecureProviderTable
*ret
;
223 EnterCriticalSection(&cs
);
226 if (table
->numAllocated
< howBig
)
228 ret
= (SecureProviderTable
*)HeapReAlloc(GetProcessHeap(), 0, table
,
229 sizeof(SecureProviderTable
) +
230 (howBig
- 1) * sizeof(SecureProvider
));
233 ret
->numAllocated
= howBig
;
242 DWORD numAllocated
= (howBig
> 1 ? howBig
: 1);
244 ret
= (SecureProviderTable
*)HeapAlloc(GetProcessHeap(), 0,
245 sizeof(SecureProviderTable
) +
246 (numAllocated
- 1) * sizeof(SecureProvider
));
249 ret
->numAllocated
= numAllocated
;
250 ret
->numProviders
= 0;
253 LeaveCriticalSection(&cs
);
257 PWSTR
SECUR32_strdupW(PCWSTR str
)
263 ret
= (PWSTR
)SECUR32_ALLOC((lstrlenW(str
) + 1) * sizeof(WCHAR
));
272 PWSTR
SECUR32_AllocWideFromMultiByte(PCSTR str
)
278 int charsNeeded
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
282 ret
= (PWSTR
)SECUR32_ALLOC(charsNeeded
* sizeof(WCHAR
));
284 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, charsNeeded
);
294 PSTR
SECUR32_AllocMultiByteFromWide(PCWSTR str
)
300 int charsNeeded
= WideCharToMultiByte(CP_ACP
, 0, str
, -1, NULL
, 0,
305 ret
= (PSTR
)SECUR32_ALLOC(charsNeeded
);
307 WideCharToMultiByte(CP_ACP
, 0, str
, -1, ret
, charsNeeded
,
318 static void _makeFnTableA(PSecurityFunctionTableA fnTableA
,
319 const PSecurityFunctionTableA inFnTableA
,
320 const PSecurityFunctionTableW inFnTableW
)
326 /* The size of the version 1 table is based on platform sdk's
327 * sspi.h, though the sample ssp also provided with platform sdk
328 * implies only functions through QuerySecurityPackageInfoA are
329 * implemented (yikes)
331 size_t tableSize
= inFnTableA
->dwVersion
== 1 ?
332 (LPBYTE
)&inFnTableA
->SetContextAttributesA
-
333 (LPBYTE
)inFnTableA
: sizeof(SecurityFunctionTableA
);
335 memcpy(fnTableA
, inFnTableA
, tableSize
);
336 /* override this, since we can do it internally anyway */
337 fnTableA
->QuerySecurityPackageInfoA
=
338 QuerySecurityPackageInfoA
;
342 /* functions with thunks */
343 if (inFnTableW
->AcquireCredentialsHandleW
)
344 fnTableA
->AcquireCredentialsHandleA
=
345 thunk_AcquireCredentialsHandleA
;
346 if (inFnTableW
->InitializeSecurityContextW
)
347 fnTableA
->InitializeSecurityContextA
=
348 thunk_InitializeSecurityContextA
;
349 if (inFnTableW
->ImportSecurityContextW
)
350 fnTableA
->ImportSecurityContextA
=
351 thunk_ImportSecurityContextA
;
352 if (inFnTableW
->AddCredentialsW
)
353 fnTableA
->AddCredentialsA
=
354 thunk_AddCredentialsA
;
355 if (inFnTableW
->QueryCredentialsAttributesW
)
356 fnTableA
->QueryCredentialsAttributesA
=
357 thunk_QueryCredentialsAttributesA
;
358 if (inFnTableW
->QueryContextAttributesW
)
359 fnTableA
->QueryContextAttributesA
=
360 thunk_QueryContextAttributesA
;
361 if (inFnTableW
->SetContextAttributesW
)
362 fnTableA
->SetContextAttributesA
=
363 thunk_SetContextAttributesA
;
364 /* this can't be thunked, there's no extra param to know which
365 * package to forward to */
366 fnTableA
->EnumerateSecurityPackagesA
= NULL
;
367 /* functions with no thunks needed */
368 fnTableA
->AcceptSecurityContext
= inFnTableW
->AcceptSecurityContext
;
369 fnTableA
->CompleteAuthToken
= inFnTableW
->CompleteAuthToken
;
370 fnTableA
->DeleteSecurityContext
= inFnTableW
->DeleteSecurityContext
;
371 fnTableA
->ImpersonateSecurityContext
=
372 inFnTableW
->ImpersonateSecurityContext
;
373 fnTableA
->RevertSecurityContext
= inFnTableW
->RevertSecurityContext
;
374 fnTableA
->MakeSignature
= inFnTableW
->MakeSignature
;
375 fnTableA
->VerifySignature
= inFnTableW
->VerifySignature
;
376 fnTableA
->FreeContextBuffer
= inFnTableW
->FreeContextBuffer
;
377 fnTableA
->QuerySecurityPackageInfoA
=
378 QuerySecurityPackageInfoA
;
379 fnTableA
->ExportSecurityContext
=
380 inFnTableW
->ExportSecurityContext
;
381 fnTableA
->QuerySecurityContextToken
=
382 inFnTableW
->QuerySecurityContextToken
;
383 fnTableA
->EncryptMessage
= inFnTableW
->EncryptMessage
;
384 fnTableA
->DecryptMessage
= inFnTableW
->DecryptMessage
;
389 static void _makeFnTableW(PSecurityFunctionTableW fnTableW
,
390 const PSecurityFunctionTableA inFnTableA
,
391 const PSecurityFunctionTableW inFnTableW
)
397 /* The size of the version 1 table is based on platform sdk's
398 * sspi.h, though the sample ssp also provided with platform sdk
399 * implies only functions through QuerySecurityPackageInfoA are
400 * implemented (yikes)
402 size_t tableSize
= inFnTableW
->dwVersion
== 1 ?
403 (LPBYTE
)&inFnTableW
->SetContextAttributesW
-
404 (LPBYTE
)inFnTableW
: sizeof(SecurityFunctionTableW
);
406 memcpy(fnTableW
, inFnTableW
, tableSize
);
407 /* override this, since we can do it internally anyway */
408 fnTableW
->QuerySecurityPackageInfoW
=
409 QuerySecurityPackageInfoW
;
413 /* functions with thunks */
414 if (inFnTableA
->AcquireCredentialsHandleA
)
415 fnTableW
->AcquireCredentialsHandleW
=
416 thunk_AcquireCredentialsHandleW
;
417 if (inFnTableA
->InitializeSecurityContextA
)
418 fnTableW
->InitializeSecurityContextW
=
419 thunk_InitializeSecurityContextW
;
420 if (inFnTableA
->ImportSecurityContextA
)
421 fnTableW
->ImportSecurityContextW
=
422 thunk_ImportSecurityContextW
;
423 if (inFnTableA
->AddCredentialsA
)
424 fnTableW
->AddCredentialsW
=
425 thunk_AddCredentialsW
;
426 if (inFnTableA
->QueryCredentialsAttributesA
)
427 fnTableW
->QueryCredentialsAttributesW
=
428 thunk_QueryCredentialsAttributesW
;
429 if (inFnTableA
->QueryContextAttributesA
)
430 fnTableW
->QueryContextAttributesW
=
431 thunk_QueryContextAttributesW
;
432 if (inFnTableA
->SetContextAttributesA
)
433 fnTableW
->SetContextAttributesW
=
434 thunk_SetContextAttributesW
;
435 /* this can't be thunked, there's no extra param to know which
436 * package to forward to */
437 fnTableW
->EnumerateSecurityPackagesW
= NULL
;
438 /* functions with no thunks needed */
439 fnTableW
->AcceptSecurityContext
= inFnTableA
->AcceptSecurityContext
;
440 fnTableW
->CompleteAuthToken
= inFnTableA
->CompleteAuthToken
;
441 fnTableW
->DeleteSecurityContext
= inFnTableA
->DeleteSecurityContext
;
442 fnTableW
->ImpersonateSecurityContext
=
443 inFnTableA
->ImpersonateSecurityContext
;
444 fnTableW
->RevertSecurityContext
= inFnTableA
->RevertSecurityContext
;
445 fnTableW
->MakeSignature
= inFnTableA
->MakeSignature
;
446 fnTableW
->VerifySignature
= inFnTableA
->VerifySignature
;
447 fnTableW
->FreeContextBuffer
= inFnTableA
->FreeContextBuffer
;
448 fnTableW
->QuerySecurityPackageInfoW
=
449 QuerySecurityPackageInfoW
;
450 fnTableW
->ExportSecurityContext
=
451 inFnTableA
->ExportSecurityContext
;
452 fnTableW
->QuerySecurityContextToken
=
453 inFnTableA
->QuerySecurityContextToken
;
454 fnTableW
->EncryptMessage
= inFnTableA
->EncryptMessage
;
455 fnTableW
->DecryptMessage
= inFnTableA
->DecryptMessage
;
460 static void _copyPackageInfo(PSecPkgInfoW info
, PSecPkgInfoA inInfoA
,
461 PSecPkgInfoW inInfoW
)
463 if (info
&& (inInfoA
|| inInfoW
))
465 /* odd, I know, but up until Name and Comment the structures are
468 memcpy(info
, inInfoW
? inInfoW
: (PSecPkgInfoW
)inInfoA
, sizeof(*info
));
471 info
->Name
= SECUR32_strdupW(inInfoW
->Name
);
472 info
->Comment
= SECUR32_strdupW(inInfoW
->Comment
);
476 info
->Name
= SECUR32_AllocWideFromMultiByte(inInfoA
->Name
);
477 info
->Comment
= SECUR32_AllocWideFromMultiByte(inInfoA
->Comment
);
482 static void _tryLoadProvider(PWSTR moduleName
)
484 HMODULE lib
= LoadLibraryW(moduleName
);
488 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
489 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(lib
,
490 SECURITY_ENTRYPOINT_ANSIW
);
491 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
492 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(lib
,
493 SECURITY_ENTRYPOINT_ANSIA
);
495 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
496 debugstr_w(moduleName
), pInitSecurityInterfaceA
,
497 pInitSecurityInterfaceW
);
498 if (pInitSecurityInterfaceW
|| pInitSecurityInterfaceA
)
500 PSecurityFunctionTableA fnTableA
= NULL
;
501 PSecurityFunctionTableW fnTableW
= NULL
;
503 PSecPkgInfoA infoA
= NULL
;
504 PSecPkgInfoW infoW
= NULL
;
505 SECURITY_STATUS ret
= SEC_E_OK
;
507 if (pInitSecurityInterfaceA
)
508 fnTableA
= pInitSecurityInterfaceA();
509 if (pInitSecurityInterfaceW
)
510 fnTableW
= pInitSecurityInterfaceW();
511 if (fnTableW
&& fnTableW
->EnumerateSecurityPackagesW
)
512 ret
= fnTableW
->EnumerateSecurityPackagesW(&toAdd
, &infoW
);
513 else if (fnTableA
&& fnTableA
->EnumerateSecurityPackagesA
)
514 ret
= fnTableA
->EnumerateSecurityPackagesA(&toAdd
, &infoA
);
515 if (ret
== SEC_E_OK
&& toAdd
> 0 && (infoW
|| infoA
))
517 providerTable
= _resizeProviderTable(providerTable
,
518 providerTable
? providerTable
->numProviders
+ 1 : 1);
519 packageTable
= _resizePackageTable(packageTable
,
520 packageTable
? packageTable
->numPackages
+ toAdd
: toAdd
);
521 if (providerTable
&& packageTable
)
524 SecureProvider
*provider
=
525 &providerTable
->table
[providerTable
->numProviders
];
527 EnterCriticalSection(&cs
);
528 provider
->moduleName
= SECUR32_strdupW(moduleName
);
529 provider
->lib
= NULL
;
530 for (i
= 0; i
< toAdd
; i
++)
532 SecurePackage
*package
=
533 &packageTable
->table
[packageTable
->numPackages
+ i
];
535 package
->provider
= provider
;
536 _copyPackageInfo(&package
->infoW
,
537 infoA
? &infoA
[i
] : NULL
,
538 infoW
? &infoW
[i
] : NULL
);
540 packageTable
->numPackages
+= toAdd
;
541 providerTable
->numProviders
++;
542 LeaveCriticalSection(&cs
);
545 fnTableW
->FreeContextBuffer(infoW
);
547 fnTableA
->FreeContextBuffer(infoA
);
553 WARN("failed to load %s\n", debugstr_w(moduleName
));
556 static const WCHAR securityProvidersKeyW
[] = {
557 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
558 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
559 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
561 static const WCHAR securityProvidersW
[] = {
562 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
565 static void SECUR32_initializeProviders(void)
571 InitializeCriticalSection(&cs
);
572 apiRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, securityProvidersKeyW
, 0,
574 if (apiRet
== ERROR_SUCCESS
)
576 WCHAR securityPkgNames
[MAX_PATH
]; /* arbitrary len */
577 DWORD size
= sizeof(securityPkgNames
) / sizeof(WCHAR
), type
;
579 apiRet
= RegQueryValueExW(key
, securityProvidersW
, NULL
, &type
,
580 (PBYTE
)securityPkgNames
, &size
);
581 if (apiRet
== ERROR_SUCCESS
&& type
== REG_SZ
)
585 for (ptr
= securityPkgNames
;
586 ptr
< (PWSTR
)((PBYTE
)securityPkgNames
+ size
); )
590 for (comma
= ptr
; *comma
&& *comma
!= ','; comma
++)
594 for (; *ptr
&& isspace(*ptr
) && ptr
< securityPkgNames
+ size
;
598 _tryLoadProvider(ptr
);
599 ptr
+= lstrlenW(ptr
) + 1;
606 SecurePackage
*SECUR32_findPackageW(PWSTR packageName
)
610 if (packageTable
&& packageName
)
614 for (i
= 0, ret
= NULL
; !ret
&& i
< packageTable
->numPackages
; i
++)
615 if (!lstrcmpiW(packageTable
->table
[i
].infoW
.Name
, packageName
))
616 ret
= &packageTable
->table
[i
];
617 if (ret
&& ret
->provider
&& !ret
->provider
->lib
)
619 ret
->provider
->lib
= LoadLibraryW(ret
->provider
->moduleName
);
620 if (ret
->provider
->lib
)
622 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
623 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(ret
->provider
->lib
,
624 SECURITY_ENTRYPOINT_ANSIW
);
625 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
626 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(ret
->provider
->lib
,
627 SECURITY_ENTRYPOINT_ANSIA
);
628 PSecurityFunctionTableA fnTableA
= NULL
;
629 PSecurityFunctionTableW fnTableW
= NULL
;
631 if (pInitSecurityInterfaceA
)
632 fnTableA
= pInitSecurityInterfaceA();
633 if (pInitSecurityInterfaceW
)
634 fnTableW
= pInitSecurityInterfaceW();
635 _makeFnTableA(&ret
->provider
->fnTableA
, fnTableA
, fnTableW
);
636 _makeFnTableW(&ret
->provider
->fnTableW
, fnTableA
, fnTableW
);
647 SecurePackage
*SECUR32_findPackageA(PSTR packageName
)
651 if (packageTable
&& packageName
)
653 UNICODE_STRING package
;
655 RtlCreateUnicodeStringFromAsciiz(&package
, packageName
);
656 ret
= SECUR32_findPackageW(package
.Buffer
);
657 RtlFreeUnicodeString(&package
);
664 static void SECUR32_freeProviders(void)
669 EnterCriticalSection(&cs
);
672 for (i
= 0; i
< packageTable
->numPackages
; i
++)
674 SECUR32_FREE(packageTable
->table
[i
].infoW
.Name
);
675 SECUR32_FREE(packageTable
->table
[i
].infoW
.Comment
);
677 HeapFree(GetProcessHeap(), 0, packageTable
);
682 for (i
= 0; i
< providerTable
->numProviders
; i
++)
684 if (providerTable
->table
[i
].moduleName
)
685 SECUR32_FREE(providerTable
->table
[i
].moduleName
);
686 if (providerTable
->table
[i
].lib
)
687 FreeLibrary(providerTable
->table
[i
].lib
);
689 HeapFree(GetProcessHeap(), 0, providerTable
);
690 providerTable
= NULL
;
692 LeaveCriticalSection(&cs
);
693 DeleteCriticalSection(&cs
);
696 /***********************************************************************
697 * FreeContextBuffer (SECUR32.@)
699 * Doh--if pv was allocated by a crypto package, this may not be correct.
700 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
701 * be any guarantee, nor is there an alloc function in secur32.
703 SECURITY_STATUS WINAPI
FreeContextBuffer(PVOID pv
)
707 /* as it turns out, SECURITY_STATUSes are actually HRESULTS */
710 if (SECUR32_FREE(pv
) == NULL
)
713 ret
= HRESULT_FROM_WIN32(GetLastError());
716 ret
= HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
);
720 /***********************************************************************
721 * EnumerateSecurityPackagesW (SECUR32.@)
723 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesW(PULONG pcPackages
,
724 PSecPkgInfoW
*ppPackageInfo
)
726 SECURITY_STATUS ret
= SEC_E_OK
;
728 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
730 EnterCriticalSection(&cs
);
736 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
737 for (i
= 0; i
< packageTable
->numPackages
; i
++)
739 if (packageTable
->table
[i
].infoW
.Name
)
741 (lstrlenW(packageTable
->table
[i
].infoW
.Name
) + 1) *
743 if (packageTable
->table
[i
].infoW
.Comment
)
745 (lstrlenW(packageTable
->table
[i
].infoW
.Comment
) + 1) *
750 *ppPackageInfo
= (PSecPkgInfoW
)SECUR32_ALLOC(bytesNeeded
);
755 *pcPackages
= packageTable
->numPackages
;
756 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
757 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
758 for (i
= 0; i
< packageTable
->numPackages
; i
++)
760 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
;
762 memcpy(pkgInfo
, &packageTable
->table
[i
].infoW
,
763 sizeof(SecPkgInfoW
));
764 if (packageTable
->table
[i
].infoW
.Name
)
766 pkgInfo
->Name
= nextString
;
767 lstrcpyW(nextString
, packageTable
->table
[i
].infoW
.Name
);
768 nextString
+= lstrlenW(nextString
) + 1;
771 pkgInfo
->Name
= NULL
;
772 if (packageTable
->table
[i
].infoW
.Comment
)
774 pkgInfo
->Comment
= nextString
;
776 packageTable
->table
[i
].infoW
.Comment
);
777 nextString
+= lstrlenW(nextString
) + 1;
780 pkgInfo
->Comment
= NULL
;
784 ret
= SEC_E_INSUFFICIENT_MEMORY
;
787 LeaveCriticalSection(&cs
);
791 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
792 * structures) into an array of SecPkgInfoA structures, which it returns.
794 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
795 const PSecPkgInfoW info
)
801 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
804 for (i
= 0; i
< cPackages
; i
++)
807 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
808 -1, NULL
, 0, NULL
, NULL
);
810 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
811 -1, NULL
, 0, NULL
, NULL
);
813 ret
= (PSecPkgInfoA
)SECUR32_ALLOC(bytesNeeded
);
818 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
819 for (i
= 0; i
< cPackages
; i
++)
821 PSecPkgInfoA pkgInfo
= ret
+ i
;
824 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
827 pkgInfo
->Name
= nextString
;
828 /* just repeat back to WideCharToMultiByte how many bytes
829 * it requires, since we asked it earlier
831 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
832 NULL
, 0, NULL
, NULL
);
833 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
834 pkgInfo
->Name
, bytes
, NULL
, NULL
);
835 nextString
+= lstrlenA(nextString
) + 1;
838 pkgInfo
->Name
= NULL
;
841 pkgInfo
->Comment
= nextString
;
842 /* just repeat back to WideCharToMultiByte how many bytes
843 * it requires, since we asked it earlier
845 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
846 NULL
, 0, NULL
, NULL
);
847 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
848 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
849 nextString
+= lstrlenA(nextString
) + 1;
852 pkgInfo
->Comment
= NULL
;
861 /***********************************************************************
862 * EnumerateSecurityPackagesA (SECUR32.@)
864 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesA(PULONG pcPackages
,
865 PSecPkgInfoA
*ppPackageInfo
)
870 ret
= EnumerateSecurityPackagesW(pcPackages
, &info
);
871 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
873 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
874 if (*pcPackages
&& !*ppPackageInfo
)
877 ret
= SEC_E_INSUFFICIENT_MEMORY
;
879 FreeContextBuffer(info
);
884 /***********************************************************************
885 * GetComputerObjectNameA (SECUR32.@)
887 BOOLEAN WINAPI
GetComputerObjectNameA(
888 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
890 FIXME("%d %p %p\n", NameFormat
, lpNameBuffer
, nSize
);
894 /***********************************************************************
895 * GetComputerObjectNameW (SECUR32.@)
897 BOOLEAN WINAPI
GetComputerObjectNameW(
898 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
900 FIXME("%d %p %p\n", NameFormat
, lpNameBuffer
, nSize
);
904 /***********************************************************************
905 * DllMain (SECUR32.0)
907 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
909 if (fdwReason
== DLL_PROCESS_ATTACH
)
911 DisableThreadLibraryCalls(hinstDLL
);
912 SECUR32_initializeProviders();
914 else if (fdwReason
== DLL_PROCESS_DETACH
)
916 SECUR32_freeProviders();