Get rid of the almost empty tmarshal.h file.
[wine/wine-kai.git] / dlls / secur32 / secur32.c
blob1e89f8d3f67da154c345591acc8ac2e972e4ca88
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/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
37 /**
38 * Type definitions
41 typedef struct _SecurePackageTable
43 DWORD numPackages;
44 DWORD numAllocated;
45 SecurePackage table[1];
46 } SecurePackageTable;
48 typedef struct _SecureProviderTable
50 DWORD numProviders;
51 DWORD numAllocated;
52 SecureProvider table[1];
53 } SecureProviderTable;
55 /**
56 * Prototypes
59 /* Makes sure table has space for at least howBig entries. If table is NULL,
60 * returns a newly allocated table. Otherwise returns the address of the
61 * modified table, which may not be the same was when called.
63 static SecurePackageTable *_resizePackageTable(SecurePackageTable *table,
64 DWORD howBig);
66 /* Makes sure table has space for at least howBig entries. If table is NULL,
67 * returns a newly allocated table. Otherwise returns the address of the
68 * modified table, which may not be the same was when called.
70 static SecureProviderTable *_resizeProviderTable(SecureProviderTable *table,
71 DWORD howBig);
73 /* Tries to load moduleName as a provider. If successful, enumerates what
74 * packages it can and adds them to the package and provider tables. Resizes
75 * tables as necessary.
77 static void _tryLoadProvider(PWSTR moduleName);
79 /* Initialization: read securityproviders value and attempt to open each dll
80 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
81 * Two undocumented functions, AddSecurityPackage(A/W) and
82 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
83 * unregister a dll, but I'm not sure.
85 static void SECUR32_initializeProviders(void);
87 /* Frees all loaded packages and providers */
88 static void SECUR32_freeProviders(void);
90 /**
91 * Globals
94 static CRITICAL_SECTION cs;
95 static SecurePackageTable *packageTable = NULL;
96 static SecureProviderTable *providerTable = NULL;
98 static SecurityFunctionTableA securityFunctionTableA = {
99 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2,
100 EnumerateSecurityPackagesA,
101 QueryCredentialsAttributesA,
102 AcquireCredentialsHandleA,
103 FreeCredentialsHandle,
104 NULL, /* Reserved2 */
105 InitializeSecurityContextA,
106 AcceptSecurityContext,
107 CompleteAuthToken,
108 DeleteSecurityContext,
109 ApplyControlToken,
110 QueryContextAttributesA,
111 ImpersonateSecurityContext,
112 RevertSecurityContext,
113 MakeSignature,
114 VerifySignature,
115 FreeContextBuffer,
116 QuerySecurityPackageInfoA,
117 NULL, /* Reserved3 */
118 NULL, /* Reserved4 */
119 ExportSecurityContext,
120 ImportSecurityContextA,
121 AddCredentialsA,
122 NULL, /* Reserved8 */
123 QuerySecurityContextToken,
124 EncryptMessage,
125 DecryptMessage,
126 SetContextAttributesA
129 static SecurityFunctionTableW securityFunctionTableW = {
130 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2,
131 EnumerateSecurityPackagesW,
132 QueryCredentialsAttributesW,
133 AcquireCredentialsHandleW,
134 FreeCredentialsHandle,
135 NULL, /* Reserved2 */
136 InitializeSecurityContextW,
137 AcceptSecurityContext,
138 CompleteAuthToken,
139 DeleteSecurityContext,
140 ApplyControlToken,
141 QueryContextAttributesW,
142 ImpersonateSecurityContext,
143 RevertSecurityContext,
144 MakeSignature,
145 VerifySignature,
146 FreeContextBuffer,
147 QuerySecurityPackageInfoW,
148 NULL, /* Reserved3 */
149 NULL, /* Reserved4 */
150 ExportSecurityContext,
151 ImportSecurityContextW,
152 AddCredentialsW,
153 NULL, /* Reserved8 */
154 QuerySecurityContextToken,
155 EncryptMessage,
156 DecryptMessage,
157 SetContextAttributesW
160 /***********************************************************************
161 * InitSecurityInterfaceA (SECUR32.@)
163 PSecurityFunctionTableA WINAPI InitSecurityInterfaceA(void)
165 return &securityFunctionTableA;
168 /***********************************************************************
169 * InitSecurityInterfaceW (SECUR32.@)
171 PSecurityFunctionTableW WINAPI InitSecurityInterfaceW(void)
173 return &securityFunctionTableW;
176 /* Allocates or resizes table to have space for at least howBig packages.
177 * Uses Heap functions, because needs to be able to reallocate.
179 static SecurePackageTable *_resizePackageTable(SecurePackageTable *table,
180 DWORD howBig)
182 SecurePackageTable *ret;
184 EnterCriticalSection(&cs);
185 if (table)
187 if (table->numAllocated < howBig)
189 ret = HeapReAlloc(GetProcessHeap(), 0, table,
190 sizeof(SecurePackageTable) + (howBig - 1) * sizeof(SecurePackage));
191 if (ret)
193 ret->numAllocated = howBig;
194 table = ret;
197 else
198 ret = table;
200 else
202 DWORD numAllocated = (howBig > 1 ? howBig : 1);
204 ret = HeapAlloc(GetProcessHeap(), 0,
205 sizeof(SecurePackageTable) +
206 (numAllocated - 1) * sizeof(SecurePackage));
207 if (ret)
209 ret->numAllocated = numAllocated;
210 ret->numPackages = 0;
213 LeaveCriticalSection(&cs);
214 return ret;
217 /* Allocates or resizes table to have space for at least howBig providers.
218 * Uses Heap functions, because needs to be able to reallocate.
220 static SecureProviderTable *_resizeProviderTable(SecureProviderTable *table,
221 DWORD howBig)
223 SecureProviderTable *ret;
225 EnterCriticalSection(&cs);
226 if (table)
228 if (table->numAllocated < howBig)
230 ret = HeapReAlloc(GetProcessHeap(), 0, table,
231 sizeof(SecureProviderTable) +
232 (howBig - 1) * sizeof(SecureProvider));
233 if (ret)
235 ret->numAllocated = howBig;
236 table = ret;
239 else
240 ret = table;
242 else
244 DWORD numAllocated = (howBig > 1 ? howBig : 1);
246 ret = HeapAlloc(GetProcessHeap(), 0,
247 sizeof(SecureProviderTable) +
248 (numAllocated - 1) * sizeof(SecureProvider));
249 if (ret)
251 ret->numAllocated = numAllocated;
252 ret->numProviders = 0;
255 LeaveCriticalSection(&cs);
256 return ret;
259 PWSTR SECUR32_strdupW(PCWSTR str)
261 PWSTR ret;
263 if (str)
265 ret = (PWSTR)SECUR32_ALLOC((lstrlenW(str) + 1) * sizeof(WCHAR));
266 if (ret)
267 lstrcpyW(ret, str);
269 else
270 ret = NULL;
271 return ret;
274 PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str)
276 PWSTR ret;
278 if (str)
280 int charsNeeded = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
282 if (charsNeeded)
284 ret = (PWSTR)SECUR32_ALLOC(charsNeeded * sizeof(WCHAR));
285 if (ret)
286 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, charsNeeded);
288 else
289 ret = NULL;
291 else
292 ret = NULL;
293 return ret;
296 PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str)
298 PSTR ret;
300 if (str)
302 int charsNeeded = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0,
303 NULL, NULL);
305 if (charsNeeded)
307 ret = (PSTR)SECUR32_ALLOC(charsNeeded);
308 if (ret)
309 WideCharToMultiByte(CP_ACP, 0, str, -1, ret, charsNeeded,
310 NULL, NULL);
312 else
313 ret = NULL;
315 else
316 ret = NULL;
317 return ret;
320 static void _makeFnTableA(PSecurityFunctionTableA fnTableA,
321 const PSecurityFunctionTableA inFnTableA,
322 const PSecurityFunctionTableW inFnTableW)
324 if (fnTableA)
326 if (inFnTableA)
328 /* The size of the version 1 table is based on platform sdk's
329 * sspi.h, though the sample ssp also provided with platform sdk
330 * implies only functions through QuerySecurityPackageInfoA are
331 * implemented (yikes)
333 size_t tableSize = inFnTableA->dwVersion == 1 ?
334 (LPBYTE)&inFnTableA->SetContextAttributesA -
335 (LPBYTE)inFnTableA : sizeof(SecurityFunctionTableA);
337 memcpy(fnTableA, inFnTableA, tableSize);
338 /* override this, since we can do it internally anyway */
339 fnTableA->QuerySecurityPackageInfoA =
340 QuerySecurityPackageInfoA;
342 else if (inFnTableW)
344 /* functions with thunks */
345 if (inFnTableW->AcquireCredentialsHandleW)
346 fnTableA->AcquireCredentialsHandleA =
347 thunk_AcquireCredentialsHandleA;
348 if (inFnTableW->InitializeSecurityContextW)
349 fnTableA->InitializeSecurityContextA =
350 thunk_InitializeSecurityContextA;
351 if (inFnTableW->ImportSecurityContextW)
352 fnTableA->ImportSecurityContextA =
353 thunk_ImportSecurityContextA;
354 if (inFnTableW->AddCredentialsW)
355 fnTableA->AddCredentialsA =
356 thunk_AddCredentialsA;
357 if (inFnTableW->QueryCredentialsAttributesW)
358 fnTableA->QueryCredentialsAttributesA =
359 thunk_QueryCredentialsAttributesA;
360 if (inFnTableW->QueryContextAttributesW)
361 fnTableA->QueryContextAttributesA =
362 thunk_QueryContextAttributesA;
363 if (inFnTableW->SetContextAttributesW)
364 fnTableA->SetContextAttributesA =
365 thunk_SetContextAttributesA;
366 /* this can't be thunked, there's no extra param to know which
367 * package to forward to */
368 fnTableA->EnumerateSecurityPackagesA = NULL;
369 /* functions with no thunks needed */
370 fnTableA->AcceptSecurityContext = inFnTableW->AcceptSecurityContext;
371 fnTableA->CompleteAuthToken = inFnTableW->CompleteAuthToken;
372 fnTableA->DeleteSecurityContext = inFnTableW->DeleteSecurityContext;
373 fnTableA->ImpersonateSecurityContext =
374 inFnTableW->ImpersonateSecurityContext;
375 fnTableA->RevertSecurityContext = inFnTableW->RevertSecurityContext;
376 fnTableA->MakeSignature = inFnTableW->MakeSignature;
377 fnTableA->VerifySignature = inFnTableW->VerifySignature;
378 fnTableA->FreeContextBuffer = inFnTableW->FreeContextBuffer;
379 fnTableA->QuerySecurityPackageInfoA =
380 QuerySecurityPackageInfoA;
381 fnTableA->ExportSecurityContext =
382 inFnTableW->ExportSecurityContext;
383 fnTableA->QuerySecurityContextToken =
384 inFnTableW->QuerySecurityContextToken;
385 fnTableA->EncryptMessage = inFnTableW->EncryptMessage;
386 fnTableA->DecryptMessage = inFnTableW->DecryptMessage;
391 static void _makeFnTableW(PSecurityFunctionTableW fnTableW,
392 const PSecurityFunctionTableA inFnTableA,
393 const PSecurityFunctionTableW inFnTableW)
395 if (fnTableW)
397 if (inFnTableW)
399 /* The size of the version 1 table is based on platform sdk's
400 * sspi.h, though the sample ssp also provided with platform sdk
401 * implies only functions through QuerySecurityPackageInfoA are
402 * implemented (yikes)
404 size_t tableSize = inFnTableW->dwVersion == 1 ?
405 (LPBYTE)&inFnTableW->SetContextAttributesW -
406 (LPBYTE)inFnTableW : sizeof(SecurityFunctionTableW);
408 memcpy(fnTableW, inFnTableW, tableSize);
409 /* override this, since we can do it internally anyway */
410 fnTableW->QuerySecurityPackageInfoW =
411 QuerySecurityPackageInfoW;
413 else if (inFnTableA)
415 /* functions with thunks */
416 if (inFnTableA->AcquireCredentialsHandleA)
417 fnTableW->AcquireCredentialsHandleW =
418 thunk_AcquireCredentialsHandleW;
419 if (inFnTableA->InitializeSecurityContextA)
420 fnTableW->InitializeSecurityContextW =
421 thunk_InitializeSecurityContextW;
422 if (inFnTableA->ImportSecurityContextA)
423 fnTableW->ImportSecurityContextW =
424 thunk_ImportSecurityContextW;
425 if (inFnTableA->AddCredentialsA)
426 fnTableW->AddCredentialsW =
427 thunk_AddCredentialsW;
428 if (inFnTableA->QueryCredentialsAttributesA)
429 fnTableW->QueryCredentialsAttributesW =
430 thunk_QueryCredentialsAttributesW;
431 if (inFnTableA->QueryContextAttributesA)
432 fnTableW->QueryContextAttributesW =
433 thunk_QueryContextAttributesW;
434 if (inFnTableA->SetContextAttributesA)
435 fnTableW->SetContextAttributesW =
436 thunk_SetContextAttributesW;
437 /* this can't be thunked, there's no extra param to know which
438 * package to forward to */
439 fnTableW->EnumerateSecurityPackagesW = NULL;
440 /* functions with no thunks needed */
441 fnTableW->AcceptSecurityContext = inFnTableA->AcceptSecurityContext;
442 fnTableW->CompleteAuthToken = inFnTableA->CompleteAuthToken;
443 fnTableW->DeleteSecurityContext = inFnTableA->DeleteSecurityContext;
444 fnTableW->ImpersonateSecurityContext =
445 inFnTableA->ImpersonateSecurityContext;
446 fnTableW->RevertSecurityContext = inFnTableA->RevertSecurityContext;
447 fnTableW->MakeSignature = inFnTableA->MakeSignature;
448 fnTableW->VerifySignature = inFnTableA->VerifySignature;
449 fnTableW->FreeContextBuffer = inFnTableA->FreeContextBuffer;
450 fnTableW->QuerySecurityPackageInfoW =
451 QuerySecurityPackageInfoW;
452 fnTableW->ExportSecurityContext =
453 inFnTableA->ExportSecurityContext;
454 fnTableW->QuerySecurityContextToken =
455 inFnTableA->QuerySecurityContextToken;
456 fnTableW->EncryptMessage = inFnTableA->EncryptMessage;
457 fnTableW->DecryptMessage = inFnTableA->DecryptMessage;
462 static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA,
463 const SecPkgInfoW *inInfoW)
465 if (info && (inInfoA || inInfoW))
467 /* odd, I know, but up until Name and Comment the structures are
468 * identical
470 memcpy(info, inInfoW ? inInfoW : (PSecPkgInfoW)inInfoA, sizeof(*info));
471 if (inInfoW)
473 info->Name = SECUR32_strdupW(inInfoW->Name);
474 info->Comment = SECUR32_strdupW(inInfoW->Comment);
476 else
478 info->Name = SECUR32_AllocWideFromMultiByte(inInfoA->Name);
479 info->Comment = SECUR32_AllocWideFromMultiByte(inInfoA->Comment);
484 SecureProvider *SECUR32_addProvider(PSecurityFunctionTableA fnTableA,
485 PSecurityFunctionTableW fnTableW, PWSTR moduleName)
487 SecureProvider *ret;
489 EnterCriticalSection(&cs);
490 providerTable = _resizeProviderTable(providerTable,
491 providerTable ? providerTable->numProviders + 1 : 1);
492 if (providerTable)
494 ret = &providerTable->table[providerTable->numProviders++];
495 ret->lib = NULL;
496 if (fnTableA || fnTableW)
498 _makeFnTableA(&ret->fnTableA, fnTableA, fnTableW);
499 _makeFnTableW(&ret->fnTableW, fnTableA, fnTableW);
500 ret->loaded = TRUE;
502 else
504 ret->moduleName = SECUR32_strdupW(moduleName);
505 ret->loaded = FALSE;
508 else
509 ret = NULL;
510 LeaveCriticalSection(&cs);
511 return ret;
514 void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
515 const SecPkgInfoA *infoA, const SecPkgInfoW *infoW)
517 assert(provider);
518 assert(infoA || infoW);
520 EnterCriticalSection(&cs);
521 packageTable = _resizePackageTable(packageTable,
522 packageTable ? packageTable->numPackages + toAdd : toAdd);
523 if (packageTable)
525 ULONG i;
527 for (i = 0; i < toAdd; i++)
529 SecurePackage *package =
530 &packageTable->table[packageTable->numPackages + i];
532 package->provider = provider;
533 _copyPackageInfo(&package->infoW,
534 infoA ? &infoA[i] : NULL,
535 infoW ? &infoW[i] : NULL);
537 packageTable->numPackages += toAdd;
539 LeaveCriticalSection(&cs);
542 static void _tryLoadProvider(PWSTR moduleName)
544 HMODULE lib = LoadLibraryW(moduleName);
546 if (lib)
548 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
549 (INIT_SECURITY_INTERFACE_W)GetProcAddress(lib,
550 SECURITY_ENTRYPOINT_ANSIW);
551 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
552 (INIT_SECURITY_INTERFACE_A)GetProcAddress(lib,
553 SECURITY_ENTRYPOINT_ANSIA);
555 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
556 debugstr_w(moduleName), pInitSecurityInterfaceA,
557 pInitSecurityInterfaceW);
558 if (pInitSecurityInterfaceW || pInitSecurityInterfaceA)
560 PSecurityFunctionTableA fnTableA = NULL;
561 PSecurityFunctionTableW fnTableW = NULL;
562 ULONG toAdd = 0;
563 PSecPkgInfoA infoA = NULL;
564 PSecPkgInfoW infoW = NULL;
565 SECURITY_STATUS ret = SEC_E_OK;
567 if (pInitSecurityInterfaceA)
568 fnTableA = pInitSecurityInterfaceA();
569 if (pInitSecurityInterfaceW)
570 fnTableW = pInitSecurityInterfaceW();
571 if (fnTableW && fnTableW->EnumerateSecurityPackagesW)
572 ret = fnTableW->EnumerateSecurityPackagesW(&toAdd, &infoW);
573 else if (fnTableA && fnTableA->EnumerateSecurityPackagesA)
574 ret = fnTableA->EnumerateSecurityPackagesA(&toAdd, &infoA);
575 if (ret == SEC_E_OK && toAdd > 0 && (infoW || infoA))
577 SecureProvider *provider = SECUR32_addProvider(NULL, NULL,
578 moduleName);
580 if (provider)
581 SECUR32_addPackages(provider, toAdd, infoA, infoW);
582 if (infoW)
583 fnTableW->FreeContextBuffer(infoW);
584 else
585 fnTableA->FreeContextBuffer(infoA);
588 FreeLibrary(lib);
590 else
591 WARN("failed to load %s\n", debugstr_w(moduleName));
594 static const WCHAR securityProvidersKeyW[] = {
595 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
596 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
597 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
599 static const WCHAR securityProvidersW[] = {
600 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
603 static void SECUR32_initializeProviders(void)
605 HKEY key;
606 long apiRet;
608 TRACE("\n");
609 InitializeCriticalSection(&cs);
610 /* First load built-in providers */
611 SECUR32_initSchannelSP();
612 /* Now load providers from registry */
613 apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
614 KEY_READ, &key);
615 if (apiRet == ERROR_SUCCESS)
617 WCHAR securityPkgNames[MAX_PATH]; /* arbitrary len */
618 DWORD size = sizeof(securityPkgNames) / sizeof(WCHAR), type;
620 apiRet = RegQueryValueExW(key, securityProvidersW, NULL, &type,
621 (PBYTE)securityPkgNames, &size);
622 if (apiRet == ERROR_SUCCESS && type == REG_SZ)
624 WCHAR *ptr;
626 for (ptr = securityPkgNames;
627 ptr < (PWSTR)((PBYTE)securityPkgNames + size); )
629 WCHAR *comma;
631 for (comma = ptr; *comma && *comma != ','; comma++)
633 if (*comma == ',')
634 *comma = '\0';
635 for (; *ptr && isspace(*ptr) && ptr < securityPkgNames + size;
636 ptr++)
638 if (*ptr)
639 _tryLoadProvider(ptr);
640 ptr += lstrlenW(ptr) + 1;
643 RegCloseKey(key);
647 SecurePackage *SECUR32_findPackageW(PWSTR packageName)
649 SecurePackage *ret = NULL;
651 if (packageTable && packageName)
653 DWORD i;
655 for (i = 0, ret = NULL; !ret && i < packageTable->numPackages; i++)
656 if (!lstrcmpiW(packageTable->table[i].infoW.Name, packageName))
657 ret = &packageTable->table[i];
658 if (ret && ret->provider && !ret->provider->loaded)
660 ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
661 if (ret->provider->lib)
663 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
664 (INIT_SECURITY_INTERFACE_W)GetProcAddress(ret->provider->lib,
665 SECURITY_ENTRYPOINT_ANSIW);
666 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
667 (INIT_SECURITY_INTERFACE_A)GetProcAddress(ret->provider->lib,
668 SECURITY_ENTRYPOINT_ANSIA);
669 PSecurityFunctionTableA fnTableA = NULL;
670 PSecurityFunctionTableW fnTableW = NULL;
672 if (pInitSecurityInterfaceA)
673 fnTableA = pInitSecurityInterfaceA();
674 if (pInitSecurityInterfaceW)
675 fnTableW = pInitSecurityInterfaceW();
676 _makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW);
677 _makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW);
678 ret->provider->loaded = TRUE;
680 else
681 ret = NULL;
684 return ret;
687 SecurePackage *SECUR32_findPackageA(PSTR packageName)
689 SecurePackage *ret;
691 if (packageTable && packageName)
693 UNICODE_STRING package;
695 RtlCreateUnicodeStringFromAsciiz(&package, packageName);
696 ret = SECUR32_findPackageW(package.Buffer);
697 RtlFreeUnicodeString(&package);
699 else
700 ret = NULL;
701 return ret;
704 static void SECUR32_freeProviders(void)
706 DWORD i;
708 TRACE("\n");
709 EnterCriticalSection(&cs);
710 if (packageTable)
712 for (i = 0; i < packageTable->numPackages; i++)
714 SECUR32_FREE(packageTable->table[i].infoW.Name);
715 SECUR32_FREE(packageTable->table[i].infoW.Comment);
717 HeapFree(GetProcessHeap(), 0, packageTable);
718 packageTable = NULL;
720 if (providerTable)
722 for (i = 0; i < providerTable->numProviders; i++)
724 if (providerTable->table[i].moduleName)
725 SECUR32_FREE(providerTable->table[i].moduleName);
726 if (providerTable->table[i].lib)
727 FreeLibrary(providerTable->table[i].lib);
729 HeapFree(GetProcessHeap(), 0, providerTable);
730 providerTable = NULL;
732 LeaveCriticalSection(&cs);
733 DeleteCriticalSection(&cs);
736 /***********************************************************************
737 * FreeContextBuffer (SECUR32.@)
739 * Doh--if pv was allocated by a crypto package, this may not be correct.
740 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
741 * be any guarantee, nor is there an alloc function in secur32.
743 SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
745 SECURITY_STATUS ret;
747 /* as it turns out, SECURITY_STATUSes are actually HRESULTS */
748 if (pv)
750 if (SECUR32_FREE(pv) == NULL)
751 ret = SEC_E_OK;
752 else
753 ret = HRESULT_FROM_WIN32(GetLastError());
755 else
756 ret = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
757 return ret;
760 /***********************************************************************
761 * EnumerateSecurityPackagesW (SECUR32.@)
763 SECURITY_STATUS WINAPI EnumerateSecurityPackagesW(PULONG pcPackages,
764 PSecPkgInfoW *ppPackageInfo)
766 SECURITY_STATUS ret = SEC_E_OK;
768 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
769 *pcPackages = 0;
770 EnterCriticalSection(&cs);
771 if (packageTable)
773 ULONG i;
774 size_t bytesNeeded;
776 bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
777 for (i = 0; i < packageTable->numPackages; i++)
779 if (packageTable->table[i].infoW.Name)
780 bytesNeeded +=
781 (lstrlenW(packageTable->table[i].infoW.Name) + 1) *
782 sizeof(WCHAR);
783 if (packageTable->table[i].infoW.Comment)
784 bytesNeeded +=
785 (lstrlenW(packageTable->table[i].infoW.Comment) + 1) *
786 sizeof(WCHAR);
788 if (bytesNeeded)
790 *ppPackageInfo = (PSecPkgInfoW)SECUR32_ALLOC(bytesNeeded);
791 if (*ppPackageInfo)
793 PWSTR nextString;
795 *pcPackages = packageTable->numPackages;
796 nextString = (PWSTR)((PBYTE)*ppPackageInfo +
797 packageTable->numPackages * sizeof(SecPkgInfoW));
798 for (i = 0; i < packageTable->numPackages; i++)
800 PSecPkgInfoW pkgInfo = *ppPackageInfo + i;
802 memcpy(pkgInfo, &packageTable->table[i].infoW,
803 sizeof(SecPkgInfoW));
804 if (packageTable->table[i].infoW.Name)
806 pkgInfo->Name = nextString;
807 lstrcpyW(nextString, packageTable->table[i].infoW.Name);
808 nextString += lstrlenW(nextString) + 1;
810 else
811 pkgInfo->Name = NULL;
812 if (packageTable->table[i].infoW.Comment)
814 pkgInfo->Comment = nextString;
815 lstrcpyW(nextString,
816 packageTable->table[i].infoW.Comment);
817 nextString += lstrlenW(nextString) + 1;
819 else
820 pkgInfo->Comment = NULL;
823 else
824 ret = SEC_E_INSUFFICIENT_MEMORY;
827 LeaveCriticalSection(&cs);
828 return ret;
831 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
832 * structures) into an array of SecPkgInfoA structures, which it returns.
834 static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
835 const PSecPkgInfoW info)
837 PSecPkgInfoA ret;
839 if (info)
841 size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
842 ULONG i;
844 for (i = 0; i < cPackages; i++)
846 if (info[i].Name)
847 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
848 -1, NULL, 0, NULL, NULL);
849 if (info[i].Comment)
850 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
851 -1, NULL, 0, NULL, NULL);
853 ret = (PSecPkgInfoA)SECUR32_ALLOC(bytesNeeded);
854 if (ret)
856 PSTR nextString;
858 nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
859 for (i = 0; i < cPackages; i++)
861 PSecPkgInfoA pkgInfo = ret + i;
862 int bytes;
864 memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
865 if (info[i].Name)
867 pkgInfo->Name = nextString;
868 /* just repeat back to WideCharToMultiByte how many bytes
869 * it requires, since we asked it earlier
871 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
872 NULL, 0, NULL, NULL);
873 WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
874 pkgInfo->Name, bytes, NULL, NULL);
875 nextString += lstrlenA(nextString) + 1;
877 else
878 pkgInfo->Name = NULL;
879 if (info[i].Comment)
881 pkgInfo->Comment = nextString;
882 /* just repeat back to WideCharToMultiByte how many bytes
883 * it requires, since we asked it earlier
885 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
886 NULL, 0, NULL, NULL);
887 WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
888 pkgInfo->Comment, bytes, NULL, NULL);
889 nextString += lstrlenA(nextString) + 1;
891 else
892 pkgInfo->Comment = NULL;
896 else
897 ret = NULL;
898 return ret;
901 /***********************************************************************
902 * EnumerateSecurityPackagesA (SECUR32.@)
904 SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
905 PSecPkgInfoA *ppPackageInfo)
907 SECURITY_STATUS ret;
908 PSecPkgInfoW info;
910 ret = EnumerateSecurityPackagesW(pcPackages, &info);
911 if (ret == SEC_E_OK && *pcPackages && info)
913 *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
914 if (*pcPackages && !*ppPackageInfo)
916 *pcPackages = 0;
917 ret = SEC_E_INSUFFICIENT_MEMORY;
919 FreeContextBuffer(info);
921 return ret;
924 /***********************************************************************
925 * GetComputerObjectNameA (SECUR32.@)
927 BOOLEAN WINAPI GetComputerObjectNameA(
928 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
930 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
931 return FALSE;
934 /***********************************************************************
935 * GetComputerObjectNameW (SECUR32.@)
937 BOOLEAN WINAPI GetComputerObjectNameW(
938 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
940 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
941 return FALSE;
944 BOOLEAN WINAPI GetUserNameExA(
945 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
947 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
948 return FALSE;
951 BOOLEAN WINAPI GetUserNameExW(
952 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
954 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
955 return FALSE;
958 NTSTATUS WINAPI LsaCallAuthenticationPackage(
959 HANDLE LsaHandle, ULONG AuthenticationPackage, PVOID ProtocolSubmitBuffer,
960 ULONG SubmitBufferLength, PVOID* ProtocolReturnBuffer, PULONG ReturnBufferLength,
961 NTSTATUS *ProtocolStatus)
963 FIXME("%p %ld %p %ld %p %p %p\n", LsaHandle, AuthenticationPackage,
964 ProtocolSubmitBuffer, SubmitBufferLength, ProtocolReturnBuffer,
965 ReturnBufferLength, ProtocolStatus);
966 return 0;
969 NTSTATUS WINAPI LsaConnectUntrusted(PHANDLE LsaHandle)
971 FIXME("%p\n", LsaHandle);
972 return 0;
975 NTSTATUS WINAPI LsaDeregisterLogonProcess(HANDLE LsaHandle)
977 FIXME("%p\n", LsaHandle);
978 return 0;
981 BOOLEAN WINAPI TranslateNameA(
982 LPCSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
983 EXTENDED_NAME_FORMAT DesiredNameFormat, LPSTR lpTranslatedName,
984 PULONG nSize)
986 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
987 DesiredNameFormat, lpTranslatedName, nSize);
988 return FALSE;
991 BOOLEAN WINAPI TranslateNameW(
992 LPCWSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
993 EXTENDED_NAME_FORMAT DesiredNameFormat, LPWSTR lpTranslatedName,
994 PULONG nSize)
996 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
997 DesiredNameFormat, lpTranslatedName, nSize);
998 return FALSE;
1001 /***********************************************************************
1002 * DllMain (SECUR32.0)
1004 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1006 if (fdwReason == DLL_PROCESS_ATTACH)
1008 DisableThreadLibraryCalls(hinstDLL);
1009 SECUR32_initializeProviders();
1011 else if (fdwReason == DLL_PROCESS_DETACH)
1013 SECUR32_freeProviders();
1016 return TRUE;