push 92ef5b88da02911741c0a2f56030fd2e20189321
[wine/hacks.git] / dlls / secur32 / secur32.c
blob2e12c66b7281479cbfdb0c305bcf5a5804a0b251
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"
36 #include "wine/list.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
41 /**
42 * Type definitions
45 typedef struct _SecurePackageTable
47 DWORD numPackages;
48 DWORD numAllocated;
49 struct list table;
50 } SecurePackageTable;
52 typedef struct _SecureProviderTable
54 DWORD numProviders;
55 DWORD numAllocated;
56 struct list table;
57 } SecureProviderTable;
59 /**
60 * Prototypes
63 /* Tries to load moduleName as a provider. If successful, enumerates what
64 * packages it can and adds them to the package and provider tables. Resizes
65 * tables as necessary.
67 static void _tryLoadProvider(PWSTR moduleName);
69 /* Initialization: read securityproviders value and attempt to open each dll
70 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
71 * Two undocumented functions, AddSecurityPackage(A/W) and
72 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
73 * unregister a dll, but I'm not sure.
75 static void SECUR32_initializeProviders(void);
77 /* Frees all loaded packages and providers */
78 static void SECUR32_freeProviders(void);
80 /**
81 * Globals
84 static CRITICAL_SECTION cs;
85 static SecurePackageTable *packageTable = NULL;
86 static SecureProviderTable *providerTable = NULL;
88 static SecurityFunctionTableA securityFunctionTableA = {
89 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
90 EnumerateSecurityPackagesA,
91 QueryCredentialsAttributesA,
92 AcquireCredentialsHandleA,
93 FreeCredentialsHandle,
94 NULL, /* Reserved2 */
95 InitializeSecurityContextA,
96 AcceptSecurityContext,
97 CompleteAuthToken,
98 DeleteSecurityContext,
99 ApplyControlToken,
100 QueryContextAttributesA,
101 ImpersonateSecurityContext,
102 RevertSecurityContext,
103 MakeSignature,
104 VerifySignature,
105 FreeContextBuffer,
106 QuerySecurityPackageInfoA,
107 NULL, /* Reserved3 */
108 NULL, /* Reserved4 */
109 ExportSecurityContext,
110 ImportSecurityContextA,
111 AddCredentialsA,
112 NULL, /* Reserved8 */
113 QuerySecurityContextToken,
114 EncryptMessage,
115 DecryptMessage,
116 SetContextAttributesA
119 static SecurityFunctionTableW securityFunctionTableW = {
120 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
121 EnumerateSecurityPackagesW,
122 QueryCredentialsAttributesW,
123 AcquireCredentialsHandleW,
124 FreeCredentialsHandle,
125 NULL, /* Reserved2 */
126 InitializeSecurityContextW,
127 AcceptSecurityContext,
128 CompleteAuthToken,
129 DeleteSecurityContext,
130 ApplyControlToken,
131 QueryContextAttributesW,
132 ImpersonateSecurityContext,
133 RevertSecurityContext,
134 MakeSignature,
135 VerifySignature,
136 FreeContextBuffer,
137 QuerySecurityPackageInfoW,
138 NULL, /* Reserved3 */
139 NULL, /* Reserved4 */
140 ExportSecurityContext,
141 ImportSecurityContextW,
142 AddCredentialsW,
143 NULL, /* Reserved8 */
144 QuerySecurityContextToken,
145 EncryptMessage,
146 DecryptMessage,
147 SetContextAttributesW
150 /***********************************************************************
151 * InitSecurityInterfaceA (SECUR32.@)
153 PSecurityFunctionTableA WINAPI InitSecurityInterfaceA(void)
155 return &securityFunctionTableA;
158 /***********************************************************************
159 * InitSecurityInterfaceW (SECUR32.@)
161 PSecurityFunctionTableW WINAPI InitSecurityInterfaceW(void)
163 return &securityFunctionTableW;
166 PWSTR SECUR32_strdupW(PCWSTR str)
168 PWSTR ret;
170 if (str)
172 ret = (PWSTR)SECUR32_ALLOC((lstrlenW(str) + 1) * sizeof(WCHAR));
173 if (ret)
174 lstrcpyW(ret, str);
176 else
177 ret = NULL;
178 return ret;
181 PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str)
183 PWSTR ret;
185 if (str)
187 int charsNeeded = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
189 if (charsNeeded)
191 ret = (PWSTR)SECUR32_ALLOC(charsNeeded * sizeof(WCHAR));
192 if (ret)
193 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, charsNeeded);
195 else
196 ret = NULL;
198 else
199 ret = NULL;
200 return ret;
203 PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str)
205 PSTR ret;
207 if (str)
209 int charsNeeded = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0,
210 NULL, NULL);
212 if (charsNeeded)
214 ret = (PSTR)SECUR32_ALLOC(charsNeeded);
215 if (ret)
216 WideCharToMultiByte(CP_ACP, 0, str, -1, ret, charsNeeded,
217 NULL, NULL);
219 else
220 ret = NULL;
222 else
223 ret = NULL;
224 return ret;
227 static void _makeFnTableA(PSecurityFunctionTableA fnTableA,
228 const SecurityFunctionTableA *inFnTableA,
229 const SecurityFunctionTableW *inFnTableW)
231 if (fnTableA)
233 if (inFnTableA)
235 /* The size of the version 1 table is based on platform sdk's
236 * sspi.h, though the sample ssp also provided with platform sdk
237 * implies only functions through QuerySecurityPackageInfoA are
238 * implemented (yikes)
240 size_t tableSize = inFnTableA->dwVersion == 1 ?
241 (const BYTE *)&inFnTableA->SetContextAttributesA -
242 (const BYTE *)inFnTableA : sizeof(SecurityFunctionTableA);
244 memcpy(fnTableA, inFnTableA, tableSize);
245 /* override this, since we can do it internally anyway */
246 fnTableA->QuerySecurityPackageInfoA =
247 QuerySecurityPackageInfoA;
249 else if (inFnTableW)
251 /* functions with thunks */
252 if (inFnTableW->AcquireCredentialsHandleW)
253 fnTableA->AcquireCredentialsHandleA =
254 thunk_AcquireCredentialsHandleA;
255 if (inFnTableW->InitializeSecurityContextW)
256 fnTableA->InitializeSecurityContextA =
257 thunk_InitializeSecurityContextA;
258 if (inFnTableW->ImportSecurityContextW)
259 fnTableA->ImportSecurityContextA =
260 thunk_ImportSecurityContextA;
261 if (inFnTableW->AddCredentialsW)
262 fnTableA->AddCredentialsA =
263 thunk_AddCredentialsA;
264 if (inFnTableW->QueryCredentialsAttributesW)
265 fnTableA->QueryCredentialsAttributesA =
266 thunk_QueryCredentialsAttributesA;
267 if (inFnTableW->QueryContextAttributesW)
268 fnTableA->QueryContextAttributesA =
269 thunk_QueryContextAttributesA;
270 if (inFnTableW->SetContextAttributesW)
271 fnTableA->SetContextAttributesA =
272 thunk_SetContextAttributesA;
273 /* this can't be thunked, there's no extra param to know which
274 * package to forward to */
275 fnTableA->EnumerateSecurityPackagesA = NULL;
276 /* functions with no thunks needed */
277 fnTableA->AcceptSecurityContext = inFnTableW->AcceptSecurityContext;
278 fnTableA->CompleteAuthToken = inFnTableW->CompleteAuthToken;
279 fnTableA->DeleteSecurityContext = inFnTableW->DeleteSecurityContext;
280 fnTableA->ImpersonateSecurityContext =
281 inFnTableW->ImpersonateSecurityContext;
282 fnTableA->RevertSecurityContext = inFnTableW->RevertSecurityContext;
283 fnTableA->MakeSignature = inFnTableW->MakeSignature;
284 fnTableA->VerifySignature = inFnTableW->VerifySignature;
285 fnTableA->FreeContextBuffer = inFnTableW->FreeContextBuffer;
286 fnTableA->QuerySecurityPackageInfoA =
287 QuerySecurityPackageInfoA;
288 fnTableA->ExportSecurityContext =
289 inFnTableW->ExportSecurityContext;
290 fnTableA->QuerySecurityContextToken =
291 inFnTableW->QuerySecurityContextToken;
292 fnTableA->EncryptMessage = inFnTableW->EncryptMessage;
293 fnTableA->DecryptMessage = inFnTableW->DecryptMessage;
298 static void _makeFnTableW(PSecurityFunctionTableW fnTableW,
299 const SecurityFunctionTableA *inFnTableA,
300 const SecurityFunctionTableW *inFnTableW)
302 if (fnTableW)
304 if (inFnTableW)
306 /* The size of the version 1 table is based on platform sdk's
307 * sspi.h, though the sample ssp also provided with platform sdk
308 * implies only functions through QuerySecurityPackageInfoA are
309 * implemented (yikes)
311 size_t tableSize = inFnTableW->dwVersion == 1 ?
312 (const BYTE *)&inFnTableW->SetContextAttributesW -
313 (const BYTE *)inFnTableW : sizeof(SecurityFunctionTableW);
315 memcpy(fnTableW, inFnTableW, tableSize);
316 /* override this, since we can do it internally anyway */
317 fnTableW->QuerySecurityPackageInfoW =
318 QuerySecurityPackageInfoW;
320 else if (inFnTableA)
322 /* functions with thunks */
323 if (inFnTableA->AcquireCredentialsHandleA)
324 fnTableW->AcquireCredentialsHandleW =
325 thunk_AcquireCredentialsHandleW;
326 if (inFnTableA->InitializeSecurityContextA)
327 fnTableW->InitializeSecurityContextW =
328 thunk_InitializeSecurityContextW;
329 if (inFnTableA->ImportSecurityContextA)
330 fnTableW->ImportSecurityContextW =
331 thunk_ImportSecurityContextW;
332 if (inFnTableA->AddCredentialsA)
333 fnTableW->AddCredentialsW =
334 thunk_AddCredentialsW;
335 if (inFnTableA->QueryCredentialsAttributesA)
336 fnTableW->QueryCredentialsAttributesW =
337 thunk_QueryCredentialsAttributesW;
338 if (inFnTableA->QueryContextAttributesA)
339 fnTableW->QueryContextAttributesW =
340 thunk_QueryContextAttributesW;
341 if (inFnTableA->SetContextAttributesA)
342 fnTableW->SetContextAttributesW =
343 thunk_SetContextAttributesW;
344 /* this can't be thunked, there's no extra param to know which
345 * package to forward to */
346 fnTableW->EnumerateSecurityPackagesW = NULL;
347 /* functions with no thunks needed */
348 fnTableW->AcceptSecurityContext = inFnTableA->AcceptSecurityContext;
349 fnTableW->CompleteAuthToken = inFnTableA->CompleteAuthToken;
350 fnTableW->DeleteSecurityContext = inFnTableA->DeleteSecurityContext;
351 fnTableW->ImpersonateSecurityContext =
352 inFnTableA->ImpersonateSecurityContext;
353 fnTableW->RevertSecurityContext = inFnTableA->RevertSecurityContext;
354 fnTableW->MakeSignature = inFnTableA->MakeSignature;
355 fnTableW->VerifySignature = inFnTableA->VerifySignature;
356 fnTableW->FreeContextBuffer = inFnTableA->FreeContextBuffer;
357 fnTableW->QuerySecurityPackageInfoW =
358 QuerySecurityPackageInfoW;
359 fnTableW->ExportSecurityContext =
360 inFnTableA->ExportSecurityContext;
361 fnTableW->QuerySecurityContextToken =
362 inFnTableA->QuerySecurityContextToken;
363 fnTableW->EncryptMessage = inFnTableA->EncryptMessage;
364 fnTableW->DecryptMessage = inFnTableA->DecryptMessage;
369 static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA,
370 const SecPkgInfoW *inInfoW)
372 if (info && (inInfoA || inInfoW))
374 /* odd, I know, but up until Name and Comment the structures are
375 * identical
377 memcpy(info, inInfoW ? inInfoW : (const SecPkgInfoW *)inInfoA, sizeof(*info));
378 if (inInfoW)
380 info->Name = SECUR32_strdupW(inInfoW->Name);
381 info->Comment = SECUR32_strdupW(inInfoW->Comment);
383 else
385 info->Name = SECUR32_AllocWideFromMultiByte(inInfoA->Name);
386 info->Comment = SECUR32_AllocWideFromMultiByte(inInfoA->Comment);
391 SecureProvider *SECUR32_addProvider(const SecurityFunctionTableA *fnTableA,
392 const SecurityFunctionTableW *fnTableW, PCWSTR moduleName)
394 SecureProvider *ret;
396 EnterCriticalSection(&cs);
398 if (!providerTable)
400 providerTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable));
401 if (!providerTable)
403 LeaveCriticalSection(&cs);
404 return NULL;
407 list_init(&providerTable->table);
410 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider));
411 if (!ret)
413 LeaveCriticalSection(&cs);
414 return NULL;
417 list_add_tail(&providerTable->table, &ret->entry);
418 ret->lib = NULL;
420 if (fnTableA || fnTableW)
422 ret->moduleName = NULL;
423 _makeFnTableA(&ret->fnTableA, fnTableA, fnTableW);
424 _makeFnTableW(&ret->fnTableW, fnTableA, fnTableW);
425 ret->loaded = TRUE;
427 else
429 ret->moduleName = SECUR32_strdupW(moduleName);
430 ret->loaded = FALSE;
433 LeaveCriticalSection(&cs);
434 return ret;
437 void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
438 const SecPkgInfoA *infoA, const SecPkgInfoW *infoW)
440 ULONG i;
442 assert(provider);
443 assert(infoA || infoW);
445 EnterCriticalSection(&cs);
447 if (!packageTable)
449 packageTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable));
450 if (!packageTable)
452 LeaveCriticalSection(&cs);
453 return;
456 packageTable->numPackages = 0;
457 list_init(&packageTable->table);
460 for (i = 0; i < toAdd; i++)
462 SecurePackage *package = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage));
463 if (!package)
464 continue;
466 list_add_tail(&packageTable->table, &package->entry);
468 package->provider = provider;
469 _copyPackageInfo(&package->infoW,
470 infoA ? &infoA[i] : NULL,
471 infoW ? &infoW[i] : NULL);
473 packageTable->numPackages += toAdd;
475 LeaveCriticalSection(&cs);
478 static void _tryLoadProvider(PWSTR moduleName)
480 HMODULE lib = LoadLibraryW(moduleName);
482 if (lib)
484 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
485 (INIT_SECURITY_INTERFACE_W)GetProcAddress(lib,
486 SECURITY_ENTRYPOINT_ANSIW);
487 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
488 (INIT_SECURITY_INTERFACE_A)GetProcAddress(lib,
489 SECURITY_ENTRYPOINT_ANSIA);
491 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
492 debugstr_w(moduleName), pInitSecurityInterfaceA,
493 pInitSecurityInterfaceW);
494 if (pInitSecurityInterfaceW || pInitSecurityInterfaceA)
496 PSecurityFunctionTableA fnTableA = NULL;
497 PSecurityFunctionTableW fnTableW = NULL;
498 ULONG toAdd = 0;
499 PSecPkgInfoA infoA = NULL;
500 PSecPkgInfoW infoW = NULL;
501 SECURITY_STATUS ret = SEC_E_OK;
503 if (pInitSecurityInterfaceA)
504 fnTableA = pInitSecurityInterfaceA();
505 if (pInitSecurityInterfaceW)
506 fnTableW = pInitSecurityInterfaceW();
507 if (fnTableW && fnTableW->EnumerateSecurityPackagesW)
508 ret = fnTableW->EnumerateSecurityPackagesW(&toAdd, &infoW);
509 else if (fnTableA && fnTableA->EnumerateSecurityPackagesA)
510 ret = fnTableA->EnumerateSecurityPackagesA(&toAdd, &infoA);
511 if (ret == SEC_E_OK && toAdd > 0 && (infoW || infoA))
513 SecureProvider *provider = SECUR32_addProvider(NULL, NULL,
514 moduleName);
516 if (provider)
517 SECUR32_addPackages(provider, toAdd, infoA, infoW);
518 if (infoW)
519 fnTableW->FreeContextBuffer(infoW);
520 else
521 fnTableA->FreeContextBuffer(infoA);
524 FreeLibrary(lib);
526 else
527 WARN("failed to load %s\n", debugstr_w(moduleName));
530 static const WCHAR securityProvidersKeyW[] = {
531 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
532 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
533 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
535 static const WCHAR securityProvidersW[] = {
536 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
539 static void SECUR32_initializeProviders(void)
541 HKEY key;
542 long apiRet;
544 TRACE("\n");
545 InitializeCriticalSection(&cs);
546 cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs");
547 /* First load built-in providers */
548 SECUR32_initSchannelSP();
549 /* Do not load Negotiate yet. This breaks for some user on the wine-users
550 * mailing list as of 2006-09-12. Without Negotiate, applications should
551 * fall back to NTLM and that should work.*/
552 #if 0
553 SECUR32_initNegotiateSP();
554 #endif
555 SECUR32_initNTLMSP();
556 /* Now load providers from registry */
557 apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
558 KEY_READ, &key);
559 if (apiRet == ERROR_SUCCESS)
561 WCHAR securityPkgNames[MAX_PATH]; /* arbitrary len */
562 DWORD size = sizeof(securityPkgNames) / sizeof(WCHAR), type;
564 apiRet = RegQueryValueExW(key, securityProvidersW, NULL, &type,
565 (PBYTE)securityPkgNames, &size);
566 if (apiRet == ERROR_SUCCESS && type == REG_SZ)
568 WCHAR *ptr;
570 for (ptr = securityPkgNames;
571 ptr < (PWSTR)((PBYTE)securityPkgNames + size); )
573 WCHAR *comma;
575 for (comma = ptr; *comma && *comma != ','; comma++)
577 if (*comma == ',')
578 *comma = '\0';
579 for (; *ptr && isspace(*ptr) && ptr < securityPkgNames + size;
580 ptr++)
582 if (*ptr)
583 _tryLoadProvider(ptr);
584 ptr += lstrlenW(ptr) + 1;
587 RegCloseKey(key);
591 SecurePackage *SECUR32_findPackageW(PCWSTR packageName)
593 SecurePackage *ret = NULL;
594 BOOL matched = FALSE;
596 if (packageTable && packageName)
598 LIST_FOR_EACH_ENTRY(ret, &packageTable->table, SecurePackage, entry)
600 matched = !lstrcmpiW(ret->infoW.Name, packageName);
601 if (matched)
602 break;
605 if (!matched)
606 return NULL;
608 if (ret->provider && !ret->provider->loaded)
610 ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
611 if (ret->provider->lib)
613 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
614 (INIT_SECURITY_INTERFACE_W)GetProcAddress(ret->provider->lib,
615 SECURITY_ENTRYPOINT_ANSIW);
616 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
617 (INIT_SECURITY_INTERFACE_A)GetProcAddress(ret->provider->lib,
618 SECURITY_ENTRYPOINT_ANSIA);
619 PSecurityFunctionTableA fnTableA = NULL;
620 PSecurityFunctionTableW fnTableW = NULL;
622 if (pInitSecurityInterfaceA)
623 fnTableA = pInitSecurityInterfaceA();
624 if (pInitSecurityInterfaceW)
625 fnTableW = pInitSecurityInterfaceW();
626 _makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW);
627 _makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW);
628 ret->provider->loaded = TRUE;
630 else
631 ret = NULL;
634 return ret;
637 SecurePackage *SECUR32_findPackageA(PCSTR packageName)
639 SecurePackage *ret;
641 if (packageTable && packageName)
643 UNICODE_STRING package;
645 RtlCreateUnicodeStringFromAsciiz(&package, packageName);
646 ret = SECUR32_findPackageW(package.Buffer);
647 RtlFreeUnicodeString(&package);
649 else
650 ret = NULL;
651 return ret;
654 static void SECUR32_freeProviders(void)
656 SecurePackage *package;
657 SecureProvider *provider;
659 TRACE("\n");
660 EnterCriticalSection(&cs);
662 if (packageTable)
664 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
666 SECUR32_FREE(package->infoW.Name);
667 SECUR32_FREE(package->infoW.Comment);
670 HeapFree(GetProcessHeap(), 0, packageTable);
671 packageTable = NULL;
674 if (providerTable)
676 LIST_FOR_EACH_ENTRY(provider, &providerTable->table, SecureProvider, entry)
678 SECUR32_FREE(provider->moduleName);
679 if (provider->lib)
680 FreeLibrary(provider->lib);
683 HeapFree(GetProcessHeap(), 0, providerTable);
684 providerTable = NULL;
687 LeaveCriticalSection(&cs);
688 cs.DebugInfo->Spare[0] = 0;
689 DeleteCriticalSection(&cs);
692 /***********************************************************************
693 * FreeContextBuffer (SECUR32.@)
695 * Doh--if pv was allocated by a crypto package, this may not be correct.
696 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
697 * be any guarantee, nor is there an alloc function in secur32.
699 SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
701 SECUR32_FREE(pv);
703 return SEC_E_OK;
706 /***********************************************************************
707 * EnumerateSecurityPackagesW (SECUR32.@)
709 SECURITY_STATUS WINAPI EnumerateSecurityPackagesW(PULONG pcPackages,
710 PSecPkgInfoW *ppPackageInfo)
712 SECURITY_STATUS ret = SEC_E_OK;
714 TRACE("(%p, %p)\n", pcPackages, ppPackageInfo);
716 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
717 *pcPackages = 0;
718 EnterCriticalSection(&cs);
719 if (packageTable)
721 SecurePackage *package;
722 size_t bytesNeeded;
724 bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
725 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
727 if (package->infoW.Name)
728 bytesNeeded += (lstrlenW(package->infoW.Name) + 1) * sizeof(WCHAR);
729 if (package->infoW.Comment)
730 bytesNeeded += (lstrlenW(package->infoW.Comment) + 1) * sizeof(WCHAR);
732 if (bytesNeeded)
734 *ppPackageInfo = (PSecPkgInfoW)SECUR32_ALLOC(bytesNeeded);
735 if (*ppPackageInfo)
737 ULONG i = 0;
738 PWSTR nextString;
740 *pcPackages = packageTable->numPackages;
741 nextString = (PWSTR)((PBYTE)*ppPackageInfo +
742 packageTable->numPackages * sizeof(SecPkgInfoW));
743 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
745 PSecPkgInfoW pkgInfo = *ppPackageInfo + i++;
747 memcpy(pkgInfo, &package->infoW, sizeof(SecPkgInfoW));
748 if (package->infoW.Name)
750 TRACE("Name[%d] = %s\n", i - 1, debugstr_w(package->infoW.Name));
751 pkgInfo->Name = nextString;
752 lstrcpyW(nextString, package->infoW.Name);
753 nextString += lstrlenW(nextString) + 1;
755 else
756 pkgInfo->Name = NULL;
757 if (package->infoW.Comment)
759 TRACE("Comment[%d] = %s\n", i - 1, debugstr_w(package->infoW.Comment));
760 pkgInfo->Comment = nextString;
761 lstrcpyW(nextString, package->infoW.Comment);
762 nextString += lstrlenW(nextString) + 1;
764 else
765 pkgInfo->Comment = NULL;
768 else
769 ret = SEC_E_INSUFFICIENT_MEMORY;
772 LeaveCriticalSection(&cs);
773 TRACE("<-- 0x%08x\n", ret);
774 return ret;
777 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
778 * structures) into an array of SecPkgInfoA structures, which it returns.
780 static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
781 const SecPkgInfoW *info)
783 PSecPkgInfoA ret;
785 if (info)
787 size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
788 ULONG i;
790 for (i = 0; i < cPackages; i++)
792 if (info[i].Name)
793 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
794 -1, NULL, 0, NULL, NULL);
795 if (info[i].Comment)
796 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
797 -1, NULL, 0, NULL, NULL);
799 ret = (PSecPkgInfoA)SECUR32_ALLOC(bytesNeeded);
800 if (ret)
802 PSTR nextString;
804 nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
805 for (i = 0; i < cPackages; i++)
807 PSecPkgInfoA pkgInfo = ret + i;
808 int bytes;
810 memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
811 if (info[i].Name)
813 pkgInfo->Name = nextString;
814 /* just repeat back to WideCharToMultiByte how many bytes
815 * it requires, since we asked it earlier
817 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
818 NULL, 0, NULL, NULL);
819 WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
820 pkgInfo->Name, bytes, NULL, NULL);
821 nextString += lstrlenA(nextString) + 1;
823 else
824 pkgInfo->Name = NULL;
825 if (info[i].Comment)
827 pkgInfo->Comment = nextString;
828 /* just repeat back to WideCharToMultiByte how many bytes
829 * it requires, since we asked it earlier
831 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
832 NULL, 0, NULL, NULL);
833 WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
834 pkgInfo->Comment, bytes, NULL, NULL);
835 nextString += lstrlenA(nextString) + 1;
837 else
838 pkgInfo->Comment = NULL;
842 else
843 ret = NULL;
844 return ret;
847 /***********************************************************************
848 * EnumerateSecurityPackagesA (SECUR32.@)
850 SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
851 PSecPkgInfoA *ppPackageInfo)
853 SECURITY_STATUS ret;
854 PSecPkgInfoW info;
856 ret = EnumerateSecurityPackagesW(pcPackages, &info);
857 if (ret == SEC_E_OK && *pcPackages && info)
859 *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
860 if (*pcPackages && !*ppPackageInfo)
862 *pcPackages = 0;
863 ret = SEC_E_INSUFFICIENT_MEMORY;
865 FreeContextBuffer(info);
867 return ret;
870 /***********************************************************************
871 * GetComputerObjectNameA (SECUR32.@)
873 * Get the local computer's name using the format specified.
875 * PARAMS
876 * NameFormat [I] The format for the name.
877 * lpNameBuffer [O] Pointer to buffer to receive the name.
878 * nSize [I/O] Size in characters of buffer.
880 * RETURNS
881 * TRUE If the name was written to lpNameBuffer.
882 * FALSE If the name couldn't be written.
884 * NOTES
885 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
886 * name will be returned in *nSize.
888 * nSize returns the number of characters written when lpNameBuffer is not
889 * NULL or the size of the buffer needed to hold the name when the buffer
890 * is too short or lpNameBuffer is NULL.
892 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
894 BOOLEAN WINAPI GetComputerObjectNameA(
895 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
897 BOOLEAN rc;
898 LPWSTR bufferW = NULL;
899 ULONG sizeW = *nSize;
900 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
901 if (lpNameBuffer) {
902 bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
903 if (bufferW == NULL) {
904 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
905 return FALSE;
908 rc = GetComputerObjectNameW(NameFormat, bufferW, &sizeW);
909 if (rc && bufferW) {
910 ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
911 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
912 *nSize = len;
914 else
915 *nSize = sizeW;
916 HeapFree(GetProcessHeap(), 0, bufferW);
917 return rc;
920 /***********************************************************************
921 * GetComputerObjectNameW (SECUR32.@)
923 BOOLEAN WINAPI GetComputerObjectNameW(
924 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
926 LSA_HANDLE policyHandle;
927 LSA_OBJECT_ATTRIBUTES objectAttributes;
928 PPOLICY_DNS_DOMAIN_INFO domainInfo;
929 NTSTATUS ntStatus;
930 BOOLEAN status;
931 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
933 if (NameFormat == NameUnknown)
935 SetLastError(ERROR_INVALID_PARAMETER);
936 return FALSE;
939 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
940 objectAttributes.Length = sizeof(objectAttributes);
942 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
943 POLICY_VIEW_LOCAL_INFORMATION,
944 &policyHandle);
945 if (ntStatus != STATUS_SUCCESS)
947 SetLastError(LsaNtStatusToWinError(ntStatus));
948 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
949 return FALSE;
952 ntStatus = LsaQueryInformationPolicy(policyHandle,
953 PolicyDnsDomainInformation,
954 (PVOID *)&domainInfo);
955 if (ntStatus != STATUS_SUCCESS)
957 SetLastError(LsaNtStatusToWinError(ntStatus));
958 WARN("LsaQueryInformationPolicy failed with NT status %u\n",
959 GetLastError());
960 LsaClose(policyHandle);
961 return FALSE;
964 if (domainInfo->Sid)
966 switch (NameFormat)
968 case NameSamCompatible:
970 WCHAR name[MAX_COMPUTERNAME_LENGTH + 1];
971 DWORD size = sizeof(name);
972 if (GetComputerNameW(name, &size))
974 int len = domainInfo->Name.Length + size + 3;
975 if (lpNameBuffer)
977 if (*nSize < len)
979 *nSize = len;
980 SetLastError(ERROR_INSUFFICIENT_BUFFER);
981 status = FALSE;
983 else
985 WCHAR bs[] = { '\\', 0 };
986 WCHAR ds[] = { '$', 0 };
987 lstrcpyW(lpNameBuffer, domainInfo->Name.Buffer);
988 lstrcatW(lpNameBuffer, bs);
989 lstrcatW(lpNameBuffer, name);
990 lstrcatW(lpNameBuffer, ds);
991 status = TRUE;
994 else /* just requesting length required */
996 *nSize = len;
997 status = TRUE;
1000 else
1002 SetLastError(ERROR_INTERNAL_ERROR);
1003 status = FALSE;
1006 break;
1007 case NameFullyQualifiedDN:
1008 case NameDisplay:
1009 case NameUniqueId:
1010 case NameCanonical:
1011 case NameUserPrincipal:
1012 case NameCanonicalEx:
1013 case NameServicePrincipal:
1014 case NameDnsDomain:
1015 FIXME("NameFormat %d not implemented\n", NameFormat);
1016 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1017 status = FALSE;
1018 break;
1019 default:
1020 SetLastError(ERROR_INVALID_PARAMETER);
1021 status = FALSE;
1024 else
1026 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1027 status = FALSE;
1030 LsaFreeMemory(domainInfo);
1031 LsaClose(policyHandle);
1033 return status;
1036 /***********************************************************************
1037 * GetUserNameExA (SECUR32.@)
1039 BOOLEAN WINAPI GetUserNameExA(
1040 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
1042 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
1043 return FALSE;
1046 BOOLEAN WINAPI GetUserNameExW(
1047 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
1049 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
1050 return FALSE;
1053 NTSTATUS WINAPI LsaCallAuthenticationPackage(
1054 HANDLE LsaHandle, ULONG AuthenticationPackage, PVOID ProtocolSubmitBuffer,
1055 ULONG SubmitBufferLength, PVOID* ProtocolReturnBuffer, PULONG ReturnBufferLength,
1056 PNTSTATUS ProtocolStatus)
1058 FIXME("%p %d %p %d %p %p %p\n", LsaHandle, AuthenticationPackage,
1059 ProtocolSubmitBuffer, SubmitBufferLength, ProtocolReturnBuffer,
1060 ReturnBufferLength, ProtocolStatus);
1061 return 0;
1064 NTSTATUS WINAPI LsaConnectUntrusted(PHANDLE LsaHandle)
1066 FIXME("%p\n", LsaHandle);
1067 return 0;
1070 NTSTATUS WINAPI LsaDeregisterLogonProcess(HANDLE LsaHandle)
1072 FIXME("%p\n", LsaHandle);
1073 return 0;
1076 BOOLEAN WINAPI TranslateNameA(
1077 LPCSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1078 EXTENDED_NAME_FORMAT DesiredNameFormat, LPSTR lpTranslatedName,
1079 PULONG nSize)
1081 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1082 DesiredNameFormat, lpTranslatedName, nSize);
1083 return FALSE;
1086 BOOLEAN WINAPI TranslateNameW(
1087 LPCWSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1088 EXTENDED_NAME_FORMAT DesiredNameFormat, LPWSTR lpTranslatedName,
1089 PULONG nSize)
1091 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1092 DesiredNameFormat, lpTranslatedName, nSize);
1093 return FALSE;
1096 /***********************************************************************
1097 * DllMain (SECUR32.0)
1099 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1101 if (fdwReason == DLL_PROCESS_ATTACH)
1103 DisableThreadLibraryCalls(hinstDLL);
1104 SECUR32_initializeProviders();
1106 else if (fdwReason == DLL_PROCESS_DETACH)
1108 SECUR32_freeProviders();
1111 return TRUE;