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 CRITICAL_SECTION_DEBUG cs_debug =
89 { &cs_debug.ProcessLocksList, &cs_debug.ProcessLocksList },
90 0, 0, { (DWORD_PTR)(__FILE__ ": cs") }
92 static CRITICAL_SECTION cs = { &cs_debug, -1, 0, 0, 0, 0 };
93 static SecurePackageTable *packageTable = NULL;
94 static SecureProviderTable *providerTable = NULL;
96 static SecurityFunctionTableA securityFunctionTableA = {
97 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
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 EncryptMessage, /* Reserved3 */
116 DecryptMessage, /* Reserved4 */
117 ExportSecurityContext,
118 ImportSecurityContextA,
120 NULL, /* Reserved8 */
121 QuerySecurityContextToken,
124 SetContextAttributesA
127 static SecurityFunctionTableW securityFunctionTableW = {
128 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
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 EncryptMessage, /* Reserved3 */
147 DecryptMessage, /* 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 static PWSTR SECUR32_strdupW(PCWSTR str)
180 ret = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str) + 1) * sizeof(WCHAR));
189 PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str)
195 int charsNeeded = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
199 ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded * sizeof(WCHAR));
201 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, charsNeeded);
211 PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str)
217 int charsNeeded = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0,
222 ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded);
224 WideCharToMultiByte(CP_ACP, 0, str, -1, ret, charsNeeded,
235 static void _makeFnTableA(PSecurityFunctionTableA fnTableA,
236 const SecurityFunctionTableA *inFnTableA,
237 const SecurityFunctionTableW *inFnTableW)
243 /* The size of the version 1 table is based on platform sdk's
244 * sspi.h, though the sample ssp also provided with platform sdk
245 * implies only functions through QuerySecurityPackageInfoA are
246 * implemented (yikes)
248 size_t tableSize = inFnTableA->dwVersion == 1 ?
249 (const BYTE *)&inFnTableA->SetContextAttributesA -
250 (const BYTE *)inFnTableA : sizeof(SecurityFunctionTableA);
252 memcpy(fnTableA, inFnTableA, tableSize);
253 /* override this, since we can do it internally anyway */
254 fnTableA->QuerySecurityPackageInfoA =
255 QuerySecurityPackageInfoA;
259 /* functions with thunks */
260 if (inFnTableW->AcquireCredentialsHandleW)
261 fnTableA->AcquireCredentialsHandleA =
262 thunk_AcquireCredentialsHandleA;
263 if (inFnTableW->InitializeSecurityContextW)
264 fnTableA->InitializeSecurityContextA =
265 thunk_InitializeSecurityContextA;
266 if (inFnTableW->ImportSecurityContextW)
267 fnTableA->ImportSecurityContextA =
268 thunk_ImportSecurityContextA;
269 if (inFnTableW->AddCredentialsW)
270 fnTableA->AddCredentialsA =
271 thunk_AddCredentialsA;
272 if (inFnTableW->QueryCredentialsAttributesW)
273 fnTableA->QueryCredentialsAttributesA =
274 thunk_QueryCredentialsAttributesA;
275 if (inFnTableW->QueryContextAttributesW)
276 fnTableA->QueryContextAttributesA =
277 thunk_QueryContextAttributesA;
278 if (inFnTableW->SetContextAttributesW)
279 fnTableA->SetContextAttributesA =
280 thunk_SetContextAttributesA;
281 /* this can't be thunked, there's no extra param to know which
282 * package to forward to */
283 fnTableA->EnumerateSecurityPackagesA = NULL;
284 /* functions with no thunks needed */
285 fnTableA->AcceptSecurityContext = inFnTableW->AcceptSecurityContext;
286 fnTableA->CompleteAuthToken = inFnTableW->CompleteAuthToken;
287 fnTableA->DeleteSecurityContext = inFnTableW->DeleteSecurityContext;
288 fnTableA->ImpersonateSecurityContext =
289 inFnTableW->ImpersonateSecurityContext;
290 fnTableA->RevertSecurityContext = inFnTableW->RevertSecurityContext;
291 fnTableA->MakeSignature = inFnTableW->MakeSignature;
292 fnTableA->VerifySignature = inFnTableW->VerifySignature;
293 fnTableA->FreeContextBuffer = inFnTableW->FreeContextBuffer;
294 fnTableA->QuerySecurityPackageInfoA =
295 QuerySecurityPackageInfoA;
296 fnTableA->ExportSecurityContext =
297 inFnTableW->ExportSecurityContext;
298 fnTableA->QuerySecurityContextToken =
299 inFnTableW->QuerySecurityContextToken;
300 fnTableA->EncryptMessage = inFnTableW->EncryptMessage;
301 fnTableA->DecryptMessage = inFnTableW->DecryptMessage;
306 static void _makeFnTableW(PSecurityFunctionTableW fnTableW,
307 const SecurityFunctionTableA *inFnTableA,
308 const SecurityFunctionTableW *inFnTableW)
314 /* The size of the version 1 table is based on platform sdk's
315 * sspi.h, though the sample ssp also provided with platform sdk
316 * implies only functions through QuerySecurityPackageInfoA are
317 * implemented (yikes)
319 size_t tableSize = inFnTableW->dwVersion == 1 ?
320 (const BYTE *)&inFnTableW->SetContextAttributesW -
321 (const BYTE *)inFnTableW : sizeof(SecurityFunctionTableW);
323 memcpy(fnTableW, inFnTableW, tableSize);
324 /* override this, since we can do it internally anyway */
325 fnTableW->QuerySecurityPackageInfoW =
326 QuerySecurityPackageInfoW;
330 /* functions with thunks */
331 if (inFnTableA->AcquireCredentialsHandleA)
332 fnTableW->AcquireCredentialsHandleW =
333 thunk_AcquireCredentialsHandleW;
334 if (inFnTableA->InitializeSecurityContextA)
335 fnTableW->InitializeSecurityContextW =
336 thunk_InitializeSecurityContextW;
337 if (inFnTableA->ImportSecurityContextA)
338 fnTableW->ImportSecurityContextW =
339 thunk_ImportSecurityContextW;
340 if (inFnTableA->AddCredentialsA)
341 fnTableW->AddCredentialsW =
342 thunk_AddCredentialsW;
343 if (inFnTableA->QueryCredentialsAttributesA)
344 fnTableW->QueryCredentialsAttributesW =
345 thunk_QueryCredentialsAttributesW;
346 if (inFnTableA->QueryContextAttributesA)
347 fnTableW->QueryContextAttributesW =
348 thunk_QueryContextAttributesW;
349 if (inFnTableA->SetContextAttributesA)
350 fnTableW->SetContextAttributesW =
351 thunk_SetContextAttributesW;
352 /* this can't be thunked, there's no extra param to know which
353 * package to forward to */
354 fnTableW->EnumerateSecurityPackagesW = NULL;
355 /* functions with no thunks needed */
356 fnTableW->AcceptSecurityContext = inFnTableA->AcceptSecurityContext;
357 fnTableW->CompleteAuthToken = inFnTableA->CompleteAuthToken;
358 fnTableW->DeleteSecurityContext = inFnTableA->DeleteSecurityContext;
359 fnTableW->ImpersonateSecurityContext =
360 inFnTableA->ImpersonateSecurityContext;
361 fnTableW->RevertSecurityContext = inFnTableA->RevertSecurityContext;
362 fnTableW->MakeSignature = inFnTableA->MakeSignature;
363 fnTableW->VerifySignature = inFnTableA->VerifySignature;
364 fnTableW->FreeContextBuffer = inFnTableA->FreeContextBuffer;
365 fnTableW->QuerySecurityPackageInfoW =
366 QuerySecurityPackageInfoW;
367 fnTableW->ExportSecurityContext =
368 inFnTableA->ExportSecurityContext;
369 fnTableW->QuerySecurityContextToken =
370 inFnTableA->QuerySecurityContextToken;
371 fnTableW->EncryptMessage = inFnTableA->EncryptMessage;
372 fnTableW->DecryptMessage = inFnTableA->DecryptMessage;
377 static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA,
378 const SecPkgInfoW *inInfoW)
380 if (info && (inInfoA || inInfoW))
382 /* odd, I know, but up until Name and Comment the structures are
385 memcpy(info, inInfoW ? inInfoW : (const SecPkgInfoW *)inInfoA, sizeof(*info));
388 info->Name = SECUR32_strdupW(inInfoW->Name);
389 info->Comment = SECUR32_strdupW(inInfoW->Comment);
393 info->Name = SECUR32_AllocWideFromMultiByte(inInfoA->Name);
394 info->Comment = SECUR32_AllocWideFromMultiByte(inInfoA->Comment);
399 SecureProvider *SECUR32_addProvider(const SecurityFunctionTableA *fnTableA,
400 const SecurityFunctionTableW *fnTableW, PCWSTR moduleName)
404 EnterCriticalSection(&cs);
408 providerTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable));
411 LeaveCriticalSection(&cs);
415 list_init(&providerTable->table);
418 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider));
421 LeaveCriticalSection(&cs);
425 list_add_tail(&providerTable->table, &ret->entry);
428 if (fnTableA || fnTableW)
430 ret->moduleName = moduleName ? SECUR32_strdupW(moduleName) : NULL;
431 _makeFnTableA(&ret->fnTableA, fnTableA, fnTableW);
432 _makeFnTableW(&ret->fnTableW, fnTableA, fnTableW);
433 ret->loaded = !moduleName;
437 ret->moduleName = SECUR32_strdupW(moduleName);
441 LeaveCriticalSection(&cs);
445 void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
446 const SecPkgInfoA *infoA, const SecPkgInfoW *infoW)
451 assert(infoA || infoW);
453 EnterCriticalSection(&cs);
457 packageTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable));
460 LeaveCriticalSection(&cs);
464 packageTable->numPackages = 0;
465 list_init(&packageTable->table);
468 for (i = 0; i < toAdd; i++)
470 SecurePackage *package = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage));
474 list_add_tail(&packageTable->table, &package->entry);
476 package->provider = provider;
477 _copyPackageInfo(&package->infoW,
478 infoA ? &infoA[i] : NULL,
479 infoW ? &infoW[i] : NULL);
481 packageTable->numPackages += toAdd;
483 LeaveCriticalSection(&cs);
486 static void _tryLoadProvider(PWSTR moduleName)
488 HMODULE lib = LoadLibraryW(moduleName);
492 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
493 (INIT_SECURITY_INTERFACE_W)GetProcAddress(lib,
494 SECURITY_ENTRYPOINT_ANSIW);
495 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
496 (INIT_SECURITY_INTERFACE_A)GetProcAddress(lib,
497 SECURITY_ENTRYPOINT_ANSIA);
499 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
500 debugstr_w(moduleName), pInitSecurityInterfaceA,
501 pInitSecurityInterfaceW);
502 if (pInitSecurityInterfaceW || pInitSecurityInterfaceA)
504 PSecurityFunctionTableA fnTableA = NULL;
505 PSecurityFunctionTableW fnTableW = NULL;
507 PSecPkgInfoA infoA = NULL;
508 PSecPkgInfoW infoW = NULL;
509 SECURITY_STATUS ret = SEC_E_OK;
511 if (pInitSecurityInterfaceA)
512 fnTableA = pInitSecurityInterfaceA();
513 if (pInitSecurityInterfaceW)
514 fnTableW = pInitSecurityInterfaceW();
515 if (fnTableW && fnTableW->EnumerateSecurityPackagesW)
517 if (fnTableW != &securityFunctionTableW)
518 ret = fnTableW->EnumerateSecurityPackagesW(&toAdd, &infoW);
520 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName));
522 else if (fnTableA && fnTableA->EnumerateSecurityPackagesA)
524 if (fnTableA != &securityFunctionTableA)
525 ret = fnTableA->EnumerateSecurityPackagesA(&toAdd, &infoA);
527 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName));
529 if (ret == SEC_E_OK && toAdd > 0 && (infoW || infoA))
531 SecureProvider *provider = SECUR32_addProvider(NULL, NULL,
535 SECUR32_addPackages(provider, toAdd, infoA, infoW);
537 fnTableW->FreeContextBuffer(infoW);
539 fnTableA->FreeContextBuffer(infoA);
545 WARN("failed to load %s\n", debugstr_w(moduleName));
548 static const WCHAR securityProvidersKeyW[] = {
549 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
550 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
551 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
553 static const WCHAR securityProvidersW[] = {
554 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
557 static void SECUR32_initializeProviders(void)
563 /* First load built-in providers */
564 SECUR32_initSchannelSP();
565 SECUR32_initNTLMSP();
566 /* Load the Negotiate provider last so apps stumble over the working NTLM
567 * provider first. Attempting to fix bug #16905 while keeping the
568 * application reported on wine-users on 2006-09-12 working. */
569 SECUR32_initNegotiateSP();
570 /* Now load providers from registry */
571 apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
573 if (apiRet == ERROR_SUCCESS)
575 WCHAR securityPkgNames[MAX_PATH]; /* arbitrary len */
576 DWORD size = sizeof(securityPkgNames) / sizeof(WCHAR), type;
578 apiRet = RegQueryValueExW(key, securityProvidersW, NULL, &type,
579 (PBYTE)securityPkgNames, &size);
580 if (apiRet == ERROR_SUCCESS && type == REG_SZ)
584 size = size / sizeof(WCHAR);
585 for (ptr = securityPkgNames;
586 ptr < 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(PCWSTR packageName)
608 SecurePackage *ret = NULL;
609 BOOL matched = FALSE;
611 if (packageTable && packageName)
613 LIST_FOR_EACH_ENTRY(ret, &packageTable->table, SecurePackage, entry)
615 matched = !lstrcmpiW(ret->infoW.Name, packageName);
623 if (ret->provider && !ret->provider->loaded)
625 ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
626 if (ret->provider->lib)
628 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
629 (INIT_SECURITY_INTERFACE_W)GetProcAddress(ret->provider->lib,
630 SECURITY_ENTRYPOINT_ANSIW);
631 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
632 (INIT_SECURITY_INTERFACE_A)GetProcAddress(ret->provider->lib,
633 SECURITY_ENTRYPOINT_ANSIA);
634 PSecurityFunctionTableA fnTableA = NULL;
635 PSecurityFunctionTableW fnTableW = NULL;
637 if (pInitSecurityInterfaceA)
638 fnTableA = pInitSecurityInterfaceA();
639 if (pInitSecurityInterfaceW)
640 fnTableW = pInitSecurityInterfaceW();
641 /* don't update built-in SecurityFunctionTable */
642 if (fnTableA != &securityFunctionTableA)
643 _makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW);
644 if (fnTableW != &securityFunctionTableW)
645 _makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW);
646 ret->provider->loaded = TRUE;
655 SecurePackage *SECUR32_findPackageA(PCSTR packageName)
659 if (packageTable && packageName)
661 UNICODE_STRING package;
663 RtlCreateUnicodeStringFromAsciiz(&package, packageName);
664 ret = SECUR32_findPackageW(package.Buffer);
665 RtlFreeUnicodeString(&package);
672 static void SECUR32_freeProviders(void)
675 EnterCriticalSection(&cs);
677 SECUR32_deinitSchannelSP();
681 SecurePackage *package, *package_next;
682 LIST_FOR_EACH_ENTRY_SAFE(package, package_next, &packageTable->table,
683 SecurePackage, entry)
685 HeapFree(GetProcessHeap(), 0, package->infoW.Name);
686 HeapFree(GetProcessHeap(), 0, package->infoW.Comment);
687 HeapFree(GetProcessHeap(), 0, package);
690 HeapFree(GetProcessHeap(), 0, packageTable);
696 SecureProvider *provider, *provider_next;
697 LIST_FOR_EACH_ENTRY_SAFE(provider, provider_next, &providerTable->table,
698 SecureProvider, entry)
700 HeapFree(GetProcessHeap(), 0, provider->moduleName);
702 FreeLibrary(provider->lib);
703 HeapFree(GetProcessHeap(), 0, provider);
706 HeapFree(GetProcessHeap(), 0, providerTable);
707 providerTable = NULL;
710 LeaveCriticalSection(&cs);
711 DeleteCriticalSection(&cs);
714 /***********************************************************************
715 * FreeContextBuffer (SECUR32.@)
717 * Doh--if pv was allocated by a crypto package, this may not be correct.
718 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
719 * be any guarantee, nor is there an alloc function in secur32.
721 SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
723 HeapFree(GetProcessHeap(), 0, pv);
728 /***********************************************************************
729 * EnumerateSecurityPackagesW (SECUR32.@)
731 SECURITY_STATUS WINAPI EnumerateSecurityPackagesW(PULONG pcPackages,
732 PSecPkgInfoW *ppPackageInfo)
734 SECURITY_STATUS ret = SEC_E_OK;
736 TRACE("(%p, %p)\n", pcPackages, ppPackageInfo);
738 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
740 EnterCriticalSection(&cs);
743 SecurePackage *package;
746 bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
747 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
749 if (package->infoW.Name)
750 bytesNeeded += (lstrlenW(package->infoW.Name) + 1) * sizeof(WCHAR);
751 if (package->infoW.Comment)
752 bytesNeeded += (lstrlenW(package->infoW.Comment) + 1) * sizeof(WCHAR);
756 *ppPackageInfo = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
762 *pcPackages = packageTable->numPackages;
763 nextString = (PWSTR)((PBYTE)*ppPackageInfo +
764 packageTable->numPackages * sizeof(SecPkgInfoW));
765 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
767 PSecPkgInfoW pkgInfo = *ppPackageInfo + i++;
769 *pkgInfo = package->infoW;
770 if (package->infoW.Name)
772 TRACE("Name[%d] = %s\n", i - 1, debugstr_w(package->infoW.Name));
773 pkgInfo->Name = nextString;
774 lstrcpyW(nextString, package->infoW.Name);
775 nextString += lstrlenW(nextString) + 1;
778 pkgInfo->Name = NULL;
779 if (package->infoW.Comment)
781 TRACE("Comment[%d] = %s\n", i - 1, debugstr_w(package->infoW.Comment));
782 pkgInfo->Comment = nextString;
783 lstrcpyW(nextString, package->infoW.Comment);
784 nextString += lstrlenW(nextString) + 1;
787 pkgInfo->Comment = NULL;
791 ret = SEC_E_INSUFFICIENT_MEMORY;
794 LeaveCriticalSection(&cs);
795 TRACE("<-- 0x%08x\n", ret);
799 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
800 * structures) into an array of SecPkgInfoA structures, which it returns.
802 static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
803 const SecPkgInfoW *info)
809 size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
812 for (i = 0; i < cPackages; i++)
815 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
816 -1, NULL, 0, NULL, NULL);
818 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
819 -1, NULL, 0, NULL, NULL);
821 ret = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
826 nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
827 for (i = 0; i < cPackages; i++)
829 PSecPkgInfoA pkgInfo = ret + i;
832 memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
835 pkgInfo->Name = nextString;
836 /* just repeat back to WideCharToMultiByte how many bytes
837 * it requires, since we asked it earlier
839 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
840 NULL, 0, NULL, NULL);
841 WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
842 pkgInfo->Name, bytes, NULL, NULL);
843 nextString += lstrlenA(nextString) + 1;
846 pkgInfo->Name = NULL;
849 pkgInfo->Comment = nextString;
850 /* just repeat back to WideCharToMultiByte how many bytes
851 * it requires, since we asked it earlier
853 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
854 NULL, 0, NULL, NULL);
855 WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
856 pkgInfo->Comment, bytes, NULL, NULL);
857 nextString += lstrlenA(nextString) + 1;
860 pkgInfo->Comment = NULL;
869 /***********************************************************************
870 * EnumerateSecurityPackagesA (SECUR32.@)
872 SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
873 PSecPkgInfoA *ppPackageInfo)
878 ret = EnumerateSecurityPackagesW(pcPackages, &info);
879 if (ret == SEC_E_OK && *pcPackages && info)
881 *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
882 if (*pcPackages && !*ppPackageInfo)
885 ret = SEC_E_INSUFFICIENT_MEMORY;
887 FreeContextBuffer(info);
892 /***********************************************************************
893 * GetComputerObjectNameA (SECUR32.@)
895 * Get the local computer's name using the format specified.
898 * NameFormat [I] The format for the name.
899 * lpNameBuffer [O] Pointer to buffer to receive the name.
900 * nSize [I/O] Size in characters of buffer.
903 * TRUE If the name was written to lpNameBuffer.
904 * FALSE If the name couldn't be written.
907 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
908 * name will be returned in *nSize.
910 * nSize returns the number of characters written when lpNameBuffer is not
911 * NULL or the size of the buffer needed to hold the name when the buffer
912 * is too short or lpNameBuffer is NULL.
914 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
916 BOOLEAN WINAPI GetComputerObjectNameA(
917 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
920 LPWSTR bufferW = NULL;
921 ULONG sizeW = *nSize;
922 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
924 bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
925 if (bufferW == NULL) {
926 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
930 rc = GetComputerObjectNameW(NameFormat, bufferW, &sizeW);
932 ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
933 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
938 HeapFree(GetProcessHeap(), 0, bufferW);
942 /***********************************************************************
943 * GetComputerObjectNameW (SECUR32.@)
945 BOOLEAN WINAPI GetComputerObjectNameW(
946 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
948 LSA_HANDLE policyHandle;
949 LSA_OBJECT_ATTRIBUTES objectAttributes;
950 PPOLICY_DNS_DOMAIN_INFO domainInfo;
953 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
955 if (NameFormat == NameUnknown)
957 SetLastError(ERROR_INVALID_PARAMETER);
961 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
962 objectAttributes.Length = sizeof(objectAttributes);
964 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
965 POLICY_VIEW_LOCAL_INFORMATION,
967 if (ntStatus != STATUS_SUCCESS)
969 SetLastError(LsaNtStatusToWinError(ntStatus));
970 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
974 ntStatus = LsaQueryInformationPolicy(policyHandle,
975 PolicyDnsDomainInformation,
976 (PVOID *)&domainInfo);
977 if (ntStatus != STATUS_SUCCESS)
979 SetLastError(LsaNtStatusToWinError(ntStatus));
980 WARN("LsaQueryInformationPolicy failed with NT status %u\n",
982 LsaClose(policyHandle);
990 case NameSamCompatible:
992 WCHAR name[MAX_COMPUTERNAME_LENGTH + 1];
993 DWORD size = sizeof(name)/sizeof(name[0]);
994 if (GetComputerNameW(name, &size))
996 DWORD len = domainInfo->Name.Length + size + 3;
1002 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1007 WCHAR bs[] = { '\\', 0 };
1008 WCHAR ds[] = { '$', 0 };
1009 lstrcpyW(lpNameBuffer, domainInfo->Name.Buffer);
1010 lstrcatW(lpNameBuffer, bs);
1011 lstrcatW(lpNameBuffer, name);
1012 lstrcatW(lpNameBuffer, ds);
1016 else /* just requesting length required */
1024 SetLastError(ERROR_INTERNAL_ERROR);
1029 case NameFullyQualifiedDN:
1033 case NameUserPrincipal:
1034 case NameCanonicalEx:
1035 case NameServicePrincipal:
1037 FIXME("NameFormat %d not implemented\n", NameFormat);
1038 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1042 SetLastError(ERROR_INVALID_PARAMETER);
1048 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1052 LsaFreeMemory(domainInfo);
1053 LsaClose(policyHandle);
1058 /***********************************************************************
1059 * GetUserNameExA (SECUR32.@)
1061 BOOLEAN WINAPI GetUserNameExA(
1062 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
1065 LPWSTR bufferW = NULL;
1066 ULONG sizeW = *nSize;
1067 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
1069 bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
1070 if (bufferW == NULL) {
1071 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1075 rc = GetUserNameExW(NameFormat, bufferW, &sizeW);
1077 ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
1080 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
1087 SetLastError(ERROR_MORE_DATA);
1092 HeapFree(GetProcessHeap(), 0, bufferW);
1096 BOOLEAN WINAPI GetUserNameExW(
1097 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
1100 WCHAR samname[UNLEN + 1 + MAX_COMPUTERNAME_LENGTH + 1];
1103 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
1107 case NameSamCompatible:
1109 /* This assumes the current user is always a local account */
1110 len = MAX_COMPUTERNAME_LENGTH + 1;
1111 if (GetComputerNameW(samname, &len))
1113 out = samname + lstrlenW(samname);
1116 if (GetUserNameW(out, &len))
1118 status = (lstrlenW(samname) < *nSize);
1121 lstrcpyW(lpNameBuffer, samname);
1122 *nSize = lstrlenW(samname);
1126 SetLastError(ERROR_MORE_DATA);
1127 *nSize = lstrlenW(samname) + 1;
1138 case NameFullyQualifiedDN:
1142 case NameUserPrincipal:
1143 case NameCanonicalEx:
1144 case NameServicePrincipal:
1146 SetLastError(ERROR_NONE_MAPPED);
1150 SetLastError(ERROR_INVALID_PARAMETER);
1157 BOOLEAN WINAPI TranslateNameA(
1158 LPCSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1159 EXTENDED_NAME_FORMAT DesiredNameFormat, LPSTR lpTranslatedName,
1162 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1163 DesiredNameFormat, lpTranslatedName, nSize);
1167 BOOLEAN WINAPI TranslateNameW(
1168 LPCWSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1169 EXTENDED_NAME_FORMAT DesiredNameFormat, LPWSTR lpTranslatedName,
1172 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1173 DesiredNameFormat, lpTranslatedName, nSize);
1177 /***********************************************************************
1178 * DllMain (SECUR32.0)
1180 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1182 if (fdwReason == DLL_PROCESS_ATTACH)
1184 DisableThreadLibraryCalls(hinstDLL);
1185 SECUR32_initializeProviders();
1187 else if (fdwReason == DLL_PROCESS_DETACH)
1189 SECUR32_freeProviders();