secur32: Fix some wrong assumptions in the NTLM test case, make it pass in XP SP2...
[wine/multimedia.git] / dlls / secur32 / secur32.c
blob475778265ca42d16e02653e5fcdff6234789e59b
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <assert.h>
20 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winnls.h"
24 #include "winreg.h"
25 #include "winternl.h"
26 #include "shlwapi.h"
27 #include "sspi.h"
28 #include "secur32_priv.h"
29 #include "secext.h"
30 #include "ntsecapi.h"
31 #include "thunks.h"
33 #include "wine/list.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
38 /**
39 * Type definitions
42 typedef struct _SecurePackageTable
44 DWORD numPackages;
45 DWORD numAllocated;
46 struct list table;
47 } SecurePackageTable;
49 typedef struct _SecureProviderTable
51 DWORD numProviders;
52 DWORD numAllocated;
53 struct list table;
54 } SecureProviderTable;
56 /**
57 * Prototypes
60 /* Tries to load moduleName as a provider. If successful, enumerates what
61 * packages it can and adds them to the package and provider tables. Resizes
62 * tables as necessary.
64 static void _tryLoadProvider(PWSTR moduleName);
66 /* Initialization: read securityproviders value and attempt to open each dll
67 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
68 * Two undocumented functions, AddSecurityPackage(A/W) and
69 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
70 * unregister a dll, but I'm not sure.
72 static void SECUR32_initializeProviders(void);
74 /* Frees all loaded packages and providers */
75 static void SECUR32_freeProviders(void);
77 /**
78 * Globals
81 static CRITICAL_SECTION cs;
82 static SecurePackageTable *packageTable = NULL;
83 static SecureProviderTable *providerTable = NULL;
85 static SecurityFunctionTableA securityFunctionTableA = {
86 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2,
87 EnumerateSecurityPackagesA,
88 QueryCredentialsAttributesA,
89 AcquireCredentialsHandleA,
90 FreeCredentialsHandle,
91 NULL, /* Reserved2 */
92 InitializeSecurityContextA,
93 AcceptSecurityContext,
94 CompleteAuthToken,
95 DeleteSecurityContext,
96 ApplyControlToken,
97 QueryContextAttributesA,
98 ImpersonateSecurityContext,
99 RevertSecurityContext,
100 MakeSignature,
101 VerifySignature,
102 FreeContextBuffer,
103 QuerySecurityPackageInfoA,
104 NULL, /* Reserved3 */
105 NULL, /* Reserved4 */
106 ExportSecurityContext,
107 ImportSecurityContextA,
108 AddCredentialsA,
109 NULL, /* Reserved8 */
110 QuerySecurityContextToken,
111 EncryptMessage,
112 DecryptMessage,
113 SetContextAttributesA
116 static SecurityFunctionTableW securityFunctionTableW = {
117 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2,
118 EnumerateSecurityPackagesW,
119 QueryCredentialsAttributesW,
120 AcquireCredentialsHandleW,
121 FreeCredentialsHandle,
122 NULL, /* Reserved2 */
123 InitializeSecurityContextW,
124 AcceptSecurityContext,
125 CompleteAuthToken,
126 DeleteSecurityContext,
127 ApplyControlToken,
128 QueryContextAttributesW,
129 ImpersonateSecurityContext,
130 RevertSecurityContext,
131 MakeSignature,
132 VerifySignature,
133 FreeContextBuffer,
134 QuerySecurityPackageInfoW,
135 NULL, /* Reserved3 */
136 NULL, /* Reserved4 */
137 ExportSecurityContext,
138 ImportSecurityContextW,
139 AddCredentialsW,
140 NULL, /* Reserved8 */
141 QuerySecurityContextToken,
142 EncryptMessage,
143 DecryptMessage,
144 SetContextAttributesW
147 /***********************************************************************
148 * InitSecurityInterfaceA (SECUR32.@)
150 PSecurityFunctionTableA WINAPI InitSecurityInterfaceA(void)
152 return &securityFunctionTableA;
155 /***********************************************************************
156 * InitSecurityInterfaceW (SECUR32.@)
158 PSecurityFunctionTableW WINAPI InitSecurityInterfaceW(void)
160 return &securityFunctionTableW;
163 PWSTR SECUR32_strdupW(PCWSTR str)
165 PWSTR ret;
167 if (str)
169 ret = (PWSTR)SECUR32_ALLOC((lstrlenW(str) + 1) * sizeof(WCHAR));
170 if (ret)
171 lstrcpyW(ret, str);
173 else
174 ret = NULL;
175 return ret;
178 PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str)
180 PWSTR ret;
182 if (str)
184 int charsNeeded = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
186 if (charsNeeded)
188 ret = (PWSTR)SECUR32_ALLOC(charsNeeded * sizeof(WCHAR));
189 if (ret)
190 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, charsNeeded);
192 else
193 ret = NULL;
195 else
196 ret = NULL;
197 return ret;
200 PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str)
202 PSTR ret;
204 if (str)
206 int charsNeeded = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0,
207 NULL, NULL);
209 if (charsNeeded)
211 ret = (PSTR)SECUR32_ALLOC(charsNeeded);
212 if (ret)
213 WideCharToMultiByte(CP_ACP, 0, str, -1, ret, charsNeeded,
214 NULL, NULL);
216 else
217 ret = NULL;
219 else
220 ret = NULL;
221 return ret;
224 static void _makeFnTableA(PSecurityFunctionTableA fnTableA,
225 const SecurityFunctionTableA *inFnTableA,
226 const SecurityFunctionTableW *inFnTableW)
228 if (fnTableA)
230 if (inFnTableA)
232 /* The size of the version 1 table is based on platform sdk's
233 * sspi.h, though the sample ssp also provided with platform sdk
234 * implies only functions through QuerySecurityPackageInfoA are
235 * implemented (yikes)
237 size_t tableSize = inFnTableA->dwVersion == 1 ?
238 (LPBYTE)&inFnTableA->SetContextAttributesA -
239 (LPBYTE)inFnTableA : sizeof(SecurityFunctionTableA);
241 memcpy(fnTableA, inFnTableA, tableSize);
242 /* override this, since we can do it internally anyway */
243 fnTableA->QuerySecurityPackageInfoA =
244 QuerySecurityPackageInfoA;
246 else if (inFnTableW)
248 /* functions with thunks */
249 if (inFnTableW->AcquireCredentialsHandleW)
250 fnTableA->AcquireCredentialsHandleA =
251 thunk_AcquireCredentialsHandleA;
252 if (inFnTableW->InitializeSecurityContextW)
253 fnTableA->InitializeSecurityContextA =
254 thunk_InitializeSecurityContextA;
255 if (inFnTableW->ImportSecurityContextW)
256 fnTableA->ImportSecurityContextA =
257 thunk_ImportSecurityContextA;
258 if (inFnTableW->AddCredentialsW)
259 fnTableA->AddCredentialsA =
260 thunk_AddCredentialsA;
261 if (inFnTableW->QueryCredentialsAttributesW)
262 fnTableA->QueryCredentialsAttributesA =
263 thunk_QueryCredentialsAttributesA;
264 if (inFnTableW->QueryContextAttributesW)
265 fnTableA->QueryContextAttributesA =
266 thunk_QueryContextAttributesA;
267 if (inFnTableW->SetContextAttributesW)
268 fnTableA->SetContextAttributesA =
269 thunk_SetContextAttributesA;
270 /* this can't be thunked, there's no extra param to know which
271 * package to forward to */
272 fnTableA->EnumerateSecurityPackagesA = NULL;
273 /* functions with no thunks needed */
274 fnTableA->AcceptSecurityContext = inFnTableW->AcceptSecurityContext;
275 fnTableA->CompleteAuthToken = inFnTableW->CompleteAuthToken;
276 fnTableA->DeleteSecurityContext = inFnTableW->DeleteSecurityContext;
277 fnTableA->ImpersonateSecurityContext =
278 inFnTableW->ImpersonateSecurityContext;
279 fnTableA->RevertSecurityContext = inFnTableW->RevertSecurityContext;
280 fnTableA->MakeSignature = inFnTableW->MakeSignature;
281 fnTableA->VerifySignature = inFnTableW->VerifySignature;
282 fnTableA->FreeContextBuffer = inFnTableW->FreeContextBuffer;
283 fnTableA->QuerySecurityPackageInfoA =
284 QuerySecurityPackageInfoA;
285 fnTableA->ExportSecurityContext =
286 inFnTableW->ExportSecurityContext;
287 fnTableA->QuerySecurityContextToken =
288 inFnTableW->QuerySecurityContextToken;
289 fnTableA->EncryptMessage = inFnTableW->EncryptMessage;
290 fnTableA->DecryptMessage = inFnTableW->DecryptMessage;
295 static void _makeFnTableW(PSecurityFunctionTableW fnTableW,
296 const SecurityFunctionTableA *inFnTableA,
297 const SecurityFunctionTableW *inFnTableW)
299 if (fnTableW)
301 if (inFnTableW)
303 /* The size of the version 1 table is based on platform sdk's
304 * sspi.h, though the sample ssp also provided with platform sdk
305 * implies only functions through QuerySecurityPackageInfoA are
306 * implemented (yikes)
308 size_t tableSize = inFnTableW->dwVersion == 1 ?
309 (LPBYTE)&inFnTableW->SetContextAttributesW -
310 (LPBYTE)inFnTableW : sizeof(SecurityFunctionTableW);
312 memcpy(fnTableW, inFnTableW, tableSize);
313 /* override this, since we can do it internally anyway */
314 fnTableW->QuerySecurityPackageInfoW =
315 QuerySecurityPackageInfoW;
317 else if (inFnTableA)
319 /* functions with thunks */
320 if (inFnTableA->AcquireCredentialsHandleA)
321 fnTableW->AcquireCredentialsHandleW =
322 thunk_AcquireCredentialsHandleW;
323 if (inFnTableA->InitializeSecurityContextA)
324 fnTableW->InitializeSecurityContextW =
325 thunk_InitializeSecurityContextW;
326 if (inFnTableA->ImportSecurityContextA)
327 fnTableW->ImportSecurityContextW =
328 thunk_ImportSecurityContextW;
329 if (inFnTableA->AddCredentialsA)
330 fnTableW->AddCredentialsW =
331 thunk_AddCredentialsW;
332 if (inFnTableA->QueryCredentialsAttributesA)
333 fnTableW->QueryCredentialsAttributesW =
334 thunk_QueryCredentialsAttributesW;
335 if (inFnTableA->QueryContextAttributesA)
336 fnTableW->QueryContextAttributesW =
337 thunk_QueryContextAttributesW;
338 if (inFnTableA->SetContextAttributesA)
339 fnTableW->SetContextAttributesW =
340 thunk_SetContextAttributesW;
341 /* this can't be thunked, there's no extra param to know which
342 * package to forward to */
343 fnTableW->EnumerateSecurityPackagesW = NULL;
344 /* functions with no thunks needed */
345 fnTableW->AcceptSecurityContext = inFnTableA->AcceptSecurityContext;
346 fnTableW->CompleteAuthToken = inFnTableA->CompleteAuthToken;
347 fnTableW->DeleteSecurityContext = inFnTableA->DeleteSecurityContext;
348 fnTableW->ImpersonateSecurityContext =
349 inFnTableA->ImpersonateSecurityContext;
350 fnTableW->RevertSecurityContext = inFnTableA->RevertSecurityContext;
351 fnTableW->MakeSignature = inFnTableA->MakeSignature;
352 fnTableW->VerifySignature = inFnTableA->VerifySignature;
353 fnTableW->FreeContextBuffer = inFnTableA->FreeContextBuffer;
354 fnTableW->QuerySecurityPackageInfoW =
355 QuerySecurityPackageInfoW;
356 fnTableW->ExportSecurityContext =
357 inFnTableA->ExportSecurityContext;
358 fnTableW->QuerySecurityContextToken =
359 inFnTableA->QuerySecurityContextToken;
360 fnTableW->EncryptMessage = inFnTableA->EncryptMessage;
361 fnTableW->DecryptMessage = inFnTableA->DecryptMessage;
366 static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA,
367 const SecPkgInfoW *inInfoW)
369 if (info && (inInfoA || inInfoW))
371 /* odd, I know, but up until Name and Comment the structures are
372 * identical
374 memcpy(info, inInfoW ? inInfoW : (PSecPkgInfoW)inInfoA, sizeof(*info));
375 if (inInfoW)
377 info->Name = SECUR32_strdupW(inInfoW->Name);
378 info->Comment = SECUR32_strdupW(inInfoW->Comment);
380 else
382 info->Name = SECUR32_AllocWideFromMultiByte(inInfoA->Name);
383 info->Comment = SECUR32_AllocWideFromMultiByte(inInfoA->Comment);
388 SecureProvider *SECUR32_addProvider(const SecurityFunctionTableA *fnTableA,
389 const SecurityFunctionTableW *fnTableW, const PWSTR moduleName)
391 SecureProvider *ret;
393 EnterCriticalSection(&cs);
395 if (!providerTable)
397 providerTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable));
398 if (!providerTable)
399 return NULL;
401 list_init(&providerTable->table);
404 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider));
405 if (!ret)
406 return NULL;
408 list_add_tail(&providerTable->table, &ret->entry);
409 ret->lib = NULL;
411 if (fnTableA || fnTableW)
413 ret->moduleName = NULL;
414 _makeFnTableA(&ret->fnTableA, fnTableA, fnTableW);
415 _makeFnTableW(&ret->fnTableW, fnTableA, fnTableW);
416 ret->loaded = TRUE;
418 else
420 ret->moduleName = SECUR32_strdupW(moduleName);
421 ret->loaded = FALSE;
424 LeaveCriticalSection(&cs);
425 return ret;
428 void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
429 const SecPkgInfoA *infoA, const SecPkgInfoW *infoW)
431 ULONG i;
433 assert(provider);
434 assert(infoA || infoW);
436 EnterCriticalSection(&cs);
438 if (!packageTable)
440 packageTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable));
441 if (!packageTable)
442 return;
444 packageTable->numPackages = 0;
445 list_init(&packageTable->table);
448 for (i = 0; i < toAdd; i++)
450 SecurePackage *package = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage));
451 if (!package)
452 continue;
454 list_add_tail(&packageTable->table, &package->entry);
456 package->provider = provider;
457 _copyPackageInfo(&package->infoW,
458 infoA ? &infoA[i] : NULL,
459 infoW ? &infoW[i] : NULL);
461 packageTable->numPackages += toAdd;
463 LeaveCriticalSection(&cs);
466 static void _tryLoadProvider(PWSTR moduleName)
468 HMODULE lib = LoadLibraryW(moduleName);
470 if (lib)
472 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
473 (INIT_SECURITY_INTERFACE_W)GetProcAddress(lib,
474 SECURITY_ENTRYPOINT_ANSIW);
475 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
476 (INIT_SECURITY_INTERFACE_A)GetProcAddress(lib,
477 SECURITY_ENTRYPOINT_ANSIA);
479 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
480 debugstr_w(moduleName), pInitSecurityInterfaceA,
481 pInitSecurityInterfaceW);
482 if (pInitSecurityInterfaceW || pInitSecurityInterfaceA)
484 PSecurityFunctionTableA fnTableA = NULL;
485 PSecurityFunctionTableW fnTableW = NULL;
486 ULONG toAdd = 0;
487 PSecPkgInfoA infoA = NULL;
488 PSecPkgInfoW infoW = NULL;
489 SECURITY_STATUS ret = SEC_E_OK;
491 if (pInitSecurityInterfaceA)
492 fnTableA = pInitSecurityInterfaceA();
493 if (pInitSecurityInterfaceW)
494 fnTableW = pInitSecurityInterfaceW();
495 if (fnTableW && fnTableW->EnumerateSecurityPackagesW)
496 ret = fnTableW->EnumerateSecurityPackagesW(&toAdd, &infoW);
497 else if (fnTableA && fnTableA->EnumerateSecurityPackagesA)
498 ret = fnTableA->EnumerateSecurityPackagesA(&toAdd, &infoA);
499 if (ret == SEC_E_OK && toAdd > 0 && (infoW || infoA))
501 SecureProvider *provider = SECUR32_addProvider(NULL, NULL,
502 moduleName);
504 if (provider)
505 SECUR32_addPackages(provider, toAdd, infoA, infoW);
506 if (infoW)
507 fnTableW->FreeContextBuffer(infoW);
508 else
509 fnTableA->FreeContextBuffer(infoA);
512 FreeLibrary(lib);
514 else
515 WARN("failed to load %s\n", debugstr_w(moduleName));
518 static const WCHAR securityProvidersKeyW[] = {
519 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
520 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
521 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
523 static const WCHAR securityProvidersW[] = {
524 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
527 static void SECUR32_initializeProviders(void)
529 HKEY key;
530 long apiRet;
532 TRACE("\n");
533 InitializeCriticalSection(&cs);
534 /* First load built-in providers */
535 SECUR32_initSchannelSP();
536 SECUR32_initNegotiateSP();
537 SECUR32_initNTLMSP();
538 /* Now load providers from registry */
539 apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
540 KEY_READ, &key);
541 if (apiRet == ERROR_SUCCESS)
543 WCHAR securityPkgNames[MAX_PATH]; /* arbitrary len */
544 DWORD size = sizeof(securityPkgNames) / sizeof(WCHAR), type;
546 apiRet = RegQueryValueExW(key, securityProvidersW, NULL, &type,
547 (PBYTE)securityPkgNames, &size);
548 if (apiRet == ERROR_SUCCESS && type == REG_SZ)
550 WCHAR *ptr;
552 for (ptr = securityPkgNames;
553 ptr < (PWSTR)((PBYTE)securityPkgNames + size); )
555 WCHAR *comma;
557 for (comma = ptr; *comma && *comma != ','; comma++)
559 if (*comma == ',')
560 *comma = '\0';
561 for (; *ptr && isspace(*ptr) && ptr < securityPkgNames + size;
562 ptr++)
564 if (*ptr)
565 _tryLoadProvider(ptr);
566 ptr += lstrlenW(ptr) + 1;
569 RegCloseKey(key);
573 SecurePackage *SECUR32_findPackageW(PWSTR packageName)
575 SecurePackage *ret = NULL;
576 BOOL matched = FALSE;
578 if (packageTable && packageName)
580 LIST_FOR_EACH_ENTRY(ret, &packageTable->table, SecurePackage, entry)
582 matched = !lstrcmpiW(ret->infoW.Name, packageName);
583 if (matched)
584 break;
587 if (!matched)
588 return NULL;
590 if (ret->provider && !ret->provider->loaded)
592 ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
593 if (ret->provider->lib)
595 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
596 (INIT_SECURITY_INTERFACE_W)GetProcAddress(ret->provider->lib,
597 SECURITY_ENTRYPOINT_ANSIW);
598 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
599 (INIT_SECURITY_INTERFACE_A)GetProcAddress(ret->provider->lib,
600 SECURITY_ENTRYPOINT_ANSIA);
601 PSecurityFunctionTableA fnTableA = NULL;
602 PSecurityFunctionTableW fnTableW = NULL;
604 if (pInitSecurityInterfaceA)
605 fnTableA = pInitSecurityInterfaceA();
606 if (pInitSecurityInterfaceW)
607 fnTableW = pInitSecurityInterfaceW();
608 _makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW);
609 _makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW);
610 ret->provider->loaded = TRUE;
612 else
613 ret = NULL;
616 return ret;
619 SecurePackage *SECUR32_findPackageA(PSTR packageName)
621 SecurePackage *ret;
623 if (packageTable && packageName)
625 UNICODE_STRING package;
627 RtlCreateUnicodeStringFromAsciiz(&package, packageName);
628 ret = SECUR32_findPackageW(package.Buffer);
629 RtlFreeUnicodeString(&package);
631 else
632 ret = NULL;
633 return ret;
636 static void SECUR32_freeProviders(void)
638 SecurePackage *package;
639 SecureProvider *provider;
641 TRACE("\n");
642 EnterCriticalSection(&cs);
644 if (packageTable)
646 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
648 SECUR32_FREE(package->infoW.Name);
649 SECUR32_FREE(package->infoW.Comment);
652 HeapFree(GetProcessHeap(), 0, packageTable);
653 packageTable = NULL;
656 if (providerTable)
658 LIST_FOR_EACH_ENTRY(provider, &providerTable->table, SecureProvider, entry)
660 if (provider->moduleName)
661 SECUR32_FREE(provider->moduleName);
662 if (provider->lib)
663 FreeLibrary(provider->lib);
666 HeapFree(GetProcessHeap(), 0, providerTable);
667 providerTable = NULL;
670 LeaveCriticalSection(&cs);
671 DeleteCriticalSection(&cs);
674 /***********************************************************************
675 * FreeContextBuffer (SECUR32.@)
677 * Doh--if pv was allocated by a crypto package, this may not be correct.
678 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
679 * be any guarantee, nor is there an alloc function in secur32.
681 SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
683 if (pv) SECUR32_FREE(pv);
685 return SEC_E_OK;
688 /***********************************************************************
689 * EnumerateSecurityPackagesW (SECUR32.@)
691 SECURITY_STATUS WINAPI EnumerateSecurityPackagesW(PULONG pcPackages,
692 PSecPkgInfoW *ppPackageInfo)
694 SECURITY_STATUS ret = SEC_E_OK;
696 TRACE("(%p, %p)\n", pcPackages, ppPackageInfo);
698 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
699 *pcPackages = 0;
700 EnterCriticalSection(&cs);
701 if (packageTable)
703 SecurePackage *package;
704 size_t bytesNeeded;
706 bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
707 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
709 if (package->infoW.Name)
710 bytesNeeded += (lstrlenW(package->infoW.Name) + 1) * sizeof(WCHAR);
711 if (package->infoW.Comment)
712 bytesNeeded += (lstrlenW(package->infoW.Comment) + 1) * sizeof(WCHAR);
714 if (bytesNeeded)
716 *ppPackageInfo = (PSecPkgInfoW)SECUR32_ALLOC(bytesNeeded);
717 if (*ppPackageInfo)
719 ULONG i = 0;
720 PWSTR nextString;
722 *pcPackages = packageTable->numPackages;
723 nextString = (PWSTR)((PBYTE)*ppPackageInfo +
724 packageTable->numPackages * sizeof(SecPkgInfoW));
725 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
727 PSecPkgInfoW pkgInfo = *ppPackageInfo + i++;
729 memcpy(pkgInfo, &package->infoW, sizeof(SecPkgInfoW));
730 if (package->infoW.Name)
732 TRACE("Name[%ld] = %s\n", i - 1, debugstr_w(package->infoW.Name));
733 pkgInfo->Name = nextString;
734 lstrcpyW(nextString, package->infoW.Name);
735 nextString += lstrlenW(nextString) + 1;
737 else
738 pkgInfo->Name = NULL;
739 if (package->infoW.Comment)
741 TRACE("Comment[%ld] = %s\n", i - 1, debugstr_w(package->infoW.Comment));
742 pkgInfo->Comment = nextString;
743 lstrcpyW(nextString, package->infoW.Comment);
744 nextString += lstrlenW(nextString) + 1;
746 else
747 pkgInfo->Comment = NULL;
750 else
751 ret = SEC_E_INSUFFICIENT_MEMORY;
754 LeaveCriticalSection(&cs);
755 TRACE("<-- 0x%08lx\n", ret);
756 return ret;
759 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
760 * structures) into an array of SecPkgInfoA structures, which it returns.
762 static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
763 const PSecPkgInfoW info)
765 PSecPkgInfoA ret;
767 if (info)
769 size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
770 ULONG i;
772 for (i = 0; i < cPackages; i++)
774 if (info[i].Name)
775 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
776 -1, NULL, 0, NULL, NULL);
777 if (info[i].Comment)
778 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
779 -1, NULL, 0, NULL, NULL);
781 ret = (PSecPkgInfoA)SECUR32_ALLOC(bytesNeeded);
782 if (ret)
784 PSTR nextString;
786 nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
787 for (i = 0; i < cPackages; i++)
789 PSecPkgInfoA pkgInfo = ret + i;
790 int bytes;
792 memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
793 if (info[i].Name)
795 pkgInfo->Name = nextString;
796 /* just repeat back to WideCharToMultiByte how many bytes
797 * it requires, since we asked it earlier
799 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
800 NULL, 0, NULL, NULL);
801 WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
802 pkgInfo->Name, bytes, NULL, NULL);
803 nextString += lstrlenA(nextString) + 1;
805 else
806 pkgInfo->Name = NULL;
807 if (info[i].Comment)
809 pkgInfo->Comment = nextString;
810 /* just repeat back to WideCharToMultiByte how many bytes
811 * it requires, since we asked it earlier
813 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
814 NULL, 0, NULL, NULL);
815 WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
816 pkgInfo->Comment, bytes, NULL, NULL);
817 nextString += lstrlenA(nextString) + 1;
819 else
820 pkgInfo->Comment = NULL;
824 else
825 ret = NULL;
826 return ret;
829 /***********************************************************************
830 * EnumerateSecurityPackagesA (SECUR32.@)
832 SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
833 PSecPkgInfoA *ppPackageInfo)
835 SECURITY_STATUS ret;
836 PSecPkgInfoW info;
838 ret = EnumerateSecurityPackagesW(pcPackages, &info);
839 if (ret == SEC_E_OK && *pcPackages && info)
841 *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
842 if (*pcPackages && !*ppPackageInfo)
844 *pcPackages = 0;
845 ret = SEC_E_INSUFFICIENT_MEMORY;
847 FreeContextBuffer(info);
849 return ret;
852 /***********************************************************************
853 * GetComputerObjectNameA (SECUR32.@)
855 BOOLEAN WINAPI GetComputerObjectNameA(
856 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
858 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
859 return FALSE;
862 /***********************************************************************
863 * GetComputerObjectNameW (SECUR32.@)
865 BOOLEAN WINAPI GetComputerObjectNameW(
866 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
868 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
869 return FALSE;
872 BOOLEAN WINAPI GetUserNameExA(
873 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
875 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
876 return FALSE;
879 BOOLEAN WINAPI GetUserNameExW(
880 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
882 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
883 return FALSE;
886 NTSTATUS WINAPI LsaCallAuthenticationPackage(
887 HANDLE LsaHandle, ULONG AuthenticationPackage, PVOID ProtocolSubmitBuffer,
888 ULONG SubmitBufferLength, PVOID* ProtocolReturnBuffer, PULONG ReturnBufferLength,
889 PNTSTATUS ProtocolStatus)
891 FIXME("%p %ld %p %ld %p %p %p\n", LsaHandle, AuthenticationPackage,
892 ProtocolSubmitBuffer, SubmitBufferLength, ProtocolReturnBuffer,
893 ReturnBufferLength, ProtocolStatus);
894 return 0;
897 NTSTATUS WINAPI LsaConnectUntrusted(PHANDLE LsaHandle)
899 FIXME("%p\n", LsaHandle);
900 return 0;
903 NTSTATUS WINAPI LsaDeregisterLogonProcess(HANDLE LsaHandle)
905 FIXME("%p\n", LsaHandle);
906 return 0;
909 BOOLEAN WINAPI TranslateNameA(
910 LPCSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
911 EXTENDED_NAME_FORMAT DesiredNameFormat, LPSTR lpTranslatedName,
912 PULONG nSize)
914 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
915 DesiredNameFormat, lpTranslatedName, nSize);
916 return FALSE;
919 BOOLEAN WINAPI TranslateNameW(
920 LPCWSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
921 EXTENDED_NAME_FORMAT DesiredNameFormat, LPWSTR lpTranslatedName,
922 PULONG nSize)
924 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
925 DesiredNameFormat, lpTranslatedName, nSize);
926 return FALSE;
929 /***********************************************************************
930 * DllMain (SECUR32.0)
932 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
934 if (fdwReason == DLL_PROCESS_ATTACH)
936 DisableThreadLibraryCalls(hinstDLL);
937 SECUR32_initializeProviders();
939 else if (fdwReason == DLL_PROCESS_DETACH)
941 SECUR32_freeProviders();
944 return TRUE;