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
23 #define WIN32_NO_STATUS
31 #include "secur32_priv.h"
37 #include "wine/list.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
46 typedef struct _SecurePackageTable
53 typedef struct _SecureProviderTable
58 } SecureProviderTable;
64 /* Tries to load moduleName as a provider. If successful, enumerates what
65 * packages it can and adds them to the package and provider tables. Resizes
66 * tables as necessary.
68 static void _tryLoadProvider(PWSTR moduleName);
70 /* Initialization: read securityproviders value and attempt to open each dll
71 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
72 * Two undocumented functions, AddSecurityPackage(A/W) and
73 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
74 * unregister a dll, but I'm not sure.
76 static void SECUR32_initializeProviders(void);
78 /* Frees all loaded packages and providers */
79 static void SECUR32_freeProviders(void);
85 static CRITICAL_SECTION cs;
86 static SecurePackageTable *packageTable = NULL;
87 static SecureProviderTable *providerTable = NULL;
89 static SecurityFunctionTableA securityFunctionTableA = {
90 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
91 EnumerateSecurityPackagesA,
92 QueryCredentialsAttributesA,
93 AcquireCredentialsHandleA,
94 FreeCredentialsHandle,
96 InitializeSecurityContextA,
97 AcceptSecurityContext,
99 DeleteSecurityContext,
101 QueryContextAttributesA,
102 ImpersonateSecurityContext,
103 RevertSecurityContext,
107 QuerySecurityPackageInfoA,
108 EncryptMessage, /* Reserved3 */
109 DecryptMessage, /* Reserved4 */
110 ExportSecurityContext,
111 ImportSecurityContextA,
113 NULL, /* Reserved8 */
114 QuerySecurityContextToken,
117 SetContextAttributesA
120 static SecurityFunctionTableW securityFunctionTableW = {
121 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
122 EnumerateSecurityPackagesW,
123 QueryCredentialsAttributesW,
124 AcquireCredentialsHandleW,
125 FreeCredentialsHandle,
126 NULL, /* Reserved2 */
127 InitializeSecurityContextW,
128 AcceptSecurityContext,
130 DeleteSecurityContext,
132 QueryContextAttributesW,
133 ImpersonateSecurityContext,
134 RevertSecurityContext,
138 QuerySecurityPackageInfoW,
139 EncryptMessage, /* Reserved3 */
140 DecryptMessage, /* Reserved4 */
141 ExportSecurityContext,
142 ImportSecurityContextW,
144 NULL, /* Reserved8 */
145 QuerySecurityContextToken,
148 SetContextAttributesW
151 /***********************************************************************
152 * InitSecurityInterfaceA (SECUR32.@)
154 PSecurityFunctionTableA WINAPI InitSecurityInterfaceA(void)
156 return &securityFunctionTableA;
159 /***********************************************************************
160 * InitSecurityInterfaceW (SECUR32.@)
162 PSecurityFunctionTableW WINAPI InitSecurityInterfaceW(void)
164 return &securityFunctionTableW;
167 static PWSTR SECUR32_strdupW(PCWSTR str)
173 ret = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str) + 1) * sizeof(WCHAR));
182 PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str)
188 int charsNeeded = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
192 ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded * sizeof(WCHAR));
194 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, charsNeeded);
204 PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str)
210 int charsNeeded = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0,
215 ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded);
217 WideCharToMultiByte(CP_ACP, 0, str, -1, ret, charsNeeded,
228 static void _makeFnTableA(PSecurityFunctionTableA fnTableA,
229 const SecurityFunctionTableA *inFnTableA,
230 const SecurityFunctionTableW *inFnTableW)
236 /* The size of the version 1 table is based on platform sdk's
237 * sspi.h, though the sample ssp also provided with platform sdk
238 * implies only functions through QuerySecurityPackageInfoA are
239 * implemented (yikes)
241 size_t tableSize = inFnTableA->dwVersion == 1 ?
242 (const BYTE *)&inFnTableA->SetContextAttributesA -
243 (const BYTE *)inFnTableA : sizeof(SecurityFunctionTableA);
245 memcpy(fnTableA, inFnTableA, tableSize);
246 /* override this, since we can do it internally anyway */
247 fnTableA->QuerySecurityPackageInfoA =
248 QuerySecurityPackageInfoA;
252 /* functions with thunks */
253 if (inFnTableW->AcquireCredentialsHandleW)
254 fnTableA->AcquireCredentialsHandleA =
255 thunk_AcquireCredentialsHandleA;
256 if (inFnTableW->InitializeSecurityContextW)
257 fnTableA->InitializeSecurityContextA =
258 thunk_InitializeSecurityContextA;
259 if (inFnTableW->ImportSecurityContextW)
260 fnTableA->ImportSecurityContextA =
261 thunk_ImportSecurityContextA;
262 if (inFnTableW->AddCredentialsW)
263 fnTableA->AddCredentialsA =
264 thunk_AddCredentialsA;
265 if (inFnTableW->QueryCredentialsAttributesW)
266 fnTableA->QueryCredentialsAttributesA =
267 thunk_QueryCredentialsAttributesA;
268 if (inFnTableW->QueryContextAttributesW)
269 fnTableA->QueryContextAttributesA =
270 thunk_QueryContextAttributesA;
271 if (inFnTableW->SetContextAttributesW)
272 fnTableA->SetContextAttributesA =
273 thunk_SetContextAttributesA;
274 /* this can't be thunked, there's no extra param to know which
275 * package to forward to */
276 fnTableA->EnumerateSecurityPackagesA = NULL;
277 /* functions with no thunks needed */
278 fnTableA->AcceptSecurityContext = inFnTableW->AcceptSecurityContext;
279 fnTableA->CompleteAuthToken = inFnTableW->CompleteAuthToken;
280 fnTableA->DeleteSecurityContext = inFnTableW->DeleteSecurityContext;
281 fnTableA->ImpersonateSecurityContext =
282 inFnTableW->ImpersonateSecurityContext;
283 fnTableA->RevertSecurityContext = inFnTableW->RevertSecurityContext;
284 fnTableA->MakeSignature = inFnTableW->MakeSignature;
285 fnTableA->VerifySignature = inFnTableW->VerifySignature;
286 fnTableA->FreeContextBuffer = inFnTableW->FreeContextBuffer;
287 fnTableA->QuerySecurityPackageInfoA =
288 QuerySecurityPackageInfoA;
289 fnTableA->ExportSecurityContext =
290 inFnTableW->ExportSecurityContext;
291 fnTableA->QuerySecurityContextToken =
292 inFnTableW->QuerySecurityContextToken;
293 fnTableA->EncryptMessage = inFnTableW->EncryptMessage;
294 fnTableA->DecryptMessage = inFnTableW->DecryptMessage;
299 static void _makeFnTableW(PSecurityFunctionTableW fnTableW,
300 const SecurityFunctionTableA *inFnTableA,
301 const SecurityFunctionTableW *inFnTableW)
307 /* The size of the version 1 table is based on platform sdk's
308 * sspi.h, though the sample ssp also provided with platform sdk
309 * implies only functions through QuerySecurityPackageInfoA are
310 * implemented (yikes)
312 size_t tableSize = inFnTableW->dwVersion == 1 ?
313 (const BYTE *)&inFnTableW->SetContextAttributesW -
314 (const BYTE *)inFnTableW : sizeof(SecurityFunctionTableW);
316 memcpy(fnTableW, inFnTableW, tableSize);
317 /* override this, since we can do it internally anyway */
318 fnTableW->QuerySecurityPackageInfoW =
319 QuerySecurityPackageInfoW;
323 /* functions with thunks */
324 if (inFnTableA->AcquireCredentialsHandleA)
325 fnTableW->AcquireCredentialsHandleW =
326 thunk_AcquireCredentialsHandleW;
327 if (inFnTableA->InitializeSecurityContextA)
328 fnTableW->InitializeSecurityContextW =
329 thunk_InitializeSecurityContextW;
330 if (inFnTableA->ImportSecurityContextA)
331 fnTableW->ImportSecurityContextW =
332 thunk_ImportSecurityContextW;
333 if (inFnTableA->AddCredentialsA)
334 fnTableW->AddCredentialsW =
335 thunk_AddCredentialsW;
336 if (inFnTableA->QueryCredentialsAttributesA)
337 fnTableW->QueryCredentialsAttributesW =
338 thunk_QueryCredentialsAttributesW;
339 if (inFnTableA->QueryContextAttributesA)
340 fnTableW->QueryContextAttributesW =
341 thunk_QueryContextAttributesW;
342 if (inFnTableA->SetContextAttributesA)
343 fnTableW->SetContextAttributesW =
344 thunk_SetContextAttributesW;
345 /* this can't be thunked, there's no extra param to know which
346 * package to forward to */
347 fnTableW->EnumerateSecurityPackagesW = NULL;
348 /* functions with no thunks needed */
349 fnTableW->AcceptSecurityContext = inFnTableA->AcceptSecurityContext;
350 fnTableW->CompleteAuthToken = inFnTableA->CompleteAuthToken;
351 fnTableW->DeleteSecurityContext = inFnTableA->DeleteSecurityContext;
352 fnTableW->ImpersonateSecurityContext =
353 inFnTableA->ImpersonateSecurityContext;
354 fnTableW->RevertSecurityContext = inFnTableA->RevertSecurityContext;
355 fnTableW->MakeSignature = inFnTableA->MakeSignature;
356 fnTableW->VerifySignature = inFnTableA->VerifySignature;
357 fnTableW->FreeContextBuffer = inFnTableA->FreeContextBuffer;
358 fnTableW->QuerySecurityPackageInfoW =
359 QuerySecurityPackageInfoW;
360 fnTableW->ExportSecurityContext =
361 inFnTableA->ExportSecurityContext;
362 fnTableW->QuerySecurityContextToken =
363 inFnTableA->QuerySecurityContextToken;
364 fnTableW->EncryptMessage = inFnTableA->EncryptMessage;
365 fnTableW->DecryptMessage = inFnTableA->DecryptMessage;
370 static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA,
371 const SecPkgInfoW *inInfoW)
373 if (info && (inInfoA || inInfoW))
375 /* odd, I know, but up until Name and Comment the structures are
378 memcpy(info, inInfoW ? inInfoW : (const SecPkgInfoW *)inInfoA, sizeof(*info));
381 info->Name = SECUR32_strdupW(inInfoW->Name);
382 info->Comment = SECUR32_strdupW(inInfoW->Comment);
386 info->Name = SECUR32_AllocWideFromMultiByte(inInfoA->Name);
387 info->Comment = SECUR32_AllocWideFromMultiByte(inInfoA->Comment);
392 SecureProvider *SECUR32_addProvider(const SecurityFunctionTableA *fnTableA,
393 const SecurityFunctionTableW *fnTableW, PCWSTR moduleName)
397 EnterCriticalSection(&cs);
401 providerTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable));
404 LeaveCriticalSection(&cs);
408 list_init(&providerTable->table);
411 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider));
414 LeaveCriticalSection(&cs);
418 list_add_tail(&providerTable->table, &ret->entry);
421 if (fnTableA || fnTableW)
423 ret->moduleName = moduleName ? SECUR32_strdupW(moduleName) : NULL;
424 _makeFnTableA(&ret->fnTableA, fnTableA, fnTableW);
425 _makeFnTableW(&ret->fnTableW, fnTableA, fnTableW);
426 ret->loaded = moduleName ? FALSE : TRUE;
430 ret->moduleName = SECUR32_strdupW(moduleName);
434 LeaveCriticalSection(&cs);
438 void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
439 const SecPkgInfoA *infoA, const SecPkgInfoW *infoW)
444 assert(infoA || infoW);
446 EnterCriticalSection(&cs);
450 packageTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable));
453 LeaveCriticalSection(&cs);
457 packageTable->numPackages = 0;
458 list_init(&packageTable->table);
461 for (i = 0; i < toAdd; i++)
463 SecurePackage *package = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage));
467 list_add_tail(&packageTable->table, &package->entry);
469 package->provider = provider;
470 _copyPackageInfo(&package->infoW,
471 infoA ? &infoA[i] : NULL,
472 infoW ? &infoW[i] : NULL);
474 packageTable->numPackages += toAdd;
476 LeaveCriticalSection(&cs);
479 static void _tryLoadProvider(PWSTR moduleName)
481 HMODULE lib = LoadLibraryW(moduleName);
485 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
486 (INIT_SECURITY_INTERFACE_W)GetProcAddress(lib,
487 SECURITY_ENTRYPOINT_ANSIW);
488 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
489 (INIT_SECURITY_INTERFACE_A)GetProcAddress(lib,
490 SECURITY_ENTRYPOINT_ANSIA);
492 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
493 debugstr_w(moduleName), pInitSecurityInterfaceA,
494 pInitSecurityInterfaceW);
495 if (pInitSecurityInterfaceW || pInitSecurityInterfaceA)
497 PSecurityFunctionTableA fnTableA = NULL;
498 PSecurityFunctionTableW fnTableW = NULL;
500 PSecPkgInfoA infoA = NULL;
501 PSecPkgInfoW infoW = NULL;
502 SECURITY_STATUS ret = SEC_E_OK;
504 if (pInitSecurityInterfaceA)
505 fnTableA = pInitSecurityInterfaceA();
506 if (pInitSecurityInterfaceW)
507 fnTableW = pInitSecurityInterfaceW();
508 if (fnTableW && fnTableW->EnumerateSecurityPackagesW)
510 if (fnTableW != &securityFunctionTableW)
511 ret = fnTableW->EnumerateSecurityPackagesW(&toAdd, &infoW);
513 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName));
515 else if (fnTableA && fnTableA->EnumerateSecurityPackagesA)
517 if (fnTableA != &securityFunctionTableA)
518 ret = fnTableA->EnumerateSecurityPackagesA(&toAdd, &infoA);
520 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName));
522 if (ret == SEC_E_OK && toAdd > 0 && (infoW || infoA))
524 SecureProvider *provider = SECUR32_addProvider(NULL, NULL,
528 SECUR32_addPackages(provider, toAdd, infoA, infoW);
530 fnTableW->FreeContextBuffer(infoW);
532 fnTableA->FreeContextBuffer(infoA);
538 WARN("failed to load %s\n", debugstr_w(moduleName));
541 static const WCHAR securityProvidersKeyW[] = {
542 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
543 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
544 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
546 static const WCHAR securityProvidersW[] = {
547 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
550 static void SECUR32_initializeProviders(void)
556 InitializeCriticalSection(&cs);
557 cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs");
558 /* First load built-in providers */
559 SECUR32_initSchannelSP();
560 SECUR32_initNTLMSP();
561 /* Load the Negotiate provider last so apps stumble over the working NTLM
562 * provider first. Attempting to fix bug #16905 while keeping the
563 * application reported on wine-users on 2006-09-12 working. */
564 SECUR32_initNegotiateSP();
565 /* Now load providers from registry */
566 apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
568 if (apiRet == ERROR_SUCCESS)
570 WCHAR securityPkgNames[MAX_PATH]; /* arbitrary len */
571 DWORD size = sizeof(securityPkgNames) / sizeof(WCHAR), type;
573 apiRet = RegQueryValueExW(key, securityProvidersW, NULL, &type,
574 (PBYTE)securityPkgNames, &size);
575 if (apiRet == ERROR_SUCCESS && type == REG_SZ)
579 size = size / sizeof(WCHAR);
580 for (ptr = securityPkgNames;
581 ptr < securityPkgNames + size; )
585 for (comma = ptr; *comma && *comma != ','; comma++)
589 for (; *ptr && isspace(*ptr) && ptr < securityPkgNames + size;
593 _tryLoadProvider(ptr);
594 ptr += lstrlenW(ptr) + 1;
601 SecurePackage *SECUR32_findPackageW(PCWSTR packageName)
603 SecurePackage *ret = NULL;
604 BOOL matched = FALSE;
606 if (packageTable && packageName)
608 LIST_FOR_EACH_ENTRY(ret, &packageTable->table, SecurePackage, entry)
610 matched = !lstrcmpiW(ret->infoW.Name, packageName);
618 if (ret->provider && !ret->provider->loaded)
620 ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
621 if (ret->provider->lib)
623 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
624 (INIT_SECURITY_INTERFACE_W)GetProcAddress(ret->provider->lib,
625 SECURITY_ENTRYPOINT_ANSIW);
626 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
627 (INIT_SECURITY_INTERFACE_A)GetProcAddress(ret->provider->lib,
628 SECURITY_ENTRYPOINT_ANSIA);
629 PSecurityFunctionTableA fnTableA = NULL;
630 PSecurityFunctionTableW fnTableW = NULL;
632 if (pInitSecurityInterfaceA)
633 fnTableA = pInitSecurityInterfaceA();
634 if (pInitSecurityInterfaceW)
635 fnTableW = pInitSecurityInterfaceW();
636 /* don't update built-in SecurityFunctionTable */
637 if (fnTableA != &securityFunctionTableA)
638 _makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW);
639 if (fnTableW != &securityFunctionTableW)
640 _makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW);
641 ret->provider->loaded = TRUE;
650 SecurePackage *SECUR32_findPackageA(PCSTR packageName)
654 if (packageTable && packageName)
656 UNICODE_STRING package;
658 RtlCreateUnicodeStringFromAsciiz(&package, packageName);
659 ret = SECUR32_findPackageW(package.Buffer);
660 RtlFreeUnicodeString(&package);
667 static void SECUR32_freeProviders(void)
670 EnterCriticalSection(&cs);
672 SECUR32_deinitSchannelSP();
676 SecurePackage *package, *package_next;
677 LIST_FOR_EACH_ENTRY_SAFE(package, package_next, &packageTable->table,
678 SecurePackage, entry)
680 HeapFree(GetProcessHeap(), 0, package->infoW.Name);
681 HeapFree(GetProcessHeap(), 0, package->infoW.Comment);
682 HeapFree(GetProcessHeap(), 0, package);
685 HeapFree(GetProcessHeap(), 0, packageTable);
691 SecureProvider *provider, *provider_next;
692 LIST_FOR_EACH_ENTRY_SAFE(provider, provider_next, &providerTable->table,
693 SecureProvider, entry)
695 HeapFree(GetProcessHeap(), 0, provider->moduleName);
697 FreeLibrary(provider->lib);
698 HeapFree(GetProcessHeap(), 0, provider);
701 HeapFree(GetProcessHeap(), 0, providerTable);
702 providerTable = NULL;
705 LeaveCriticalSection(&cs);
706 cs.DebugInfo->Spare[0] = 0;
707 DeleteCriticalSection(&cs);
710 /***********************************************************************
711 * FreeContextBuffer (SECUR32.@)
713 * Doh--if pv was allocated by a crypto package, this may not be correct.
714 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
715 * be any guarantee, nor is there an alloc function in secur32.
717 SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
719 HeapFree(GetProcessHeap(), 0, pv);
724 /***********************************************************************
725 * EnumerateSecurityPackagesW (SECUR32.@)
727 SECURITY_STATUS WINAPI EnumerateSecurityPackagesW(PULONG pcPackages,
728 PSecPkgInfoW *ppPackageInfo)
730 SECURITY_STATUS ret = SEC_E_OK;
732 TRACE("(%p, %p)\n", pcPackages, ppPackageInfo);
734 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
736 EnterCriticalSection(&cs);
739 SecurePackage *package;
742 bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
743 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
745 if (package->infoW.Name)
746 bytesNeeded += (lstrlenW(package->infoW.Name) + 1) * sizeof(WCHAR);
747 if (package->infoW.Comment)
748 bytesNeeded += (lstrlenW(package->infoW.Comment) + 1) * sizeof(WCHAR);
752 *ppPackageInfo = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
758 *pcPackages = packageTable->numPackages;
759 nextString = (PWSTR)((PBYTE)*ppPackageInfo +
760 packageTable->numPackages * sizeof(SecPkgInfoW));
761 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
763 PSecPkgInfoW pkgInfo = *ppPackageInfo + i++;
765 *pkgInfo = package->infoW;
766 if (package->infoW.Name)
768 TRACE("Name[%d] = %s\n", i - 1, debugstr_w(package->infoW.Name));
769 pkgInfo->Name = nextString;
770 lstrcpyW(nextString, package->infoW.Name);
771 nextString += lstrlenW(nextString) + 1;
774 pkgInfo->Name = NULL;
775 if (package->infoW.Comment)
777 TRACE("Comment[%d] = %s\n", i - 1, debugstr_w(package->infoW.Comment));
778 pkgInfo->Comment = nextString;
779 lstrcpyW(nextString, package->infoW.Comment);
780 nextString += lstrlenW(nextString) + 1;
783 pkgInfo->Comment = NULL;
787 ret = SEC_E_INSUFFICIENT_MEMORY;
790 LeaveCriticalSection(&cs);
791 TRACE("<-- 0x%08x\n", ret);
795 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
796 * structures) into an array of SecPkgInfoA structures, which it returns.
798 static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
799 const SecPkgInfoW *info)
805 size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
808 for (i = 0; i < cPackages; i++)
811 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
812 -1, NULL, 0, NULL, NULL);
814 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
815 -1, NULL, 0, NULL, NULL);
817 ret = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
822 nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
823 for (i = 0; i < cPackages; i++)
825 PSecPkgInfoA pkgInfo = ret + i;
828 memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
831 pkgInfo->Name = nextString;
832 /* just repeat back to WideCharToMultiByte how many bytes
833 * it requires, since we asked it earlier
835 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
836 NULL, 0, NULL, NULL);
837 WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
838 pkgInfo->Name, bytes, NULL, NULL);
839 nextString += lstrlenA(nextString) + 1;
842 pkgInfo->Name = NULL;
845 pkgInfo->Comment = nextString;
846 /* just repeat back to WideCharToMultiByte how many bytes
847 * it requires, since we asked it earlier
849 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
850 NULL, 0, NULL, NULL);
851 WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
852 pkgInfo->Comment, bytes, NULL, NULL);
853 nextString += lstrlenA(nextString) + 1;
856 pkgInfo->Comment = NULL;
865 /***********************************************************************
866 * EnumerateSecurityPackagesA (SECUR32.@)
868 SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
869 PSecPkgInfoA *ppPackageInfo)
874 ret = EnumerateSecurityPackagesW(pcPackages, &info);
875 if (ret == SEC_E_OK && *pcPackages && info)
877 *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
878 if (*pcPackages && !*ppPackageInfo)
881 ret = SEC_E_INSUFFICIENT_MEMORY;
883 FreeContextBuffer(info);
888 /***********************************************************************
889 * GetComputerObjectNameA (SECUR32.@)
891 * Get the local computer's name using the format specified.
894 * NameFormat [I] The format for the name.
895 * lpNameBuffer [O] Pointer to buffer to receive the name.
896 * nSize [I/O] Size in characters of buffer.
899 * TRUE If the name was written to lpNameBuffer.
900 * FALSE If the name couldn't be written.
903 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
904 * name will be returned in *nSize.
906 * nSize returns the number of characters written when lpNameBuffer is not
907 * NULL or the size of the buffer needed to hold the name when the buffer
908 * is too short or lpNameBuffer is NULL.
910 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
912 BOOLEAN WINAPI GetComputerObjectNameA(
913 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
916 LPWSTR bufferW = NULL;
917 ULONG sizeW = *nSize;
918 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
920 bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
921 if (bufferW == NULL) {
922 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
926 rc = GetComputerObjectNameW(NameFormat, bufferW, &sizeW);
928 ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
929 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
934 HeapFree(GetProcessHeap(), 0, bufferW);
938 /***********************************************************************
939 * GetComputerObjectNameW (SECUR32.@)
941 BOOLEAN WINAPI GetComputerObjectNameW(
942 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
944 LSA_HANDLE policyHandle;
945 LSA_OBJECT_ATTRIBUTES objectAttributes;
946 PPOLICY_DNS_DOMAIN_INFO domainInfo;
949 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
951 if (NameFormat == NameUnknown)
953 SetLastError(ERROR_INVALID_PARAMETER);
957 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
958 objectAttributes.Length = sizeof(objectAttributes);
960 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
961 POLICY_VIEW_LOCAL_INFORMATION,
963 if (ntStatus != STATUS_SUCCESS)
965 SetLastError(LsaNtStatusToWinError(ntStatus));
966 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
970 ntStatus = LsaQueryInformationPolicy(policyHandle,
971 PolicyDnsDomainInformation,
972 (PVOID *)&domainInfo);
973 if (ntStatus != STATUS_SUCCESS)
975 SetLastError(LsaNtStatusToWinError(ntStatus));
976 WARN("LsaQueryInformationPolicy failed with NT status %u\n",
978 LsaClose(policyHandle);
986 case NameSamCompatible:
988 WCHAR name[MAX_COMPUTERNAME_LENGTH + 1];
989 DWORD size = sizeof(name)/sizeof(name[0]);
990 if (GetComputerNameW(name, &size))
992 DWORD len = domainInfo->Name.Length + size + 3;
998 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1003 WCHAR bs[] = { '\\', 0 };
1004 WCHAR ds[] = { '$', 0 };
1005 lstrcpyW(lpNameBuffer, domainInfo->Name.Buffer);
1006 lstrcatW(lpNameBuffer, bs);
1007 lstrcatW(lpNameBuffer, name);
1008 lstrcatW(lpNameBuffer, ds);
1012 else /* just requesting length required */
1020 SetLastError(ERROR_INTERNAL_ERROR);
1025 case NameFullyQualifiedDN:
1029 case NameUserPrincipal:
1030 case NameCanonicalEx:
1031 case NameServicePrincipal:
1033 FIXME("NameFormat %d not implemented\n", NameFormat);
1034 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1038 SetLastError(ERROR_INVALID_PARAMETER);
1044 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1048 LsaFreeMemory(domainInfo);
1049 LsaClose(policyHandle);
1054 /***********************************************************************
1055 * GetUserNameExA (SECUR32.@)
1057 BOOLEAN WINAPI GetUserNameExA(
1058 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
1061 LPWSTR bufferW = NULL;
1062 ULONG sizeW = *nSize;
1063 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
1065 bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
1066 if (bufferW == NULL) {
1067 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1071 rc = GetUserNameExW(NameFormat, bufferW, &sizeW);
1073 ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
1076 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
1083 SetLastError(ERROR_MORE_DATA);
1088 HeapFree(GetProcessHeap(), 0, bufferW);
1092 BOOLEAN WINAPI GetUserNameExW(
1093 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
1096 WCHAR samname[UNLEN + 1 + MAX_COMPUTERNAME_LENGTH + 1];
1099 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
1103 case NameSamCompatible:
1105 /* This assumes the current user is always a local account */
1106 len = MAX_COMPUTERNAME_LENGTH + 1;
1107 if (GetComputerNameW(samname, &len))
1109 out = samname + lstrlenW(samname);
1112 if (GetUserNameW(out, &len))
1114 status = (lstrlenW(samname) < *nSize);
1117 lstrcpyW(lpNameBuffer, samname);
1118 *nSize = lstrlenW(samname);
1122 SetLastError(ERROR_MORE_DATA);
1123 *nSize = lstrlenW(samname) + 1;
1134 case NameFullyQualifiedDN:
1138 case NameUserPrincipal:
1139 case NameCanonicalEx:
1140 case NameServicePrincipal:
1142 SetLastError(ERROR_NONE_MAPPED);
1146 SetLastError(ERROR_INVALID_PARAMETER);
1153 BOOLEAN WINAPI TranslateNameA(
1154 LPCSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1155 EXTENDED_NAME_FORMAT DesiredNameFormat, LPSTR lpTranslatedName,
1158 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1159 DesiredNameFormat, lpTranslatedName, nSize);
1163 BOOLEAN WINAPI TranslateNameW(
1164 LPCWSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1165 EXTENDED_NAME_FORMAT DesiredNameFormat, LPWSTR lpTranslatedName,
1168 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1169 DesiredNameFormat, lpTranslatedName, nSize);
1173 /***********************************************************************
1174 * DllMain (SECUR32.0)
1176 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1178 if (fdwReason == DLL_PROCESS_ATTACH)
1180 DisableThreadLibraryCalls(hinstDLL);
1181 SECUR32_initializeProviders();
1183 else if (fdwReason == DLL_PROCESS_DETACH)
1185 SECUR32_freeProviders();