winedbg: Remove some superfluous pointer casts.
[wine/hacks.git] / dlls / secur32 / secur32.c
blob8f599f0fb4c0bb221e42efd7f33fdf269714d3d7
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
19 #include <assert.h>
20 #include <stdarg.h>
22 #include "ntstatus.h"
23 #define WIN32_NO_STATUS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winnls.h"
27 #include "winreg.h"
28 #include "winternl.h"
29 #include "shlwapi.h"
30 #include "sspi.h"
31 #include "secur32_priv.h"
32 #include "secext.h"
33 #include "ntsecapi.h"
34 #include "thunks.h"
35 #include "lmcons.h"
37 #include "wine/list.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
42 /**
43 * Type definitions
46 typedef struct _SecurePackageTable
48 DWORD numPackages;
49 DWORD numAllocated;
50 struct list table;
51 } SecurePackageTable;
53 typedef struct _SecureProviderTable
55 DWORD numProviders;
56 DWORD numAllocated;
57 struct list table;
58 } SecureProviderTable;
60 /**
61 * Prototypes
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);
81 /**
82 * Globals
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,
95 NULL, /* Reserved2 */
96 InitializeSecurityContextA,
97 AcceptSecurityContext,
98 CompleteAuthToken,
99 DeleteSecurityContext,
100 ApplyControlToken,
101 QueryContextAttributesA,
102 ImpersonateSecurityContext,
103 RevertSecurityContext,
104 MakeSignature,
105 VerifySignature,
106 FreeContextBuffer,
107 QuerySecurityPackageInfoA,
108 EncryptMessage, /* Reserved3 */
109 DecryptMessage, /* Reserved4 */
110 ExportSecurityContext,
111 ImportSecurityContextA,
112 AddCredentialsA,
113 NULL, /* Reserved8 */
114 QuerySecurityContextToken,
115 EncryptMessage,
116 DecryptMessage,
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,
129 CompleteAuthToken,
130 DeleteSecurityContext,
131 ApplyControlToken,
132 QueryContextAttributesW,
133 ImpersonateSecurityContext,
134 RevertSecurityContext,
135 MakeSignature,
136 VerifySignature,
137 FreeContextBuffer,
138 QuerySecurityPackageInfoW,
139 EncryptMessage, /* Reserved3 */
140 DecryptMessage, /* Reserved4 */
141 ExportSecurityContext,
142 ImportSecurityContextW,
143 AddCredentialsW,
144 NULL, /* Reserved8 */
145 QuerySecurityContextToken,
146 EncryptMessage,
147 DecryptMessage,
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)
169 PWSTR ret;
171 if (str)
173 ret = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str) + 1) * sizeof(WCHAR));
174 if (ret)
175 lstrcpyW(ret, str);
177 else
178 ret = NULL;
179 return ret;
182 PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str)
184 PWSTR ret;
186 if (str)
188 int charsNeeded = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
190 if (charsNeeded)
192 ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded * sizeof(WCHAR));
193 if (ret)
194 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, charsNeeded);
196 else
197 ret = NULL;
199 else
200 ret = NULL;
201 return ret;
204 PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str)
206 PSTR ret;
208 if (str)
210 int charsNeeded = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0,
211 NULL, NULL);
213 if (charsNeeded)
215 ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded);
216 if (ret)
217 WideCharToMultiByte(CP_ACP, 0, str, -1, ret, charsNeeded,
218 NULL, NULL);
220 else
221 ret = NULL;
223 else
224 ret = NULL;
225 return ret;
228 static void _makeFnTableA(PSecurityFunctionTableA fnTableA,
229 const SecurityFunctionTableA *inFnTableA,
230 const SecurityFunctionTableW *inFnTableW)
232 if (fnTableA)
234 if (inFnTableA)
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;
250 else if (inFnTableW)
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)
303 if (fnTableW)
305 if (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;
321 else if (inFnTableA)
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
376 * identical
378 memcpy(info, inInfoW ? inInfoW : (const SecPkgInfoW *)inInfoA, sizeof(*info));
379 if (inInfoW)
381 info->Name = SECUR32_strdupW(inInfoW->Name);
382 info->Comment = SECUR32_strdupW(inInfoW->Comment);
384 else
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)
395 SecureProvider *ret;
397 EnterCriticalSection(&cs);
399 if (!providerTable)
401 providerTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable));
402 if (!providerTable)
404 LeaveCriticalSection(&cs);
405 return NULL;
408 list_init(&providerTable->table);
411 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider));
412 if (!ret)
414 LeaveCriticalSection(&cs);
415 return NULL;
418 list_add_tail(&providerTable->table, &ret->entry);
419 ret->lib = NULL;
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;
428 else
430 ret->moduleName = SECUR32_strdupW(moduleName);
431 ret->loaded = FALSE;
434 LeaveCriticalSection(&cs);
435 return ret;
438 void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
439 const SecPkgInfoA *infoA, const SecPkgInfoW *infoW)
441 ULONG i;
443 assert(provider);
444 assert(infoA || infoW);
446 EnterCriticalSection(&cs);
448 if (!packageTable)
450 packageTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable));
451 if (!packageTable)
453 LeaveCriticalSection(&cs);
454 return;
457 packageTable->numPackages = 0;
458 list_init(&packageTable->table);
461 for (i = 0; i < toAdd; i++)
463 SecurePackage *package = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage));
464 if (!package)
465 continue;
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);
483 if (lib)
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;
499 ULONG toAdd = 0;
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);
512 else
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);
519 else
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,
525 moduleName);
527 if (provider)
528 SECUR32_addPackages(provider, toAdd, infoA, infoW);
529 if (infoW)
530 fnTableW->FreeContextBuffer(infoW);
531 else
532 fnTableA->FreeContextBuffer(infoA);
535 FreeLibrary(lib);
537 else
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)
552 HKEY key;
553 long apiRet;
555 TRACE("\n");
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.*/
563 #if 0
564 SECUR32_initNegotiateSP();
565 #endif
566 SECUR32_initNTLMSP();
567 /* Now load providers from registry */
568 apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
569 KEY_READ, &key);
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)
579 WCHAR *ptr;
581 size = size / sizeof(WCHAR);
582 for (ptr = securityPkgNames;
583 ptr < securityPkgNames + size; )
585 WCHAR *comma;
587 for (comma = ptr; *comma && *comma != ','; comma++)
589 if (*comma == ',')
590 *comma = '\0';
591 for (; *ptr && isspace(*ptr) && ptr < securityPkgNames + size;
592 ptr++)
594 if (*ptr)
595 _tryLoadProvider(ptr);
596 ptr += lstrlenW(ptr) + 1;
599 RegCloseKey(key);
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);
613 if (matched)
614 break;
617 if (!matched)
618 return NULL;
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;
645 else
646 ret = NULL;
649 return ret;
652 SecurePackage *SECUR32_findPackageA(PCSTR packageName)
654 SecurePackage *ret;
656 if (packageTable && packageName)
658 UNICODE_STRING package;
660 RtlCreateUnicodeStringFromAsciiz(&package, packageName);
661 ret = SECUR32_findPackageW(package.Buffer);
662 RtlFreeUnicodeString(&package);
664 else
665 ret = NULL;
666 return ret;
669 static void SECUR32_freeProviders(void)
671 SecurePackage *package;
672 SecureProvider *provider;
674 TRACE("\n");
675 EnterCriticalSection(&cs);
677 SECUR32_deinitSchannelSP();
679 if (packageTable)
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);
688 packageTable = NULL;
691 if (providerTable)
693 LIST_FOR_EACH_ENTRY(provider, &providerTable->table, SecureProvider, entry)
695 HeapFree(GetProcessHeap(), 0, provider->moduleName);
696 if (provider->lib)
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);
720 return SEC_E_OK;
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 */
734 *pcPackages = 0;
735 EnterCriticalSection(&cs);
736 if (packageTable)
738 SecurePackage *package;
739 size_t bytesNeeded;
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);
749 if (bytesNeeded)
751 *ppPackageInfo = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
752 if (*ppPackageInfo)
754 ULONG i = 0;
755 PWSTR nextString;
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;
772 else
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;
781 else
782 pkgInfo->Comment = NULL;
785 else
786 ret = SEC_E_INSUFFICIENT_MEMORY;
789 LeaveCriticalSection(&cs);
790 TRACE("<-- 0x%08x\n", ret);
791 return 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)
800 PSecPkgInfoA ret;
802 if (info)
804 size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
805 ULONG i;
807 for (i = 0; i < cPackages; i++)
809 if (info[i].Name)
810 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
811 -1, NULL, 0, NULL, NULL);
812 if (info[i].Comment)
813 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
814 -1, NULL, 0, NULL, NULL);
816 ret = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
817 if (ret)
819 PSTR nextString;
821 nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
822 for (i = 0; i < cPackages; i++)
824 PSecPkgInfoA pkgInfo = ret + i;
825 int bytes;
827 memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
828 if (info[i].Name)
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;
840 else
841 pkgInfo->Name = NULL;
842 if (info[i].Comment)
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;
854 else
855 pkgInfo->Comment = NULL;
859 else
860 ret = NULL;
861 return ret;
864 /***********************************************************************
865 * EnumerateSecurityPackagesA (SECUR32.@)
867 SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
868 PSecPkgInfoA *ppPackageInfo)
870 SECURITY_STATUS ret;
871 PSecPkgInfoW info;
873 ret = EnumerateSecurityPackagesW(pcPackages, &info);
874 if (ret == SEC_E_OK && *pcPackages && info)
876 *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
877 if (*pcPackages && !*ppPackageInfo)
879 *pcPackages = 0;
880 ret = SEC_E_INSUFFICIENT_MEMORY;
882 FreeContextBuffer(info);
884 return ret;
887 /***********************************************************************
888 * GetComputerObjectNameA (SECUR32.@)
890 * Get the local computer's name using the format specified.
892 * PARAMS
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.
897 * RETURNS
898 * TRUE If the name was written to lpNameBuffer.
899 * FALSE If the name couldn't be written.
901 * NOTES
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)
914 BOOLEAN rc;
915 LPWSTR bufferW = NULL;
916 ULONG sizeW = *nSize;
917 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
918 if (lpNameBuffer) {
919 bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
920 if (bufferW == NULL) {
921 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
922 return FALSE;
925 rc = GetComputerObjectNameW(NameFormat, bufferW, &sizeW);
926 if (rc && bufferW) {
927 ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
928 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
929 *nSize = len;
931 else
932 *nSize = sizeW;
933 HeapFree(GetProcessHeap(), 0, bufferW);
934 return rc;
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;
946 NTSTATUS ntStatus;
947 BOOLEAN status;
948 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
950 if (NameFormat == NameUnknown)
952 SetLastError(ERROR_INVALID_PARAMETER);
953 return FALSE;
956 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
957 objectAttributes.Length = sizeof(objectAttributes);
959 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
960 POLICY_VIEW_LOCAL_INFORMATION,
961 &policyHandle);
962 if (ntStatus != STATUS_SUCCESS)
964 SetLastError(LsaNtStatusToWinError(ntStatus));
965 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
966 return FALSE;
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",
976 GetLastError());
977 LsaClose(policyHandle);
978 return FALSE;
981 if (domainInfo->Sid)
983 switch (NameFormat)
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;
992 if (lpNameBuffer)
994 if (*nSize < len)
996 *nSize = len;
997 SetLastError(ERROR_INSUFFICIENT_BUFFER);
998 status = FALSE;
1000 else
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);
1008 status = TRUE;
1011 else /* just requesting length required */
1013 *nSize = len;
1014 status = TRUE;
1017 else
1019 SetLastError(ERROR_INTERNAL_ERROR);
1020 status = FALSE;
1023 break;
1024 case NameFullyQualifiedDN:
1025 case NameDisplay:
1026 case NameUniqueId:
1027 case NameCanonical:
1028 case NameUserPrincipal:
1029 case NameCanonicalEx:
1030 case NameServicePrincipal:
1031 case NameDnsDomain:
1032 FIXME("NameFormat %d not implemented\n", NameFormat);
1033 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1034 status = FALSE;
1035 break;
1036 default:
1037 SetLastError(ERROR_INVALID_PARAMETER);
1038 status = FALSE;
1041 else
1043 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1044 status = FALSE;
1047 LsaFreeMemory(domainInfo);
1048 LsaClose(policyHandle);
1050 return status;
1053 /***********************************************************************
1054 * GetUserNameExA (SECUR32.@)
1056 BOOLEAN WINAPI GetUserNameExA(
1057 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
1059 BOOLEAN rc;
1060 LPWSTR bufferW = NULL;
1061 ULONG sizeW = *nSize;
1062 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
1063 if (lpNameBuffer) {
1064 bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
1065 if (bufferW == NULL) {
1066 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1067 return FALSE;
1070 rc = GetUserNameExW(NameFormat, bufferW, &sizeW);
1071 if (rc) {
1072 ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
1073 if (len <= *nSize)
1075 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
1076 *nSize = len - 1;
1078 else
1080 *nSize = len;
1081 rc = FALSE;
1082 SetLastError(ERROR_MORE_DATA);
1085 else
1086 *nSize = sizeW;
1087 HeapFree(GetProcessHeap(), 0, bufferW);
1088 return rc;
1091 BOOLEAN WINAPI GetUserNameExW(
1092 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
1094 BOOLEAN status;
1095 WCHAR samname[UNLEN + 1 + MAX_COMPUTERNAME_LENGTH + 1];
1096 LPWSTR out;
1097 DWORD len;
1098 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
1100 switch (NameFormat)
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);
1109 *out++ = '\\';
1110 len = UNLEN + 1;
1111 if (GetUserNameW(out, &len))
1113 status = (lstrlenW(samname) < *nSize);
1114 if (status)
1116 lstrcpyW(lpNameBuffer, samname);
1117 *nSize = lstrlenW(samname);
1119 else
1121 SetLastError(ERROR_MORE_DATA);
1122 *nSize = lstrlenW(samname) + 1;
1125 else
1126 status = FALSE;
1128 else
1129 status = FALSE;
1131 break;
1132 case NameUnknown:
1133 case NameFullyQualifiedDN:
1134 case NameDisplay:
1135 case NameUniqueId:
1136 case NameCanonical:
1137 case NameUserPrincipal:
1138 case NameCanonicalEx:
1139 case NameServicePrincipal:
1140 case NameDnsDomain:
1141 SetLastError(ERROR_NONE_MAPPED);
1142 status = FALSE;
1143 break;
1144 default:
1145 SetLastError(ERROR_INVALID_PARAMETER);
1146 status = FALSE;
1149 return status;
1152 BOOLEAN WINAPI TranslateNameA(
1153 LPCSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1154 EXTENDED_NAME_FORMAT DesiredNameFormat, LPSTR lpTranslatedName,
1155 PULONG nSize)
1157 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1158 DesiredNameFormat, lpTranslatedName, nSize);
1159 return FALSE;
1162 BOOLEAN WINAPI TranslateNameW(
1163 LPCWSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1164 EXTENDED_NAME_FORMAT DesiredNameFormat, LPWSTR lpTranslatedName,
1165 PULONG nSize)
1167 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1168 DesiredNameFormat, lpTranslatedName, nSize);
1169 return FALSE;
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();
1187 return TRUE;