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 /* Do not load Negotiate yet. This breaks for some user on the wine-users
561 * mailing list as of 2006-09-12. Without Negotiate, applications should
562 * fall back to NTLM and that should work.*/
564 SECUR32_initNegotiateSP();
566 SECUR32_initNTLMSP();
567 /* Now load providers from registry */
568 apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
570 if (apiRet == ERROR_SUCCESS)
572 WCHAR securityPkgNames[MAX_PATH]; /* arbitrary len */
573 DWORD size = sizeof(securityPkgNames) / sizeof(WCHAR), type;
575 apiRet = RegQueryValueExW(key, securityProvidersW, NULL, &type,
576 (PBYTE)securityPkgNames, &size);
577 if (apiRet == ERROR_SUCCESS && type == REG_SZ)
581 size = size / sizeof(WCHAR);
582 for (ptr = securityPkgNames;
583 ptr < securityPkgNames + size; )
587 for (comma = ptr; *comma && *comma != ','; comma++)
591 for (; *ptr && isspace(*ptr) && ptr < securityPkgNames + size;
595 _tryLoadProvider(ptr);
596 ptr += lstrlenW(ptr) + 1;
603 SecurePackage *SECUR32_findPackageW(PCWSTR packageName)
605 SecurePackage *ret = NULL;
606 BOOL matched = FALSE;
608 if (packageTable && packageName)
610 LIST_FOR_EACH_ENTRY(ret, &packageTable->table, SecurePackage, entry)
612 matched = !lstrcmpiW(ret->infoW.Name, packageName);
620 if (ret->provider && !ret->provider->loaded)
622 ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
623 if (ret->provider->lib)
625 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
626 (INIT_SECURITY_INTERFACE_W)GetProcAddress(ret->provider->lib,
627 SECURITY_ENTRYPOINT_ANSIW);
628 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
629 (INIT_SECURITY_INTERFACE_A)GetProcAddress(ret->provider->lib,
630 SECURITY_ENTRYPOINT_ANSIA);
631 PSecurityFunctionTableA fnTableA = NULL;
632 PSecurityFunctionTableW fnTableW = NULL;
634 if (pInitSecurityInterfaceA)
635 fnTableA = pInitSecurityInterfaceA();
636 if (pInitSecurityInterfaceW)
637 fnTableW = pInitSecurityInterfaceW();
638 /* don't update built-in SecurityFunctionTable */
639 if (fnTableA != &securityFunctionTableA)
640 _makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW);
641 if (fnTableW != &securityFunctionTableW)
642 _makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW);
643 ret->provider->loaded = TRUE;
652 SecurePackage *SECUR32_findPackageA(PCSTR packageName)
656 if (packageTable && packageName)
658 UNICODE_STRING package;
660 RtlCreateUnicodeStringFromAsciiz(&package, packageName);
661 ret = SECUR32_findPackageW(package.Buffer);
662 RtlFreeUnicodeString(&package);
669 static void SECUR32_freeProviders(void)
671 SecurePackage *package;
672 SecureProvider *provider;
675 EnterCriticalSection(&cs);
677 SECUR32_deinitSchannelSP();
681 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
683 HeapFree(GetProcessHeap(), 0, package->infoW.Name);
684 HeapFree(GetProcessHeap(), 0, package->infoW.Comment);
687 HeapFree(GetProcessHeap(), 0, packageTable);
693 LIST_FOR_EACH_ENTRY(provider, &providerTable->table, SecureProvider, entry)
695 HeapFree(GetProcessHeap(), 0, provider->moduleName);
697 FreeLibrary(provider->lib);
700 HeapFree(GetProcessHeap(), 0, providerTable);
701 providerTable = NULL;
704 LeaveCriticalSection(&cs);
705 cs.DebugInfo->Spare[0] = 0;
706 DeleteCriticalSection(&cs);
709 /***********************************************************************
710 * FreeContextBuffer (SECUR32.@)
712 * Doh--if pv was allocated by a crypto package, this may not be correct.
713 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
714 * be any guarantee, nor is there an alloc function in secur32.
716 SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
718 HeapFree(GetProcessHeap(), 0, pv);
723 /***********************************************************************
724 * EnumerateSecurityPackagesW (SECUR32.@)
726 SECURITY_STATUS WINAPI EnumerateSecurityPackagesW(PULONG pcPackages,
727 PSecPkgInfoW *ppPackageInfo)
729 SECURITY_STATUS ret = SEC_E_OK;
731 TRACE("(%p, %p)\n", pcPackages, ppPackageInfo);
733 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
735 EnterCriticalSection(&cs);
738 SecurePackage *package;
741 bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
742 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
744 if (package->infoW.Name)
745 bytesNeeded += (lstrlenW(package->infoW.Name) + 1) * sizeof(WCHAR);
746 if (package->infoW.Comment)
747 bytesNeeded += (lstrlenW(package->infoW.Comment) + 1) * sizeof(WCHAR);
751 *ppPackageInfo = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
757 *pcPackages = packageTable->numPackages;
758 nextString = (PWSTR)((PBYTE)*ppPackageInfo +
759 packageTable->numPackages * sizeof(SecPkgInfoW));
760 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
762 PSecPkgInfoW pkgInfo = *ppPackageInfo + i++;
764 *pkgInfo = package->infoW;
765 if (package->infoW.Name)
767 TRACE("Name[%d] = %s\n", i - 1, debugstr_w(package->infoW.Name));
768 pkgInfo->Name = nextString;
769 lstrcpyW(nextString, package->infoW.Name);
770 nextString += lstrlenW(nextString) + 1;
773 pkgInfo->Name = NULL;
774 if (package->infoW.Comment)
776 TRACE("Comment[%d] = %s\n", i - 1, debugstr_w(package->infoW.Comment));
777 pkgInfo->Comment = nextString;
778 lstrcpyW(nextString, package->infoW.Comment);
779 nextString += lstrlenW(nextString) + 1;
782 pkgInfo->Comment = NULL;
786 ret = SEC_E_INSUFFICIENT_MEMORY;
789 LeaveCriticalSection(&cs);
790 TRACE("<-- 0x%08x\n", ret);
794 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
795 * structures) into an array of SecPkgInfoA structures, which it returns.
797 static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
798 const SecPkgInfoW *info)
804 size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
807 for (i = 0; i < cPackages; i++)
810 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
811 -1, NULL, 0, NULL, NULL);
813 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
814 -1, NULL, 0, NULL, NULL);
816 ret = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
821 nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
822 for (i = 0; i < cPackages; i++)
824 PSecPkgInfoA pkgInfo = ret + i;
827 memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
830 pkgInfo->Name = nextString;
831 /* just repeat back to WideCharToMultiByte how many bytes
832 * it requires, since we asked it earlier
834 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
835 NULL, 0, NULL, NULL);
836 WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
837 pkgInfo->Name, bytes, NULL, NULL);
838 nextString += lstrlenA(nextString) + 1;
841 pkgInfo->Name = NULL;
844 pkgInfo->Comment = nextString;
845 /* just repeat back to WideCharToMultiByte how many bytes
846 * it requires, since we asked it earlier
848 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
849 NULL, 0, NULL, NULL);
850 WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
851 pkgInfo->Comment, bytes, NULL, NULL);
852 nextString += lstrlenA(nextString) + 1;
855 pkgInfo->Comment = NULL;
864 /***********************************************************************
865 * EnumerateSecurityPackagesA (SECUR32.@)
867 SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
868 PSecPkgInfoA *ppPackageInfo)
873 ret = EnumerateSecurityPackagesW(pcPackages, &info);
874 if (ret == SEC_E_OK && *pcPackages && info)
876 *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
877 if (*pcPackages && !*ppPackageInfo)
880 ret = SEC_E_INSUFFICIENT_MEMORY;
882 FreeContextBuffer(info);
887 /***********************************************************************
888 * GetComputerObjectNameA (SECUR32.@)
890 * Get the local computer's name using the format specified.
893 * NameFormat [I] The format for the name.
894 * lpNameBuffer [O] Pointer to buffer to receive the name.
895 * nSize [I/O] Size in characters of buffer.
898 * TRUE If the name was written to lpNameBuffer.
899 * FALSE If the name couldn't be written.
902 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
903 * name will be returned in *nSize.
905 * nSize returns the number of characters written when lpNameBuffer is not
906 * NULL or the size of the buffer needed to hold the name when the buffer
907 * is too short or lpNameBuffer is NULL.
909 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
911 BOOLEAN WINAPI GetComputerObjectNameA(
912 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
915 LPWSTR bufferW = NULL;
916 ULONG sizeW = *nSize;
917 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
919 bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
920 if (bufferW == NULL) {
921 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
925 rc = GetComputerObjectNameW(NameFormat, bufferW, &sizeW);
927 ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
928 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
933 HeapFree(GetProcessHeap(), 0, bufferW);
937 /***********************************************************************
938 * GetComputerObjectNameW (SECUR32.@)
940 BOOLEAN WINAPI GetComputerObjectNameW(
941 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
943 LSA_HANDLE policyHandle;
944 LSA_OBJECT_ATTRIBUTES objectAttributes;
945 PPOLICY_DNS_DOMAIN_INFO domainInfo;
948 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
950 if (NameFormat == NameUnknown)
952 SetLastError(ERROR_INVALID_PARAMETER);
956 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
957 objectAttributes.Length = sizeof(objectAttributes);
959 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
960 POLICY_VIEW_LOCAL_INFORMATION,
962 if (ntStatus != STATUS_SUCCESS)
964 SetLastError(LsaNtStatusToWinError(ntStatus));
965 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
969 ntStatus = LsaQueryInformationPolicy(policyHandle,
970 PolicyDnsDomainInformation,
971 (PVOID *)&domainInfo);
972 if (ntStatus != STATUS_SUCCESS)
974 SetLastError(LsaNtStatusToWinError(ntStatus));
975 WARN("LsaQueryInformationPolicy failed with NT status %u\n",
977 LsaClose(policyHandle);
985 case NameSamCompatible:
987 WCHAR name[MAX_COMPUTERNAME_LENGTH + 1];
988 DWORD size = sizeof(name)/sizeof(name[0]);
989 if (GetComputerNameW(name, &size))
991 DWORD len = domainInfo->Name.Length + size + 3;
997 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1002 WCHAR bs[] = { '\\', 0 };
1003 WCHAR ds[] = { '$', 0 };
1004 lstrcpyW(lpNameBuffer, domainInfo->Name.Buffer);
1005 lstrcatW(lpNameBuffer, bs);
1006 lstrcatW(lpNameBuffer, name);
1007 lstrcatW(lpNameBuffer, ds);
1011 else /* just requesting length required */
1019 SetLastError(ERROR_INTERNAL_ERROR);
1024 case NameFullyQualifiedDN:
1028 case NameUserPrincipal:
1029 case NameCanonicalEx:
1030 case NameServicePrincipal:
1032 FIXME("NameFormat %d not implemented\n", NameFormat);
1033 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1037 SetLastError(ERROR_INVALID_PARAMETER);
1043 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1047 LsaFreeMemory(domainInfo);
1048 LsaClose(policyHandle);
1053 /***********************************************************************
1054 * GetUserNameExA (SECUR32.@)
1056 BOOLEAN WINAPI GetUserNameExA(
1057 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
1060 LPWSTR bufferW = NULL;
1061 ULONG sizeW = *nSize;
1062 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
1064 bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
1065 if (bufferW == NULL) {
1066 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1070 rc = GetUserNameExW(NameFormat, bufferW, &sizeW);
1072 ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
1075 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
1082 SetLastError(ERROR_MORE_DATA);
1087 HeapFree(GetProcessHeap(), 0, bufferW);
1091 BOOLEAN WINAPI GetUserNameExW(
1092 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
1095 WCHAR samname[UNLEN + 1 + MAX_COMPUTERNAME_LENGTH + 1];
1098 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
1102 case NameSamCompatible:
1104 /* This assumes the current user is always a local account */
1105 len = MAX_COMPUTERNAME_LENGTH + 1;
1106 if (GetComputerNameW(samname, &len))
1108 out = samname + lstrlenW(samname);
1111 if (GetUserNameW(out, &len))
1113 status = (lstrlenW(samname) < *nSize);
1116 lstrcpyW(lpNameBuffer, samname);
1117 *nSize = lstrlenW(samname);
1121 SetLastError(ERROR_MORE_DATA);
1122 *nSize = lstrlenW(samname) + 1;
1133 case NameFullyQualifiedDN:
1137 case NameUserPrincipal:
1138 case NameCanonicalEx:
1139 case NameServicePrincipal:
1141 SetLastError(ERROR_NONE_MAPPED);
1145 SetLastError(ERROR_INVALID_PARAMETER);
1152 BOOLEAN WINAPI TranslateNameA(
1153 LPCSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1154 EXTENDED_NAME_FORMAT DesiredNameFormat, LPSTR lpTranslatedName,
1157 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1158 DesiredNameFormat, lpTranslatedName, nSize);
1162 BOOLEAN WINAPI TranslateNameW(
1163 LPCWSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1164 EXTENDED_NAME_FORMAT DesiredNameFormat, LPWSTR lpTranslatedName,
1167 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1168 DesiredNameFormat, lpTranslatedName, nSize);
1172 /***********************************************************************
1173 * DllMain (SECUR32.0)
1175 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1177 if (fdwReason == DLL_PROCESS_ATTACH)
1179 DisableThreadLibraryCalls(hinstDLL);
1180 SECUR32_initializeProviders();
1182 else if (fdwReason == DLL_PROCESS_DETACH)
1184 SECUR32_freeProviders();