1 /* Copyright (C) 2004 Juan Lang
3 * This file implements loading of SSP DLLs.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define WIN32_NO_STATUS
31 #include "secur32_priv.h"
37 #include "wine/list.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(secur32
);
47 typedef struct _SecurePackageTable
54 typedef struct _SecureProviderTable
59 } SecureProviderTable
;
65 /* Tries to load moduleName as a provider. If successful, enumerates what
66 * packages it can and adds them to the package and provider tables. Resizes
67 * tables as necessary.
69 static void _tryLoadProvider(PWSTR moduleName
);
71 /* Initialization: read securityproviders value and attempt to open each dll
72 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
73 * Two undocumented functions, AddSecurityPackage(A/W) and
74 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
75 * unregister a dll, but I'm not sure.
77 static void SECUR32_initializeProviders(void);
79 /* Frees all loaded packages and providers */
80 static void SECUR32_freeProviders(void);
86 static CRITICAL_SECTION cs
;
87 static CRITICAL_SECTION_DEBUG cs_debug
=
90 { &cs_debug
.ProcessLocksList
, &cs_debug
.ProcessLocksList
},
91 0, 0, { (DWORD_PTR
)(__FILE__
": cs") }
93 static CRITICAL_SECTION cs
= { &cs_debug
, -1, 0, 0, 0, 0 };
94 static SecurePackageTable
*packageTable
= NULL
;
95 static SecureProviderTable
*providerTable
= NULL
;
97 static SecurityFunctionTableA securityFunctionTableA
= {
98 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
99 EnumerateSecurityPackagesA
,
100 QueryCredentialsAttributesA
,
101 AcquireCredentialsHandleA
,
102 FreeCredentialsHandle
,
103 NULL
, /* Reserved2 */
104 InitializeSecurityContextA
,
105 AcceptSecurityContext
,
107 DeleteSecurityContext
,
109 QueryContextAttributesA
,
110 ImpersonateSecurityContext
,
111 RevertSecurityContext
,
115 QuerySecurityPackageInfoA
,
116 EncryptMessage
, /* Reserved3 */
117 DecryptMessage
, /* Reserved4 */
118 ExportSecurityContext
,
119 ImportSecurityContextA
,
121 NULL
, /* Reserved8 */
122 QuerySecurityContextToken
,
125 SetContextAttributesA
128 static SecurityFunctionTableW securityFunctionTableW
= {
129 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
130 EnumerateSecurityPackagesW
,
131 QueryCredentialsAttributesW
,
132 AcquireCredentialsHandleW
,
133 FreeCredentialsHandle
,
134 NULL
, /* Reserved2 */
135 InitializeSecurityContextW
,
136 AcceptSecurityContext
,
138 DeleteSecurityContext
,
140 QueryContextAttributesW
,
141 ImpersonateSecurityContext
,
142 RevertSecurityContext
,
146 QuerySecurityPackageInfoW
,
147 EncryptMessage
, /* Reserved3 */
148 DecryptMessage
, /* Reserved4 */
149 ExportSecurityContext
,
150 ImportSecurityContextW
,
152 NULL
, /* Reserved8 */
153 QuerySecurityContextToken
,
156 SetContextAttributesW
159 /***********************************************************************
160 * InitSecurityInterfaceA (SECUR32.@)
162 PSecurityFunctionTableA WINAPI
InitSecurityInterfaceA(void)
164 return &securityFunctionTableA
;
167 /***********************************************************************
168 * InitSecurityInterfaceW (SECUR32.@)
170 PSecurityFunctionTableW WINAPI
InitSecurityInterfaceW(void)
172 return &securityFunctionTableW
;
175 static PWSTR
SECUR32_strdupW(PCWSTR str
)
181 ret
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str
) + 1) * sizeof(WCHAR
));
190 PWSTR
SECUR32_AllocWideFromMultiByte(PCSTR str
)
196 int charsNeeded
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
200 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
* sizeof(WCHAR
));
202 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, charsNeeded
);
212 PSTR
SECUR32_AllocMultiByteFromWide(PCWSTR str
)
218 int charsNeeded
= WideCharToMultiByte(CP_ACP
, 0, str
, -1, NULL
, 0,
223 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
);
225 WideCharToMultiByte(CP_ACP
, 0, str
, -1, ret
, charsNeeded
,
236 static void _makeFnTableA(PSecurityFunctionTableA fnTableA
,
237 const SecurityFunctionTableA
*inFnTableA
,
238 const SecurityFunctionTableW
*inFnTableW
)
244 /* The size of the version 1 table is based on platform sdk's
245 * sspi.h, though the sample ssp also provided with platform sdk
246 * implies only functions through QuerySecurityPackageInfoA are
247 * implemented (yikes)
249 size_t tableSize
= inFnTableA
->dwVersion
== 1 ?
250 (const BYTE
*)&inFnTableA
->SetContextAttributesA
-
251 (const BYTE
*)inFnTableA
: sizeof(SecurityFunctionTableA
);
253 memcpy(fnTableA
, inFnTableA
, tableSize
);
254 /* override this, since we can do it internally anyway */
255 fnTableA
->QuerySecurityPackageInfoA
=
256 QuerySecurityPackageInfoA
;
260 /* functions with thunks */
261 if (inFnTableW
->AcquireCredentialsHandleW
)
262 fnTableA
->AcquireCredentialsHandleA
=
263 thunk_AcquireCredentialsHandleA
;
264 if (inFnTableW
->InitializeSecurityContextW
)
265 fnTableA
->InitializeSecurityContextA
=
266 thunk_InitializeSecurityContextA
;
267 if (inFnTableW
->ImportSecurityContextW
)
268 fnTableA
->ImportSecurityContextA
=
269 thunk_ImportSecurityContextA
;
270 if (inFnTableW
->AddCredentialsW
)
271 fnTableA
->AddCredentialsA
=
272 thunk_AddCredentialsA
;
273 if (inFnTableW
->QueryCredentialsAttributesW
)
274 fnTableA
->QueryCredentialsAttributesA
=
275 thunk_QueryCredentialsAttributesA
;
276 if (inFnTableW
->QueryContextAttributesW
)
277 fnTableA
->QueryContextAttributesA
=
278 thunk_QueryContextAttributesA
;
279 if (inFnTableW
->SetContextAttributesW
)
280 fnTableA
->SetContextAttributesA
=
281 thunk_SetContextAttributesA
;
282 /* this can't be thunked, there's no extra param to know which
283 * package to forward to */
284 fnTableA
->EnumerateSecurityPackagesA
= NULL
;
285 /* functions with no thunks needed */
286 fnTableA
->AcceptSecurityContext
= inFnTableW
->AcceptSecurityContext
;
287 fnTableA
->CompleteAuthToken
= inFnTableW
->CompleteAuthToken
;
288 fnTableA
->DeleteSecurityContext
= inFnTableW
->DeleteSecurityContext
;
289 fnTableA
->ImpersonateSecurityContext
=
290 inFnTableW
->ImpersonateSecurityContext
;
291 fnTableA
->RevertSecurityContext
= inFnTableW
->RevertSecurityContext
;
292 fnTableA
->MakeSignature
= inFnTableW
->MakeSignature
;
293 fnTableA
->VerifySignature
= inFnTableW
->VerifySignature
;
294 fnTableA
->FreeContextBuffer
= inFnTableW
->FreeContextBuffer
;
295 fnTableA
->QuerySecurityPackageInfoA
=
296 QuerySecurityPackageInfoA
;
297 fnTableA
->ExportSecurityContext
=
298 inFnTableW
->ExportSecurityContext
;
299 fnTableA
->QuerySecurityContextToken
=
300 inFnTableW
->QuerySecurityContextToken
;
301 fnTableA
->EncryptMessage
= inFnTableW
->EncryptMessage
;
302 fnTableA
->DecryptMessage
= inFnTableW
->DecryptMessage
;
307 static void _makeFnTableW(PSecurityFunctionTableW fnTableW
,
308 const SecurityFunctionTableA
*inFnTableA
,
309 const SecurityFunctionTableW
*inFnTableW
)
315 /* The size of the version 1 table is based on platform sdk's
316 * sspi.h, though the sample ssp also provided with platform sdk
317 * implies only functions through QuerySecurityPackageInfoA are
318 * implemented (yikes)
320 size_t tableSize
= inFnTableW
->dwVersion
== 1 ?
321 (const BYTE
*)&inFnTableW
->SetContextAttributesW
-
322 (const BYTE
*)inFnTableW
: sizeof(SecurityFunctionTableW
);
324 memcpy(fnTableW
, inFnTableW
, tableSize
);
325 /* override this, since we can do it internally anyway */
326 fnTableW
->QuerySecurityPackageInfoW
=
327 QuerySecurityPackageInfoW
;
331 /* functions with thunks */
332 if (inFnTableA
->AcquireCredentialsHandleA
)
333 fnTableW
->AcquireCredentialsHandleW
=
334 thunk_AcquireCredentialsHandleW
;
335 if (inFnTableA
->InitializeSecurityContextA
)
336 fnTableW
->InitializeSecurityContextW
=
337 thunk_InitializeSecurityContextW
;
338 if (inFnTableA
->ImportSecurityContextA
)
339 fnTableW
->ImportSecurityContextW
=
340 thunk_ImportSecurityContextW
;
341 if (inFnTableA
->AddCredentialsA
)
342 fnTableW
->AddCredentialsW
=
343 thunk_AddCredentialsW
;
344 if (inFnTableA
->QueryCredentialsAttributesA
)
345 fnTableW
->QueryCredentialsAttributesW
=
346 thunk_QueryCredentialsAttributesW
;
347 if (inFnTableA
->QueryContextAttributesA
)
348 fnTableW
->QueryContextAttributesW
=
349 thunk_QueryContextAttributesW
;
350 if (inFnTableA
->SetContextAttributesA
)
351 fnTableW
->SetContextAttributesW
=
352 thunk_SetContextAttributesW
;
353 /* this can't be thunked, there's no extra param to know which
354 * package to forward to */
355 fnTableW
->EnumerateSecurityPackagesW
= NULL
;
356 /* functions with no thunks needed */
357 fnTableW
->AcceptSecurityContext
= inFnTableA
->AcceptSecurityContext
;
358 fnTableW
->CompleteAuthToken
= inFnTableA
->CompleteAuthToken
;
359 fnTableW
->DeleteSecurityContext
= inFnTableA
->DeleteSecurityContext
;
360 fnTableW
->ImpersonateSecurityContext
=
361 inFnTableA
->ImpersonateSecurityContext
;
362 fnTableW
->RevertSecurityContext
= inFnTableA
->RevertSecurityContext
;
363 fnTableW
->MakeSignature
= inFnTableA
->MakeSignature
;
364 fnTableW
->VerifySignature
= inFnTableA
->VerifySignature
;
365 fnTableW
->FreeContextBuffer
= inFnTableA
->FreeContextBuffer
;
366 fnTableW
->QuerySecurityPackageInfoW
=
367 QuerySecurityPackageInfoW
;
368 fnTableW
->ExportSecurityContext
=
369 inFnTableA
->ExportSecurityContext
;
370 fnTableW
->QuerySecurityContextToken
=
371 inFnTableA
->QuerySecurityContextToken
;
372 fnTableW
->EncryptMessage
= inFnTableA
->EncryptMessage
;
373 fnTableW
->DecryptMessage
= inFnTableA
->DecryptMessage
;
378 static void _copyPackageInfo(PSecPkgInfoW info
, const SecPkgInfoA
*inInfoA
,
379 const SecPkgInfoW
*inInfoW
)
381 if (info
&& (inInfoA
|| inInfoW
))
383 /* odd, I know, but up until Name and Comment the structures are
386 memcpy(info
, inInfoW
? inInfoW
: (const SecPkgInfoW
*)inInfoA
, sizeof(*info
));
389 info
->Name
= SECUR32_strdupW(inInfoW
->Name
);
390 info
->Comment
= SECUR32_strdupW(inInfoW
->Comment
);
394 info
->Name
= SECUR32_AllocWideFromMultiByte(inInfoA
->Name
);
395 info
->Comment
= SECUR32_AllocWideFromMultiByte(inInfoA
->Comment
);
400 SecureProvider
*SECUR32_addProvider(const SecurityFunctionTableA
*fnTableA
,
401 const SecurityFunctionTableW
*fnTableW
, PCWSTR moduleName
)
405 EnterCriticalSection(&cs
);
409 providerTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable
));
412 LeaveCriticalSection(&cs
);
416 list_init(&providerTable
->table
);
419 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider
));
422 LeaveCriticalSection(&cs
);
426 list_add_tail(&providerTable
->table
, &ret
->entry
);
429 if (fnTableA
|| fnTableW
)
431 ret
->moduleName
= moduleName
? SECUR32_strdupW(moduleName
) : NULL
;
432 _makeFnTableA(&ret
->fnTableA
, fnTableA
, fnTableW
);
433 _makeFnTableW(&ret
->fnTableW
, fnTableA
, fnTableW
);
434 ret
->loaded
= !moduleName
;
438 ret
->moduleName
= SECUR32_strdupW(moduleName
);
442 LeaveCriticalSection(&cs
);
446 void SECUR32_addPackages(SecureProvider
*provider
, ULONG toAdd
,
447 const SecPkgInfoA
*infoA
, const SecPkgInfoW
*infoW
)
452 assert(infoA
|| infoW
);
454 EnterCriticalSection(&cs
);
458 packageTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable
));
461 LeaveCriticalSection(&cs
);
465 packageTable
->numPackages
= 0;
466 list_init(&packageTable
->table
);
469 for (i
= 0; i
< toAdd
; i
++)
471 SecurePackage
*package
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage
));
475 list_add_tail(&packageTable
->table
, &package
->entry
);
477 package
->provider
= provider
;
478 _copyPackageInfo(&package
->infoW
,
479 infoA
? &infoA
[i
] : NULL
,
480 infoW
? &infoW
[i
] : NULL
);
482 packageTable
->numPackages
+= toAdd
;
484 LeaveCriticalSection(&cs
);
487 static void _tryLoadProvider(PWSTR moduleName
)
489 HMODULE lib
= LoadLibraryW(moduleName
);
493 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
494 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(lib
,
495 SECURITY_ENTRYPOINT_ANSIW
);
496 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
497 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(lib
,
498 SECURITY_ENTRYPOINT_ANSIA
);
500 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
501 debugstr_w(moduleName
), pInitSecurityInterfaceA
,
502 pInitSecurityInterfaceW
);
503 if (pInitSecurityInterfaceW
|| pInitSecurityInterfaceA
)
505 PSecurityFunctionTableA fnTableA
= NULL
;
506 PSecurityFunctionTableW fnTableW
= NULL
;
508 PSecPkgInfoA infoA
= NULL
;
509 PSecPkgInfoW infoW
= NULL
;
510 SECURITY_STATUS ret
= SEC_E_OK
;
512 if (pInitSecurityInterfaceA
)
513 fnTableA
= pInitSecurityInterfaceA();
514 if (pInitSecurityInterfaceW
)
515 fnTableW
= pInitSecurityInterfaceW();
516 if (fnTableW
&& fnTableW
->EnumerateSecurityPackagesW
)
518 if (fnTableW
!= &securityFunctionTableW
)
519 ret
= fnTableW
->EnumerateSecurityPackagesW(&toAdd
, &infoW
);
521 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
523 else if (fnTableA
&& fnTableA
->EnumerateSecurityPackagesA
)
525 if (fnTableA
!= &securityFunctionTableA
)
526 ret
= fnTableA
->EnumerateSecurityPackagesA(&toAdd
, &infoA
);
528 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
530 if (ret
== SEC_E_OK
&& toAdd
> 0 && (infoW
|| infoA
))
532 SecureProvider
*provider
= SECUR32_addProvider(NULL
, NULL
,
536 SECUR32_addPackages(provider
, toAdd
, infoA
, infoW
);
538 fnTableW
->FreeContextBuffer(infoW
);
540 fnTableA
->FreeContextBuffer(infoA
);
546 WARN("failed to load %s\n", debugstr_w(moduleName
));
549 static const WCHAR securityProvidersKeyW
[] = {
550 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
551 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
552 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
554 static const WCHAR securityProvidersW
[] = {
555 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
558 static void SECUR32_initializeProviders(void)
564 /* First load built-in providers */
565 SECUR32_initSchannelSP();
566 SECUR32_initNTLMSP();
567 /* Load the Negotiate provider last so apps stumble over the working NTLM
568 * provider first. Attempting to fix bug #16905 while keeping the
569 * application reported on wine-users on 2006-09-12 working. */
570 SECUR32_initNegotiateSP();
571 /* Now load providers from registry */
572 apiRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, securityProvidersKeyW
, 0,
574 if (apiRet
== ERROR_SUCCESS
)
576 WCHAR securityPkgNames
[MAX_PATH
]; /* arbitrary len */
577 DWORD size
= sizeof(securityPkgNames
) / sizeof(WCHAR
), type
;
579 apiRet
= RegQueryValueExW(key
, securityProvidersW
, NULL
, &type
,
580 (PBYTE
)securityPkgNames
, &size
);
581 if (apiRet
== ERROR_SUCCESS
&& type
== REG_SZ
)
585 size
= size
/ sizeof(WCHAR
);
586 for (ptr
= securityPkgNames
;
587 ptr
< securityPkgNames
+ size
; )
591 for (comma
= ptr
; *comma
&& *comma
!= ','; comma
++)
595 for (; *ptr
&& isspace(*ptr
) && ptr
< securityPkgNames
+ size
;
599 _tryLoadProvider(ptr
);
600 ptr
+= lstrlenW(ptr
) + 1;
607 SecurePackage
*SECUR32_findPackageW(PCWSTR packageName
)
609 SecurePackage
*ret
= NULL
;
610 BOOL matched
= FALSE
;
612 if (packageTable
&& packageName
)
614 LIST_FOR_EACH_ENTRY(ret
, &packageTable
->table
, SecurePackage
, entry
)
616 matched
= !lstrcmpiW(ret
->infoW
.Name
, packageName
);
624 if (ret
->provider
&& !ret
->provider
->loaded
)
626 ret
->provider
->lib
= LoadLibraryW(ret
->provider
->moduleName
);
627 if (ret
->provider
->lib
)
629 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
630 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(ret
->provider
->lib
,
631 SECURITY_ENTRYPOINT_ANSIW
);
632 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
633 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(ret
->provider
->lib
,
634 SECURITY_ENTRYPOINT_ANSIA
);
635 PSecurityFunctionTableA fnTableA
= NULL
;
636 PSecurityFunctionTableW fnTableW
= NULL
;
638 if (pInitSecurityInterfaceA
)
639 fnTableA
= pInitSecurityInterfaceA();
640 if (pInitSecurityInterfaceW
)
641 fnTableW
= pInitSecurityInterfaceW();
642 /* don't update built-in SecurityFunctionTable */
643 if (fnTableA
!= &securityFunctionTableA
)
644 _makeFnTableA(&ret
->provider
->fnTableA
, fnTableA
, fnTableW
);
645 if (fnTableW
!= &securityFunctionTableW
)
646 _makeFnTableW(&ret
->provider
->fnTableW
, fnTableA
, fnTableW
);
647 ret
->provider
->loaded
= TRUE
;
656 SecurePackage
*SECUR32_findPackageA(PCSTR packageName
)
660 if (packageTable
&& packageName
)
662 UNICODE_STRING package
;
664 RtlCreateUnicodeStringFromAsciiz(&package
, packageName
);
665 ret
= SECUR32_findPackageW(package
.Buffer
);
666 RtlFreeUnicodeString(&package
);
673 static void SECUR32_freeProviders(void)
676 EnterCriticalSection(&cs
);
678 SECUR32_deinitSchannelSP();
682 SecurePackage
*package
, *package_next
;
683 LIST_FOR_EACH_ENTRY_SAFE(package
, package_next
, &packageTable
->table
,
684 SecurePackage
, entry
)
686 HeapFree(GetProcessHeap(), 0, package
->infoW
.Name
);
687 HeapFree(GetProcessHeap(), 0, package
->infoW
.Comment
);
688 HeapFree(GetProcessHeap(), 0, package
);
691 HeapFree(GetProcessHeap(), 0, packageTable
);
697 SecureProvider
*provider
, *provider_next
;
698 LIST_FOR_EACH_ENTRY_SAFE(provider
, provider_next
, &providerTable
->table
,
699 SecureProvider
, entry
)
701 HeapFree(GetProcessHeap(), 0, provider
->moduleName
);
703 FreeLibrary(provider
->lib
);
704 HeapFree(GetProcessHeap(), 0, provider
);
707 HeapFree(GetProcessHeap(), 0, providerTable
);
708 providerTable
= NULL
;
711 LeaveCriticalSection(&cs
);
712 DeleteCriticalSection(&cs
);
715 /***********************************************************************
716 * FreeContextBuffer (SECUR32.@)
718 * Doh--if pv was allocated by a crypto package, this may not be correct.
719 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
720 * be any guarantee, nor is there an alloc function in secur32.
722 SECURITY_STATUS WINAPI
FreeContextBuffer(PVOID pv
)
724 HeapFree(GetProcessHeap(), 0, pv
);
729 /***********************************************************************
730 * EnumerateSecurityPackagesW (SECUR32.@)
732 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesW(PULONG pcPackages
,
733 PSecPkgInfoW
*ppPackageInfo
)
735 SECURITY_STATUS ret
= SEC_E_OK
;
737 TRACE("(%p, %p)\n", pcPackages
, ppPackageInfo
);
739 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
741 EnterCriticalSection(&cs
);
744 SecurePackage
*package
;
747 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
748 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
750 if (package
->infoW
.Name
)
751 bytesNeeded
+= (lstrlenW(package
->infoW
.Name
) + 1) * sizeof(WCHAR
);
752 if (package
->infoW
.Comment
)
753 bytesNeeded
+= (lstrlenW(package
->infoW
.Comment
) + 1) * sizeof(WCHAR
);
757 *ppPackageInfo
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
763 *pcPackages
= packageTable
->numPackages
;
764 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
765 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
766 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
768 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
++;
770 *pkgInfo
= package
->infoW
;
771 if (package
->infoW
.Name
)
773 TRACE("Name[%d] = %s\n", i
- 1, debugstr_w(package
->infoW
.Name
));
774 pkgInfo
->Name
= nextString
;
775 lstrcpyW(nextString
, package
->infoW
.Name
);
776 nextString
+= lstrlenW(nextString
) + 1;
779 pkgInfo
->Name
= NULL
;
780 if (package
->infoW
.Comment
)
782 TRACE("Comment[%d] = %s\n", i
- 1, debugstr_w(package
->infoW
.Comment
));
783 pkgInfo
->Comment
= nextString
;
784 lstrcpyW(nextString
, package
->infoW
.Comment
);
785 nextString
+= lstrlenW(nextString
) + 1;
788 pkgInfo
->Comment
= NULL
;
792 ret
= SEC_E_INSUFFICIENT_MEMORY
;
795 LeaveCriticalSection(&cs
);
796 TRACE("<-- 0x%08x\n", ret
);
800 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
801 * structures) into an array of SecPkgInfoA structures, which it returns.
803 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
804 const SecPkgInfoW
*info
)
810 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
813 for (i
= 0; i
< cPackages
; i
++)
816 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
817 -1, NULL
, 0, NULL
, NULL
);
819 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
820 -1, NULL
, 0, NULL
, NULL
);
822 ret
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
827 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
828 for (i
= 0; i
< cPackages
; i
++)
830 PSecPkgInfoA pkgInfo
= ret
+ i
;
833 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
836 pkgInfo
->Name
= nextString
;
837 /* just repeat back to WideCharToMultiByte how many bytes
838 * it requires, since we asked it earlier
840 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
841 NULL
, 0, NULL
, NULL
);
842 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
843 pkgInfo
->Name
, bytes
, NULL
, NULL
);
844 nextString
+= lstrlenA(nextString
) + 1;
847 pkgInfo
->Name
= NULL
;
850 pkgInfo
->Comment
= nextString
;
851 /* just repeat back to WideCharToMultiByte how many bytes
852 * it requires, since we asked it earlier
854 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
855 NULL
, 0, NULL
, NULL
);
856 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
857 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
858 nextString
+= lstrlenA(nextString
) + 1;
861 pkgInfo
->Comment
= NULL
;
870 /***********************************************************************
871 * EnumerateSecurityPackagesA (SECUR32.@)
873 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesA(PULONG pcPackages
,
874 PSecPkgInfoA
*ppPackageInfo
)
879 ret
= EnumerateSecurityPackagesW(pcPackages
, &info
);
880 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
882 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
883 if (*pcPackages
&& !*ppPackageInfo
)
886 ret
= SEC_E_INSUFFICIENT_MEMORY
;
888 FreeContextBuffer(info
);
893 /***********************************************************************
894 * GetComputerObjectNameA (SECUR32.@)
896 * Get the local computer's name using the format specified.
899 * NameFormat [I] The format for the name.
900 * lpNameBuffer [O] Pointer to buffer to receive the name.
901 * nSize [I/O] Size in characters of buffer.
904 * TRUE If the name was written to lpNameBuffer.
905 * FALSE If the name couldn't be written.
908 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
909 * name will be returned in *nSize.
911 * nSize returns the number of characters written when lpNameBuffer is not
912 * NULL or the size of the buffer needed to hold the name when the buffer
913 * is too short or lpNameBuffer is NULL.
915 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
917 BOOLEAN WINAPI
GetComputerObjectNameA(
918 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
921 LPWSTR bufferW
= NULL
;
922 ULONG sizeW
= *nSize
;
923 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
925 bufferW
= HeapAlloc(GetProcessHeap(), 0, sizeW
* sizeof(WCHAR
));
926 if (bufferW
== NULL
) {
927 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
931 rc
= GetComputerObjectNameW(NameFormat
, bufferW
, &sizeW
);
933 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
934 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
939 HeapFree(GetProcessHeap(), 0, bufferW
);
943 /***********************************************************************
944 * GetComputerObjectNameW (SECUR32.@)
946 BOOLEAN WINAPI
GetComputerObjectNameW(
947 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
949 LSA_HANDLE policyHandle
;
950 LSA_OBJECT_ATTRIBUTES objectAttributes
;
951 PPOLICY_DNS_DOMAIN_INFO domainInfo
;
954 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
956 if (NameFormat
== NameUnknown
)
958 SetLastError(ERROR_INVALID_PARAMETER
);
962 ZeroMemory(&objectAttributes
, sizeof(objectAttributes
));
963 objectAttributes
.Length
= sizeof(objectAttributes
);
965 ntStatus
= LsaOpenPolicy(NULL
, &objectAttributes
,
966 POLICY_VIEW_LOCAL_INFORMATION
,
968 if (ntStatus
!= STATUS_SUCCESS
)
970 SetLastError(LsaNtStatusToWinError(ntStatus
));
971 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
975 ntStatus
= LsaQueryInformationPolicy(policyHandle
,
976 PolicyDnsDomainInformation
,
977 (PVOID
*)&domainInfo
);
978 if (ntStatus
!= STATUS_SUCCESS
)
980 SetLastError(LsaNtStatusToWinError(ntStatus
));
981 WARN("LsaQueryInformationPolicy failed with NT status %u\n",
983 LsaClose(policyHandle
);
991 case NameSamCompatible
:
993 WCHAR name
[MAX_COMPUTERNAME_LENGTH
+ 1];
994 DWORD size
= sizeof(name
)/sizeof(name
[0]);
995 if (GetComputerNameW(name
, &size
))
997 DWORD len
= domainInfo
->Name
.Length
+ size
+ 3;
1003 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1008 WCHAR bs
[] = { '\\', 0 };
1009 WCHAR ds
[] = { '$', 0 };
1010 lstrcpyW(lpNameBuffer
, domainInfo
->Name
.Buffer
);
1011 lstrcatW(lpNameBuffer
, bs
);
1012 lstrcatW(lpNameBuffer
, name
);
1013 lstrcatW(lpNameBuffer
, ds
);
1017 else /* just requesting length required */
1025 SetLastError(ERROR_INTERNAL_ERROR
);
1030 case NameFullyQualifiedDN
:
1034 case NameUserPrincipal
:
1035 case NameCanonicalEx
:
1036 case NameServicePrincipal
:
1038 FIXME("NameFormat %d not implemented\n", NameFormat
);
1039 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
1043 SetLastError(ERROR_INVALID_PARAMETER
);
1049 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
1053 LsaFreeMemory(domainInfo
);
1054 LsaClose(policyHandle
);
1059 /***********************************************************************
1060 * GetUserNameExA (SECUR32.@)
1062 BOOLEAN WINAPI
GetUserNameExA(
1063 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
1066 LPWSTR bufferW
= NULL
;
1067 ULONG sizeW
= *nSize
;
1068 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
1070 bufferW
= HeapAlloc(GetProcessHeap(), 0, sizeW
* sizeof(WCHAR
));
1071 if (bufferW
== NULL
) {
1072 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1076 rc
= GetUserNameExW(NameFormat
, bufferW
, &sizeW
);
1078 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
1081 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
1088 SetLastError(ERROR_MORE_DATA
);
1093 HeapFree(GetProcessHeap(), 0, bufferW
);
1097 BOOLEAN WINAPI
GetUserNameExW(
1098 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
1100 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
1104 case NameSamCompatible
:
1106 WCHAR samname
[UNLEN
+ 1 + MAX_COMPUTERNAME_LENGTH
+ 1];
1110 /* This assumes the current user is always a local account */
1111 len
= MAX_COMPUTERNAME_LENGTH
+ 1;
1112 if (GetComputerNameW(samname
, &len
))
1114 out
= samname
+ lstrlenW(samname
);
1117 if (GetUserNameW(out
, &len
))
1119 if (lstrlenW(samname
) < *nSize
)
1121 lstrcpyW(lpNameBuffer
, samname
);
1122 *nSize
= lstrlenW(samname
);
1126 SetLastError(ERROR_MORE_DATA
);
1127 *nSize
= lstrlenW(samname
) + 1;
1134 case NameFullyQualifiedDN
:
1138 case NameUserPrincipal
:
1139 case NameCanonicalEx
:
1140 case NameServicePrincipal
:
1142 SetLastError(ERROR_NONE_MAPPED
);
1146 SetLastError(ERROR_INVALID_PARAMETER
);
1151 BOOLEAN WINAPI
TranslateNameA(
1152 LPCSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1153 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPSTR lpTranslatedName
,
1156 FIXME("%p %d %d %p %p\n", lpAccountName
, AccountNameFormat
,
1157 DesiredNameFormat
, lpTranslatedName
, nSize
);
1161 BOOLEAN WINAPI
TranslateNameW(
1162 LPCWSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1163 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPWSTR lpTranslatedName
,
1166 FIXME("%p %d %d %p %p\n", lpAccountName
, AccountNameFormat
,
1167 DesiredNameFormat
, lpTranslatedName
, nSize
);
1171 /***********************************************************************
1172 * SspiEncodeAuthIdentityAsStrings (SECUR32.0)
1174 SECURITY_STATUS SEC_ENTRY
SspiEncodeAuthIdentityAsStrings(
1175 PSEC_WINNT_AUTH_IDENTITY_OPAQUE opaque_id
, PCWSTR
*username
,
1176 PCWSTR
*domainname
, PCWSTR
*creds
)
1178 SEC_WINNT_AUTH_IDENTITY_W
*id
= (SEC_WINNT_AUTH_IDENTITY_W
*)opaque_id
;
1180 FIXME("%p %p %p %p\n", opaque_id
, username
, domainname
, creds
);
1182 *username
= SECUR32_strdupW( id
->User
);
1183 *domainname
= SECUR32_strdupW( id
->Domain
);
1184 *creds
= SECUR32_strdupW( id
->Password
);
1189 /***********************************************************************
1190 * SspiEncodeStringsAsAuthIdentity (SECUR32.0)
1192 SECURITY_STATUS SEC_ENTRY
SspiEncodeStringsAsAuthIdentity(
1193 PCWSTR username
, PCWSTR domainname
, PCWSTR creds
,
1194 PSEC_WINNT_AUTH_IDENTITY_OPAQUE
*opaque_id
)
1196 SEC_WINNT_AUTH_IDENTITY_W
*id
;
1197 DWORD len_username
= 0, len_domainname
= 0, len_password
= 0, size
;
1200 FIXME( "%s %s %s %p\n", debugstr_w(username
), debugstr_w(domainname
),
1201 debugstr_w(creds
), opaque_id
);
1203 if (!username
&& !domainname
&& !creds
) return SEC_E_INVALID_TOKEN
;
1205 if (username
) len_username
= strlenW( username
);
1206 if (domainname
) len_domainname
= strlenW( domainname
);
1207 if (creds
) len_password
= strlenW( creds
);
1210 if (username
) size
+= (len_username
+ 1) * sizeof(WCHAR
);
1211 if (domainname
) size
+= (len_domainname
+ 1) * sizeof(WCHAR
);
1212 if (creds
) size
+= (len_password
+ 1) * sizeof(WCHAR
);
1213 if (!(id
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, size
))) return ERROR_OUTOFMEMORY
;
1214 ptr
= (WCHAR
*)(id
+ 1);
1218 memcpy( ptr
, username
, (len_username
+ 1) * sizeof(WCHAR
) );
1220 id
->UserLength
= len_username
;
1221 ptr
+= len_username
+ 1;
1225 memcpy( ptr
, domainname
, (len_domainname
+ 1) * sizeof(WCHAR
) );
1227 id
->DomainLength
= len_domainname
;
1228 ptr
+= len_domainname
+ 1;
1232 memcpy( ptr
, creds
, (len_password
+ 1) * sizeof(WCHAR
) );
1234 id
->PasswordLength
= len_password
;
1241 /***********************************************************************
1242 * SspiFreeAuthIdentity (SECUR32.0)
1244 void SEC_ENTRY
SspiFreeAuthIdentity( PSEC_WINNT_AUTH_IDENTITY_OPAQUE opaque_id
)
1247 TRACE( "%p\n", opaque_id
);
1248 HeapFree( GetProcessHeap(), 0, opaque_id
);
1251 /***********************************************************************
1252 * SspiLocalFree (SECUR32.0)
1254 void SEC_ENTRY
SspiLocalFree( void *ptr
)
1256 TRACE( "%p\n", ptr
);
1257 HeapFree( GetProcessHeap(), 0, ptr
);
1260 /***********************************************************************
1261 * SspiZeroAuthIdentity (SECUR32.0)
1263 void SEC_ENTRY
SspiZeroAuthIdentity( PSEC_WINNT_AUTH_IDENTITY_OPAQUE opaque_id
)
1265 SEC_WINNT_AUTH_IDENTITY_W
*id
= (SEC_WINNT_AUTH_IDENTITY_W
*)opaque_id
;
1267 TRACE( "%p\n", opaque_id
);
1270 if (id
->User
) memset( id
->User
, 0, id
->UserLength
* sizeof(WCHAR
) );
1271 if (id
->Domain
) memset( id
->Domain
, 0, id
->DomainLength
* sizeof(WCHAR
) );
1272 if (id
->Password
) memset( id
->Password
, 0, id
->PasswordLength
* sizeof(WCHAR
) );
1273 memset( id
, 0, sizeof(*id
) );
1276 /***********************************************************************
1277 * DllMain (SECUR32.0)
1279 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD reason
, LPVOID reserved
)
1283 case DLL_PROCESS_ATTACH
:
1284 DisableThreadLibraryCalls(hinstDLL
);
1285 SECUR32_initializeProviders();
1287 case DLL_PROCESS_DETACH
:
1288 if (reserved
) break;
1289 SECUR32_freeProviders();