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
28 #include "secur32_priv.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
40 typedef struct _SecurePackageTable
44 SecurePackage table[1];
47 typedef struct _SecureProviderTable
51 SecureProvider table[1];
52 } SecureProviderTable;
58 /* Makes sure table has space for at least howBig entries. If table is NULL,
59 * returns a newly allocated table. Otherwise returns the address of the
60 * modified table, which may not be the same was when called.
62 static SecurePackageTable *_resizePackageTable(SecurePackageTable *table,
65 /* Makes sure table has space for at least howBig entries. If table is NULL,
66 * returns a newly allocated table. Otherwise returns the address of the
67 * modified table, which may not be the same was when called.
69 static SecureProviderTable *_resizeProviderTable(SecureProviderTable *table,
72 /* Tries to load moduleName as a provider. If successful, enumerates what
73 * packages it can and adds them to the package and provider tables. Resizes
74 * tables as necessary.
76 static void _tryLoadProvider(PWSTR moduleName);
78 /* Initialization: read securityproviders value and attempt to open each dll
79 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
80 * Two undocumented functions, AddSecurityPackage(A/W) and
81 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
82 * unregister a dll, but I'm not sure.
84 static void SECUR32_initializeProviders(void);
86 /* Frees all loaded packages and providers */
87 static void SECUR32_freeProviders(void);
93 static CRITICAL_SECTION cs;
94 static SecurePackageTable *packageTable = NULL;
95 static SecureProviderTable *providerTable = NULL;
97 static SecurityFunctionTableA securityFunctionTableA = {
98 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2,
99 EnumerateSecurityPackagesA,
100 QueryCredentialsAttributesA,
101 AcquireCredentialsHandleA,
102 FreeCredentialsHandle,
103 NULL, /* Reserved2 */
104 InitializeSecurityContextA,
105 AcceptSecurityContext,
107 DeleteSecurityContext,
109 QueryContextAttributesA,
110 ImpersonateSecurityContext,
111 RevertSecurityContext,
115 QuerySecurityPackageInfoA,
116 NULL, /* Reserved3 */
117 NULL, /* Reserved4 */
118 ExportSecurityContext,
119 ImportSecurityContextA,
121 NULL, /* Reserved8 */
122 QuerySecurityContextToken,
125 SetContextAttributesA
128 static SecurityFunctionTableW securityFunctionTableW = {
129 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2,
130 EnumerateSecurityPackagesW,
131 QueryCredentialsAttributesW,
132 AcquireCredentialsHandleW,
133 FreeCredentialsHandle,
134 NULL, /* Reserved2 */
135 InitializeSecurityContextW,
136 AcceptSecurityContext,
138 DeleteSecurityContext,
140 QueryContextAttributesW,
141 ImpersonateSecurityContext,
142 RevertSecurityContext,
146 QuerySecurityPackageInfoW,
147 NULL, /* Reserved3 */
148 NULL, /* Reserved4 */
149 ExportSecurityContext,
150 ImportSecurityContextW,
152 NULL, /* Reserved8 */
153 QuerySecurityContextToken,
156 SetContextAttributesW
159 /***********************************************************************
160 * InitSecurityInterfaceA (SECUR32.@)
162 PSecurityFunctionTableA WINAPI InitSecurityInterfaceA(void)
164 return &securityFunctionTableA;
167 /***********************************************************************
168 * InitSecurityInterfaceW (SECUR32.@)
170 PSecurityFunctionTableW WINAPI InitSecurityInterfaceW(void)
172 return &securityFunctionTableW;
175 /* Allocates or resizes table to have space for at least howBig packages.
176 * Uses Heap functions, because needs to be able to reallocate.
178 static SecurePackageTable *_resizePackageTable(SecurePackageTable *table,
181 SecurePackageTable *ret;
183 EnterCriticalSection(&cs);
186 if (table->numAllocated < howBig)
188 ret = HeapReAlloc(GetProcessHeap(), 0, table,
189 sizeof(SecurePackageTable) + (howBig - 1) * sizeof(SecurePackage));
192 ret->numAllocated = howBig;
201 DWORD numAllocated = (howBig > 1 ? howBig : 1);
203 ret = HeapAlloc(GetProcessHeap(), 0,
204 sizeof(SecurePackageTable) +
205 (numAllocated - 1) * sizeof(SecurePackage));
208 ret->numAllocated = numAllocated;
209 ret->numPackages = 0;
212 LeaveCriticalSection(&cs);
216 /* Allocates or resizes table to have space for at least howBig providers.
217 * Uses Heap functions, because needs to be able to reallocate.
219 static SecureProviderTable *_resizeProviderTable(SecureProviderTable *table,
222 SecureProviderTable *ret;
224 EnterCriticalSection(&cs);
227 if (table->numAllocated < howBig)
229 ret = HeapReAlloc(GetProcessHeap(), 0, table,
230 sizeof(SecureProviderTable) +
231 (howBig - 1) * sizeof(SecureProvider));
234 ret->numAllocated = howBig;
243 DWORD numAllocated = (howBig > 1 ? howBig : 1);
245 ret = HeapAlloc(GetProcessHeap(), 0,
246 sizeof(SecureProviderTable) +
247 (numAllocated - 1) * sizeof(SecureProvider));
250 ret->numAllocated = numAllocated;
251 ret->numProviders = 0;
254 LeaveCriticalSection(&cs);
258 PWSTR SECUR32_strdupW(PCWSTR str)
264 ret = (PWSTR)SECUR32_ALLOC((lstrlenW(str) + 1) * sizeof(WCHAR));
273 PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str)
279 int charsNeeded = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
283 ret = (PWSTR)SECUR32_ALLOC(charsNeeded * sizeof(WCHAR));
285 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, charsNeeded);
295 PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str)
301 int charsNeeded = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0,
306 ret = (PSTR)SECUR32_ALLOC(charsNeeded);
308 WideCharToMultiByte(CP_ACP, 0, str, -1, ret, charsNeeded,
319 static void _makeFnTableA(PSecurityFunctionTableA fnTableA,
320 const PSecurityFunctionTableA inFnTableA,
321 const PSecurityFunctionTableW inFnTableW)
327 /* The size of the version 1 table is based on platform sdk's
328 * sspi.h, though the sample ssp also provided with platform sdk
329 * implies only functions through QuerySecurityPackageInfoA are
330 * implemented (yikes)
332 size_t tableSize = inFnTableA->dwVersion == 1 ?
333 (LPBYTE)&inFnTableA->SetContextAttributesA -
334 (LPBYTE)inFnTableA : sizeof(SecurityFunctionTableA);
336 memcpy(fnTableA, inFnTableA, tableSize);
337 /* override this, since we can do it internally anyway */
338 fnTableA->QuerySecurityPackageInfoA =
339 QuerySecurityPackageInfoA;
343 /* functions with thunks */
344 if (inFnTableW->AcquireCredentialsHandleW)
345 fnTableA->AcquireCredentialsHandleA =
346 thunk_AcquireCredentialsHandleA;
347 if (inFnTableW->InitializeSecurityContextW)
348 fnTableA->InitializeSecurityContextA =
349 thunk_InitializeSecurityContextA;
350 if (inFnTableW->ImportSecurityContextW)
351 fnTableA->ImportSecurityContextA =
352 thunk_ImportSecurityContextA;
353 if (inFnTableW->AddCredentialsW)
354 fnTableA->AddCredentialsA =
355 thunk_AddCredentialsA;
356 if (inFnTableW->QueryCredentialsAttributesW)
357 fnTableA->QueryCredentialsAttributesA =
358 thunk_QueryCredentialsAttributesA;
359 if (inFnTableW->QueryContextAttributesW)
360 fnTableA->QueryContextAttributesA =
361 thunk_QueryContextAttributesA;
362 if (inFnTableW->SetContextAttributesW)
363 fnTableA->SetContextAttributesA =
364 thunk_SetContextAttributesA;
365 /* this can't be thunked, there's no extra param to know which
366 * package to forward to */
367 fnTableA->EnumerateSecurityPackagesA = NULL;
368 /* functions with no thunks needed */
369 fnTableA->AcceptSecurityContext = inFnTableW->AcceptSecurityContext;
370 fnTableA->CompleteAuthToken = inFnTableW->CompleteAuthToken;
371 fnTableA->DeleteSecurityContext = inFnTableW->DeleteSecurityContext;
372 fnTableA->ImpersonateSecurityContext =
373 inFnTableW->ImpersonateSecurityContext;
374 fnTableA->RevertSecurityContext = inFnTableW->RevertSecurityContext;
375 fnTableA->MakeSignature = inFnTableW->MakeSignature;
376 fnTableA->VerifySignature = inFnTableW->VerifySignature;
377 fnTableA->FreeContextBuffer = inFnTableW->FreeContextBuffer;
378 fnTableA->QuerySecurityPackageInfoA =
379 QuerySecurityPackageInfoA;
380 fnTableA->ExportSecurityContext =
381 inFnTableW->ExportSecurityContext;
382 fnTableA->QuerySecurityContextToken =
383 inFnTableW->QuerySecurityContextToken;
384 fnTableA->EncryptMessage = inFnTableW->EncryptMessage;
385 fnTableA->DecryptMessage = inFnTableW->DecryptMessage;
390 static void _makeFnTableW(PSecurityFunctionTableW fnTableW,
391 const PSecurityFunctionTableA inFnTableA,
392 const PSecurityFunctionTableW inFnTableW)
398 /* The size of the version 1 table is based on platform sdk's
399 * sspi.h, though the sample ssp also provided with platform sdk
400 * implies only functions through QuerySecurityPackageInfoA are
401 * implemented (yikes)
403 size_t tableSize = inFnTableW->dwVersion == 1 ?
404 (LPBYTE)&inFnTableW->SetContextAttributesW -
405 (LPBYTE)inFnTableW : sizeof(SecurityFunctionTableW);
407 memcpy(fnTableW, inFnTableW, tableSize);
408 /* override this, since we can do it internally anyway */
409 fnTableW->QuerySecurityPackageInfoW =
410 QuerySecurityPackageInfoW;
414 /* functions with thunks */
415 if (inFnTableA->AcquireCredentialsHandleA)
416 fnTableW->AcquireCredentialsHandleW =
417 thunk_AcquireCredentialsHandleW;
418 if (inFnTableA->InitializeSecurityContextA)
419 fnTableW->InitializeSecurityContextW =
420 thunk_InitializeSecurityContextW;
421 if (inFnTableA->ImportSecurityContextA)
422 fnTableW->ImportSecurityContextW =
423 thunk_ImportSecurityContextW;
424 if (inFnTableA->AddCredentialsA)
425 fnTableW->AddCredentialsW =
426 thunk_AddCredentialsW;
427 if (inFnTableA->QueryCredentialsAttributesA)
428 fnTableW->QueryCredentialsAttributesW =
429 thunk_QueryCredentialsAttributesW;
430 if (inFnTableA->QueryContextAttributesA)
431 fnTableW->QueryContextAttributesW =
432 thunk_QueryContextAttributesW;
433 if (inFnTableA->SetContextAttributesA)
434 fnTableW->SetContextAttributesW =
435 thunk_SetContextAttributesW;
436 /* this can't be thunked, there's no extra param to know which
437 * package to forward to */
438 fnTableW->EnumerateSecurityPackagesW = NULL;
439 /* functions with no thunks needed */
440 fnTableW->AcceptSecurityContext = inFnTableA->AcceptSecurityContext;
441 fnTableW->CompleteAuthToken = inFnTableA->CompleteAuthToken;
442 fnTableW->DeleteSecurityContext = inFnTableA->DeleteSecurityContext;
443 fnTableW->ImpersonateSecurityContext =
444 inFnTableA->ImpersonateSecurityContext;
445 fnTableW->RevertSecurityContext = inFnTableA->RevertSecurityContext;
446 fnTableW->MakeSignature = inFnTableA->MakeSignature;
447 fnTableW->VerifySignature = inFnTableA->VerifySignature;
448 fnTableW->FreeContextBuffer = inFnTableA->FreeContextBuffer;
449 fnTableW->QuerySecurityPackageInfoW =
450 QuerySecurityPackageInfoW;
451 fnTableW->ExportSecurityContext =
452 inFnTableA->ExportSecurityContext;
453 fnTableW->QuerySecurityContextToken =
454 inFnTableA->QuerySecurityContextToken;
455 fnTableW->EncryptMessage = inFnTableA->EncryptMessage;
456 fnTableW->DecryptMessage = inFnTableA->DecryptMessage;
461 static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA,
462 const SecPkgInfoW *inInfoW)
464 if (info && (inInfoA || inInfoW))
466 /* odd, I know, but up until Name and Comment the structures are
469 memcpy(info, inInfoW ? inInfoW : (PSecPkgInfoW)inInfoA, sizeof(*info));
472 info->Name = SECUR32_strdupW(inInfoW->Name);
473 info->Comment = SECUR32_strdupW(inInfoW->Comment);
477 info->Name = SECUR32_AllocWideFromMultiByte(inInfoA->Name);
478 info->Comment = SECUR32_AllocWideFromMultiByte(inInfoA->Comment);
483 SecureProvider *SECUR32_addProvider(PSecurityFunctionTableA fnTableA,
484 PSecurityFunctionTableW fnTableW, PWSTR moduleName)
488 EnterCriticalSection(&cs);
489 providerTable = _resizeProviderTable(providerTable,
490 providerTable ? providerTable->numProviders + 1 : 1);
493 ret = &providerTable->table[providerTable->numProviders++];
495 if (fnTableA || fnTableW)
497 _makeFnTableA(&ret->fnTableA, fnTableA, fnTableW);
498 _makeFnTableW(&ret->fnTableW, fnTableA, fnTableW);
503 ret->moduleName = SECUR32_strdupW(moduleName);
509 LeaveCriticalSection(&cs);
513 void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
514 const SecPkgInfoA *infoA, const SecPkgInfoW *infoW)
517 assert(infoA || infoW);
519 EnterCriticalSection(&cs);
520 packageTable = _resizePackageTable(packageTable,
521 packageTable ? packageTable->numPackages + toAdd : toAdd);
526 for (i = 0; i < toAdd; i++)
528 SecurePackage *package =
529 &packageTable->table[packageTable->numPackages + i];
531 package->provider = provider;
532 _copyPackageInfo(&package->infoW,
533 infoA ? &infoA[i] : NULL,
534 infoW ? &infoW[i] : NULL);
536 packageTable->numPackages += toAdd;
538 LeaveCriticalSection(&cs);
541 static void _tryLoadProvider(PWSTR moduleName)
543 HMODULE lib = LoadLibraryW(moduleName);
547 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
548 (INIT_SECURITY_INTERFACE_W)GetProcAddress(lib,
549 SECURITY_ENTRYPOINT_ANSIW);
550 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
551 (INIT_SECURITY_INTERFACE_A)GetProcAddress(lib,
552 SECURITY_ENTRYPOINT_ANSIA);
554 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
555 debugstr_w(moduleName), pInitSecurityInterfaceA,
556 pInitSecurityInterfaceW);
557 if (pInitSecurityInterfaceW || pInitSecurityInterfaceA)
559 PSecurityFunctionTableA fnTableA = NULL;
560 PSecurityFunctionTableW fnTableW = NULL;
562 PSecPkgInfoA infoA = NULL;
563 PSecPkgInfoW infoW = NULL;
564 SECURITY_STATUS ret = SEC_E_OK;
566 if (pInitSecurityInterfaceA)
567 fnTableA = pInitSecurityInterfaceA();
568 if (pInitSecurityInterfaceW)
569 fnTableW = pInitSecurityInterfaceW();
570 if (fnTableW && fnTableW->EnumerateSecurityPackagesW)
571 ret = fnTableW->EnumerateSecurityPackagesW(&toAdd, &infoW);
572 else if (fnTableA && fnTableA->EnumerateSecurityPackagesA)
573 ret = fnTableA->EnumerateSecurityPackagesA(&toAdd, &infoA);
574 if (ret == SEC_E_OK && toAdd > 0 && (infoW || infoA))
576 SecureProvider *provider = SECUR32_addProvider(NULL, NULL,
580 SECUR32_addPackages(provider, toAdd, infoA, infoW);
582 fnTableW->FreeContextBuffer(infoW);
584 fnTableA->FreeContextBuffer(infoA);
590 WARN("failed to load %s\n", debugstr_w(moduleName));
593 static const WCHAR securityProvidersKeyW[] = {
594 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
595 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
596 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
598 static const WCHAR securityProvidersW[] = {
599 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
602 static void SECUR32_initializeProviders(void)
608 InitializeCriticalSection(&cs);
609 /* First load built-in providers */
610 SECUR32_initSchannelSP();
611 /* Now load providers from registry */
612 apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
614 if (apiRet == ERROR_SUCCESS)
616 WCHAR securityPkgNames[MAX_PATH]; /* arbitrary len */
617 DWORD size = sizeof(securityPkgNames) / sizeof(WCHAR), type;
619 apiRet = RegQueryValueExW(key, securityProvidersW, NULL, &type,
620 (PBYTE)securityPkgNames, &size);
621 if (apiRet == ERROR_SUCCESS && type == REG_SZ)
625 for (ptr = securityPkgNames;
626 ptr < (PWSTR)((PBYTE)securityPkgNames + size); )
630 for (comma = ptr; *comma && *comma != ','; comma++)
634 for (; *ptr && isspace(*ptr) && ptr < securityPkgNames + size;
638 _tryLoadProvider(ptr);
639 ptr += lstrlenW(ptr) + 1;
646 SecurePackage *SECUR32_findPackageW(PWSTR packageName)
648 SecurePackage *ret = NULL;
650 if (packageTable && packageName)
654 for (i = 0, ret = NULL; !ret && i < packageTable->numPackages; i++)
655 if (!lstrcmpiW(packageTable->table[i].infoW.Name, packageName))
656 ret = &packageTable->table[i];
657 if (ret && ret->provider && !ret->provider->loaded)
659 ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
660 if (ret->provider->lib)
662 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
663 (INIT_SECURITY_INTERFACE_W)GetProcAddress(ret->provider->lib,
664 SECURITY_ENTRYPOINT_ANSIW);
665 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
666 (INIT_SECURITY_INTERFACE_A)GetProcAddress(ret->provider->lib,
667 SECURITY_ENTRYPOINT_ANSIA);
668 PSecurityFunctionTableA fnTableA = NULL;
669 PSecurityFunctionTableW fnTableW = NULL;
671 if (pInitSecurityInterfaceA)
672 fnTableA = pInitSecurityInterfaceA();
673 if (pInitSecurityInterfaceW)
674 fnTableW = pInitSecurityInterfaceW();
675 _makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW);
676 _makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW);
677 ret->provider->loaded = TRUE;
686 SecurePackage *SECUR32_findPackageA(PSTR packageName)
690 if (packageTable && packageName)
692 UNICODE_STRING package;
694 RtlCreateUnicodeStringFromAsciiz(&package, packageName);
695 ret = SECUR32_findPackageW(package.Buffer);
696 RtlFreeUnicodeString(&package);
703 static void SECUR32_freeProviders(void)
708 EnterCriticalSection(&cs);
711 for (i = 0; i < packageTable->numPackages; i++)
713 SECUR32_FREE(packageTable->table[i].infoW.Name);
714 SECUR32_FREE(packageTable->table[i].infoW.Comment);
716 HeapFree(GetProcessHeap(), 0, packageTable);
721 for (i = 0; i < providerTable->numProviders; i++)
723 if (providerTable->table[i].moduleName)
724 SECUR32_FREE(providerTable->table[i].moduleName);
725 if (providerTable->table[i].lib)
726 FreeLibrary(providerTable->table[i].lib);
728 HeapFree(GetProcessHeap(), 0, providerTable);
729 providerTable = NULL;
731 LeaveCriticalSection(&cs);
732 DeleteCriticalSection(&cs);
735 /***********************************************************************
736 * FreeContextBuffer (SECUR32.@)
738 * Doh--if pv was allocated by a crypto package, this may not be correct.
739 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
740 * be any guarantee, nor is there an alloc function in secur32.
742 SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
746 /* as it turns out, SECURITY_STATUSes are actually HRESULTS */
749 if (SECUR32_FREE(pv) == NULL)
752 ret = HRESULT_FROM_WIN32(GetLastError());
755 ret = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
759 /***********************************************************************
760 * EnumerateSecurityPackagesW (SECUR32.@)
762 SECURITY_STATUS WINAPI EnumerateSecurityPackagesW(PULONG pcPackages,
763 PSecPkgInfoW *ppPackageInfo)
765 SECURITY_STATUS ret = SEC_E_OK;
767 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
769 EnterCriticalSection(&cs);
775 bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
776 for (i = 0; i < packageTable->numPackages; i++)
778 if (packageTable->table[i].infoW.Name)
780 (lstrlenW(packageTable->table[i].infoW.Name) + 1) *
782 if (packageTable->table[i].infoW.Comment)
784 (lstrlenW(packageTable->table[i].infoW.Comment) + 1) *
789 *ppPackageInfo = (PSecPkgInfoW)SECUR32_ALLOC(bytesNeeded);
794 *pcPackages = packageTable->numPackages;
795 nextString = (PWSTR)((PBYTE)*ppPackageInfo +
796 packageTable->numPackages * sizeof(SecPkgInfoW));
797 for (i = 0; i < packageTable->numPackages; i++)
799 PSecPkgInfoW pkgInfo = *ppPackageInfo + i;
801 memcpy(pkgInfo, &packageTable->table[i].infoW,
802 sizeof(SecPkgInfoW));
803 if (packageTable->table[i].infoW.Name)
805 pkgInfo->Name = nextString;
806 lstrcpyW(nextString, packageTable->table[i].infoW.Name);
807 nextString += lstrlenW(nextString) + 1;
810 pkgInfo->Name = NULL;
811 if (packageTable->table[i].infoW.Comment)
813 pkgInfo->Comment = nextString;
815 packageTable->table[i].infoW.Comment);
816 nextString += lstrlenW(nextString) + 1;
819 pkgInfo->Comment = NULL;
823 ret = SEC_E_INSUFFICIENT_MEMORY;
826 LeaveCriticalSection(&cs);
830 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
831 * structures) into an array of SecPkgInfoA structures, which it returns.
833 static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
834 const PSecPkgInfoW info)
840 size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
843 for (i = 0; i < cPackages; i++)
846 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
847 -1, NULL, 0, NULL, NULL);
849 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
850 -1, NULL, 0, NULL, NULL);
852 ret = (PSecPkgInfoA)SECUR32_ALLOC(bytesNeeded);
857 nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
858 for (i = 0; i < cPackages; i++)
860 PSecPkgInfoA pkgInfo = ret + i;
863 memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
866 pkgInfo->Name = nextString;
867 /* just repeat back to WideCharToMultiByte how many bytes
868 * it requires, since we asked it earlier
870 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
871 NULL, 0, NULL, NULL);
872 WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
873 pkgInfo->Name, bytes, NULL, NULL);
874 nextString += lstrlenA(nextString) + 1;
877 pkgInfo->Name = NULL;
880 pkgInfo->Comment = nextString;
881 /* just repeat back to WideCharToMultiByte how many bytes
882 * it requires, since we asked it earlier
884 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
885 NULL, 0, NULL, NULL);
886 WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
887 pkgInfo->Comment, bytes, NULL, NULL);
888 nextString += lstrlenA(nextString) + 1;
891 pkgInfo->Comment = NULL;
900 /***********************************************************************
901 * EnumerateSecurityPackagesA (SECUR32.@)
903 SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
904 PSecPkgInfoA *ppPackageInfo)
909 ret = EnumerateSecurityPackagesW(pcPackages, &info);
910 if (ret == SEC_E_OK && *pcPackages && info)
912 *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
913 if (*pcPackages && !*ppPackageInfo)
916 ret = SEC_E_INSUFFICIENT_MEMORY;
918 FreeContextBuffer(info);
923 /***********************************************************************
924 * GetComputerObjectNameA (SECUR32.@)
926 BOOLEAN WINAPI GetComputerObjectNameA(
927 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
929 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
933 /***********************************************************************
934 * GetComputerObjectNameW (SECUR32.@)
936 BOOLEAN WINAPI GetComputerObjectNameW(
937 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
939 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
943 /***********************************************************************
944 * DllMain (SECUR32.0)
946 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
948 if (fdwReason == DLL_PROCESS_ATTACH)
950 DisableThreadLibraryCalls(hinstDLL);
951 SECUR32_initializeProviders();
953 else if (fdwReason == DLL_PROCESS_DETACH)
955 SECUR32_freeProviders();