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();