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"
40 WINE_DEFAULT_DEBUG_CHANNEL(secur32
);
46 typedef struct _SecurePackageTable
53 typedef struct _SecureProviderTable
58 } SecureProviderTable
;
64 /* Tries to load moduleName as a provider. If successful, enumerates what
65 * packages it can and adds them to the package and provider tables. Resizes
66 * tables as necessary.
68 static void _tryLoadProvider(PWSTR moduleName
);
70 /* Initialization: read securityproviders value and attempt to open each dll
71 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
72 * Two undocumented functions, AddSecurityPackage(A/W) and
73 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
74 * unregister a dll, but I'm not sure.
76 static void SECUR32_initializeProviders(void);
78 /* Frees all loaded packages and providers */
79 static void SECUR32_freeProviders(void);
85 static CRITICAL_SECTION cs
;
86 static CRITICAL_SECTION_DEBUG cs_debug
=
89 { &cs_debug
.ProcessLocksList
, &cs_debug
.ProcessLocksList
},
90 0, 0, { (DWORD_PTR
)(__FILE__
": cs") }
92 static CRITICAL_SECTION cs
= { &cs_debug
, -1, 0, 0, 0, 0 };
93 static SecurePackageTable
*packageTable
= NULL
;
94 static SecureProviderTable
*providerTable
= NULL
;
96 static SecurityFunctionTableA securityFunctionTableA
= {
97 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
98 EnumerateSecurityPackagesA
,
99 QueryCredentialsAttributesA
,
100 AcquireCredentialsHandleA
,
101 FreeCredentialsHandle
,
102 NULL
, /* Reserved2 */
103 InitializeSecurityContextA
,
104 AcceptSecurityContext
,
106 DeleteSecurityContext
,
108 QueryContextAttributesA
,
109 ImpersonateSecurityContext
,
110 RevertSecurityContext
,
114 QuerySecurityPackageInfoA
,
115 EncryptMessage
, /* Reserved3 */
116 DecryptMessage
, /* Reserved4 */
117 ExportSecurityContext
,
118 ImportSecurityContextA
,
120 NULL
, /* Reserved8 */
121 QuerySecurityContextToken
,
124 SetContextAttributesA
127 static SecurityFunctionTableW securityFunctionTableW
= {
128 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
129 EnumerateSecurityPackagesW
,
130 QueryCredentialsAttributesW
,
131 AcquireCredentialsHandleW
,
132 FreeCredentialsHandle
,
133 NULL
, /* Reserved2 */
134 InitializeSecurityContextW
,
135 AcceptSecurityContext
,
137 DeleteSecurityContext
,
139 QueryContextAttributesW
,
140 ImpersonateSecurityContext
,
141 RevertSecurityContext
,
145 QuerySecurityPackageInfoW
,
146 EncryptMessage
, /* Reserved3 */
147 DecryptMessage
, /* Reserved4 */
148 ExportSecurityContext
,
149 ImportSecurityContextW
,
151 NULL
, /* Reserved8 */
152 QuerySecurityContextToken
,
155 SetContextAttributesW
158 /***********************************************************************
159 * InitSecurityInterfaceA (SECUR32.@)
161 PSecurityFunctionTableA WINAPI
InitSecurityInterfaceA(void)
163 return &securityFunctionTableA
;
166 /***********************************************************************
167 * InitSecurityInterfaceW (SECUR32.@)
169 PSecurityFunctionTableW WINAPI
InitSecurityInterfaceW(void)
171 return &securityFunctionTableW
;
174 static PWSTR
SECUR32_strdupW(PCWSTR str
)
180 ret
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str
) + 1) * sizeof(WCHAR
));
189 PWSTR
SECUR32_AllocWideFromMultiByte(PCSTR str
)
195 int charsNeeded
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
199 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
* sizeof(WCHAR
));
201 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, charsNeeded
);
211 PSTR
SECUR32_AllocMultiByteFromWide(PCWSTR str
)
217 int charsNeeded
= WideCharToMultiByte(CP_ACP
, 0, str
, -1, NULL
, 0,
222 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
);
224 WideCharToMultiByte(CP_ACP
, 0, str
, -1, ret
, charsNeeded
,
235 static void _makeFnTableA(PSecurityFunctionTableA fnTableA
,
236 const SecurityFunctionTableA
*inFnTableA
,
237 const SecurityFunctionTableW
*inFnTableW
)
243 /* The size of the version 1 table is based on platform sdk's
244 * sspi.h, though the sample ssp also provided with platform sdk
245 * implies only functions through QuerySecurityPackageInfoA are
246 * implemented (yikes)
248 size_t tableSize
= inFnTableA
->dwVersion
== 1 ?
249 (const BYTE
*)&inFnTableA
->SetContextAttributesA
-
250 (const BYTE
*)inFnTableA
: sizeof(SecurityFunctionTableA
);
252 memcpy(fnTableA
, inFnTableA
, tableSize
);
253 /* override this, since we can do it internally anyway */
254 fnTableA
->QuerySecurityPackageInfoA
=
255 QuerySecurityPackageInfoA
;
259 /* functions with thunks */
260 if (inFnTableW
->AcquireCredentialsHandleW
)
261 fnTableA
->AcquireCredentialsHandleA
=
262 thunk_AcquireCredentialsHandleA
;
263 if (inFnTableW
->InitializeSecurityContextW
)
264 fnTableA
->InitializeSecurityContextA
=
265 thunk_InitializeSecurityContextA
;
266 if (inFnTableW
->ImportSecurityContextW
)
267 fnTableA
->ImportSecurityContextA
=
268 thunk_ImportSecurityContextA
;
269 if (inFnTableW
->AddCredentialsW
)
270 fnTableA
->AddCredentialsA
=
271 thunk_AddCredentialsA
;
272 if (inFnTableW
->QueryCredentialsAttributesW
)
273 fnTableA
->QueryCredentialsAttributesA
=
274 thunk_QueryCredentialsAttributesA
;
275 if (inFnTableW
->QueryContextAttributesW
)
276 fnTableA
->QueryContextAttributesA
=
277 thunk_QueryContextAttributesA
;
278 if (inFnTableW
->SetContextAttributesW
)
279 fnTableA
->SetContextAttributesA
=
280 thunk_SetContextAttributesA
;
281 /* this can't be thunked, there's no extra param to know which
282 * package to forward to */
283 fnTableA
->EnumerateSecurityPackagesA
= NULL
;
284 /* functions with no thunks needed */
285 fnTableA
->AcceptSecurityContext
= inFnTableW
->AcceptSecurityContext
;
286 fnTableA
->CompleteAuthToken
= inFnTableW
->CompleteAuthToken
;
287 fnTableA
->DeleteSecurityContext
= inFnTableW
->DeleteSecurityContext
;
288 fnTableA
->ImpersonateSecurityContext
=
289 inFnTableW
->ImpersonateSecurityContext
;
290 fnTableA
->RevertSecurityContext
= inFnTableW
->RevertSecurityContext
;
291 fnTableA
->MakeSignature
= inFnTableW
->MakeSignature
;
292 fnTableA
->VerifySignature
= inFnTableW
->VerifySignature
;
293 fnTableA
->FreeContextBuffer
= inFnTableW
->FreeContextBuffer
;
294 fnTableA
->QuerySecurityPackageInfoA
=
295 QuerySecurityPackageInfoA
;
296 fnTableA
->ExportSecurityContext
=
297 inFnTableW
->ExportSecurityContext
;
298 fnTableA
->QuerySecurityContextToken
=
299 inFnTableW
->QuerySecurityContextToken
;
300 fnTableA
->EncryptMessage
= inFnTableW
->EncryptMessage
;
301 fnTableA
->DecryptMessage
= inFnTableW
->DecryptMessage
;
306 static void _makeFnTableW(PSecurityFunctionTableW fnTableW
,
307 const SecurityFunctionTableA
*inFnTableA
,
308 const SecurityFunctionTableW
*inFnTableW
)
314 /* The size of the version 1 table is based on platform sdk's
315 * sspi.h, though the sample ssp also provided with platform sdk
316 * implies only functions through QuerySecurityPackageInfoA are
317 * implemented (yikes)
319 size_t tableSize
= inFnTableW
->dwVersion
== 1 ?
320 (const BYTE
*)&inFnTableW
->SetContextAttributesW
-
321 (const BYTE
*)inFnTableW
: sizeof(SecurityFunctionTableW
);
323 memcpy(fnTableW
, inFnTableW
, tableSize
);
324 /* override this, since we can do it internally anyway */
325 fnTableW
->QuerySecurityPackageInfoW
=
326 QuerySecurityPackageInfoW
;
330 /* functions with thunks */
331 if (inFnTableA
->AcquireCredentialsHandleA
)
332 fnTableW
->AcquireCredentialsHandleW
=
333 thunk_AcquireCredentialsHandleW
;
334 if (inFnTableA
->InitializeSecurityContextA
)
335 fnTableW
->InitializeSecurityContextW
=
336 thunk_InitializeSecurityContextW
;
337 if (inFnTableA
->ImportSecurityContextA
)
338 fnTableW
->ImportSecurityContextW
=
339 thunk_ImportSecurityContextW
;
340 if (inFnTableA
->AddCredentialsA
)
341 fnTableW
->AddCredentialsW
=
342 thunk_AddCredentialsW
;
343 if (inFnTableA
->QueryCredentialsAttributesA
)
344 fnTableW
->QueryCredentialsAttributesW
=
345 thunk_QueryCredentialsAttributesW
;
346 if (inFnTableA
->QueryContextAttributesA
)
347 fnTableW
->QueryContextAttributesW
=
348 thunk_QueryContextAttributesW
;
349 if (inFnTableA
->SetContextAttributesA
)
350 fnTableW
->SetContextAttributesW
=
351 thunk_SetContextAttributesW
;
352 /* this can't be thunked, there's no extra param to know which
353 * package to forward to */
354 fnTableW
->EnumerateSecurityPackagesW
= NULL
;
355 /* functions with no thunks needed */
356 fnTableW
->AcceptSecurityContext
= inFnTableA
->AcceptSecurityContext
;
357 fnTableW
->CompleteAuthToken
= inFnTableA
->CompleteAuthToken
;
358 fnTableW
->DeleteSecurityContext
= inFnTableA
->DeleteSecurityContext
;
359 fnTableW
->ImpersonateSecurityContext
=
360 inFnTableA
->ImpersonateSecurityContext
;
361 fnTableW
->RevertSecurityContext
= inFnTableA
->RevertSecurityContext
;
362 fnTableW
->MakeSignature
= inFnTableA
->MakeSignature
;
363 fnTableW
->VerifySignature
= inFnTableA
->VerifySignature
;
364 fnTableW
->FreeContextBuffer
= inFnTableA
->FreeContextBuffer
;
365 fnTableW
->QuerySecurityPackageInfoW
=
366 QuerySecurityPackageInfoW
;
367 fnTableW
->ExportSecurityContext
=
368 inFnTableA
->ExportSecurityContext
;
369 fnTableW
->QuerySecurityContextToken
=
370 inFnTableA
->QuerySecurityContextToken
;
371 fnTableW
->EncryptMessage
= inFnTableA
->EncryptMessage
;
372 fnTableW
->DecryptMessage
= inFnTableA
->DecryptMessage
;
377 static void _copyPackageInfo(PSecPkgInfoW info
, const SecPkgInfoA
*inInfoA
,
378 const SecPkgInfoW
*inInfoW
)
380 if (info
&& (inInfoA
|| inInfoW
))
382 /* odd, I know, but up until Name and Comment the structures are
385 memcpy(info
, inInfoW
? inInfoW
: (const SecPkgInfoW
*)inInfoA
, sizeof(*info
));
388 info
->Name
= SECUR32_strdupW(inInfoW
->Name
);
389 info
->Comment
= SECUR32_strdupW(inInfoW
->Comment
);
393 info
->Name
= SECUR32_AllocWideFromMultiByte(inInfoA
->Name
);
394 info
->Comment
= SECUR32_AllocWideFromMultiByte(inInfoA
->Comment
);
399 SecureProvider
*SECUR32_addProvider(const SecurityFunctionTableA
*fnTableA
,
400 const SecurityFunctionTableW
*fnTableW
, PCWSTR moduleName
)
404 EnterCriticalSection(&cs
);
408 providerTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable
));
411 LeaveCriticalSection(&cs
);
415 list_init(&providerTable
->table
);
418 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider
));
421 LeaveCriticalSection(&cs
);
425 list_add_tail(&providerTable
->table
, &ret
->entry
);
428 if (fnTableA
|| fnTableW
)
430 ret
->moduleName
= moduleName
? SECUR32_strdupW(moduleName
) : NULL
;
431 _makeFnTableA(&ret
->fnTableA
, fnTableA
, fnTableW
);
432 _makeFnTableW(&ret
->fnTableW
, fnTableA
, fnTableW
);
433 ret
->loaded
= moduleName
? FALSE
: TRUE
;
437 ret
->moduleName
= SECUR32_strdupW(moduleName
);
441 LeaveCriticalSection(&cs
);
445 void SECUR32_addPackages(SecureProvider
*provider
, ULONG toAdd
,
446 const SecPkgInfoA
*infoA
, const SecPkgInfoW
*infoW
)
451 assert(infoA
|| infoW
);
453 EnterCriticalSection(&cs
);
457 packageTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable
));
460 LeaveCriticalSection(&cs
);
464 packageTable
->numPackages
= 0;
465 list_init(&packageTable
->table
);
468 for (i
= 0; i
< toAdd
; i
++)
470 SecurePackage
*package
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage
));
474 list_add_tail(&packageTable
->table
, &package
->entry
);
476 package
->provider
= provider
;
477 _copyPackageInfo(&package
->infoW
,
478 infoA
? &infoA
[i
] : NULL
,
479 infoW
? &infoW
[i
] : NULL
);
481 packageTable
->numPackages
+= toAdd
;
483 LeaveCriticalSection(&cs
);
486 static void _tryLoadProvider(PWSTR moduleName
)
488 HMODULE lib
= LoadLibraryW(moduleName
);
492 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
493 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(lib
,
494 SECURITY_ENTRYPOINT_ANSIW
);
495 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
496 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(lib
,
497 SECURITY_ENTRYPOINT_ANSIA
);
499 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
500 debugstr_w(moduleName
), pInitSecurityInterfaceA
,
501 pInitSecurityInterfaceW
);
502 if (pInitSecurityInterfaceW
|| pInitSecurityInterfaceA
)
504 PSecurityFunctionTableA fnTableA
= NULL
;
505 PSecurityFunctionTableW fnTableW
= NULL
;
507 PSecPkgInfoA infoA
= NULL
;
508 PSecPkgInfoW infoW
= NULL
;
509 SECURITY_STATUS ret
= SEC_E_OK
;
511 if (pInitSecurityInterfaceA
)
512 fnTableA
= pInitSecurityInterfaceA();
513 if (pInitSecurityInterfaceW
)
514 fnTableW
= pInitSecurityInterfaceW();
515 if (fnTableW
&& fnTableW
->EnumerateSecurityPackagesW
)
517 if (fnTableW
!= &securityFunctionTableW
)
518 ret
= fnTableW
->EnumerateSecurityPackagesW(&toAdd
, &infoW
);
520 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
522 else if (fnTableA
&& fnTableA
->EnumerateSecurityPackagesA
)
524 if (fnTableA
!= &securityFunctionTableA
)
525 ret
= fnTableA
->EnumerateSecurityPackagesA(&toAdd
, &infoA
);
527 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
529 if (ret
== SEC_E_OK
&& toAdd
> 0 && (infoW
|| infoA
))
531 SecureProvider
*provider
= SECUR32_addProvider(NULL
, NULL
,
535 SECUR32_addPackages(provider
, toAdd
, infoA
, infoW
);
537 fnTableW
->FreeContextBuffer(infoW
);
539 fnTableA
->FreeContextBuffer(infoA
);
545 WARN("failed to load %s\n", debugstr_w(moduleName
));
548 static const WCHAR securityProvidersKeyW
[] = {
549 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
550 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
551 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
553 static const WCHAR securityProvidersW
[] = {
554 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
557 static void SECUR32_initializeProviders(void)
563 /* First load built-in providers */
564 SECUR32_initSchannelSP();
565 SECUR32_initNTLMSP();
566 /* Load the Negotiate provider last so apps stumble over the working NTLM
567 * provider first. Attempting to fix bug #16905 while keeping the
568 * application reported on wine-users on 2006-09-12 working. */
569 SECUR32_initNegotiateSP();
570 /* Now load providers from registry */
571 apiRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, securityProvidersKeyW
, 0,
573 if (apiRet
== ERROR_SUCCESS
)
575 WCHAR securityPkgNames
[MAX_PATH
]; /* arbitrary len */
576 DWORD size
= sizeof(securityPkgNames
) / sizeof(WCHAR
), type
;
578 apiRet
= RegQueryValueExW(key
, securityProvidersW
, NULL
, &type
,
579 (PBYTE
)securityPkgNames
, &size
);
580 if (apiRet
== ERROR_SUCCESS
&& type
== REG_SZ
)
584 size
= size
/ sizeof(WCHAR
);
585 for (ptr
= securityPkgNames
;
586 ptr
< securityPkgNames
+ size
; )
590 for (comma
= ptr
; *comma
&& *comma
!= ','; comma
++)
594 for (; *ptr
&& isspace(*ptr
) && ptr
< securityPkgNames
+ size
;
598 _tryLoadProvider(ptr
);
599 ptr
+= lstrlenW(ptr
) + 1;
606 SecurePackage
*SECUR32_findPackageW(PCWSTR packageName
)
608 SecurePackage
*ret
= NULL
;
609 BOOL matched
= FALSE
;
611 if (packageTable
&& packageName
)
613 LIST_FOR_EACH_ENTRY(ret
, &packageTable
->table
, SecurePackage
, entry
)
615 matched
= !lstrcmpiW(ret
->infoW
.Name
, packageName
);
623 if (ret
->provider
&& !ret
->provider
->loaded
)
625 ret
->provider
->lib
= LoadLibraryW(ret
->provider
->moduleName
);
626 if (ret
->provider
->lib
)
628 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
629 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(ret
->provider
->lib
,
630 SECURITY_ENTRYPOINT_ANSIW
);
631 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
632 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(ret
->provider
->lib
,
633 SECURITY_ENTRYPOINT_ANSIA
);
634 PSecurityFunctionTableA fnTableA
= NULL
;
635 PSecurityFunctionTableW fnTableW
= NULL
;
637 if (pInitSecurityInterfaceA
)
638 fnTableA
= pInitSecurityInterfaceA();
639 if (pInitSecurityInterfaceW
)
640 fnTableW
= pInitSecurityInterfaceW();
641 /* don't update built-in SecurityFunctionTable */
642 if (fnTableA
!= &securityFunctionTableA
)
643 _makeFnTableA(&ret
->provider
->fnTableA
, fnTableA
, fnTableW
);
644 if (fnTableW
!= &securityFunctionTableW
)
645 _makeFnTableW(&ret
->provider
->fnTableW
, fnTableA
, fnTableW
);
646 ret
->provider
->loaded
= TRUE
;
655 SecurePackage
*SECUR32_findPackageA(PCSTR packageName
)
659 if (packageTable
&& packageName
)
661 UNICODE_STRING package
;
663 RtlCreateUnicodeStringFromAsciiz(&package
, packageName
);
664 ret
= SECUR32_findPackageW(package
.Buffer
);
665 RtlFreeUnicodeString(&package
);
672 static void SECUR32_freeProviders(void)
675 EnterCriticalSection(&cs
);
677 SECUR32_deinitSchannelSP();
681 SecurePackage
*package
, *package_next
;
682 LIST_FOR_EACH_ENTRY_SAFE(package
, package_next
, &packageTable
->table
,
683 SecurePackage
, entry
)
685 HeapFree(GetProcessHeap(), 0, package
->infoW
.Name
);
686 HeapFree(GetProcessHeap(), 0, package
->infoW
.Comment
);
687 HeapFree(GetProcessHeap(), 0, package
);
690 HeapFree(GetProcessHeap(), 0, packageTable
);
696 SecureProvider
*provider
, *provider_next
;
697 LIST_FOR_EACH_ENTRY_SAFE(provider
, provider_next
, &providerTable
->table
,
698 SecureProvider
, entry
)
700 HeapFree(GetProcessHeap(), 0, provider
->moduleName
);
702 FreeLibrary(provider
->lib
);
703 HeapFree(GetProcessHeap(), 0, provider
);
706 HeapFree(GetProcessHeap(), 0, providerTable
);
707 providerTable
= NULL
;
710 LeaveCriticalSection(&cs
);
711 DeleteCriticalSection(&cs
);
714 /***********************************************************************
715 * FreeContextBuffer (SECUR32.@)
717 * Doh--if pv was allocated by a crypto package, this may not be correct.
718 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
719 * be any guarantee, nor is there an alloc function in secur32.
721 SECURITY_STATUS WINAPI
FreeContextBuffer(PVOID pv
)
723 HeapFree(GetProcessHeap(), 0, pv
);
728 /***********************************************************************
729 * EnumerateSecurityPackagesW (SECUR32.@)
731 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesW(PULONG pcPackages
,
732 PSecPkgInfoW
*ppPackageInfo
)
734 SECURITY_STATUS ret
= SEC_E_OK
;
736 TRACE("(%p, %p)\n", pcPackages
, ppPackageInfo
);
738 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
740 EnterCriticalSection(&cs
);
743 SecurePackage
*package
;
746 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
747 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
749 if (package
->infoW
.Name
)
750 bytesNeeded
+= (lstrlenW(package
->infoW
.Name
) + 1) * sizeof(WCHAR
);
751 if (package
->infoW
.Comment
)
752 bytesNeeded
+= (lstrlenW(package
->infoW
.Comment
) + 1) * sizeof(WCHAR
);
756 *ppPackageInfo
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
762 *pcPackages
= packageTable
->numPackages
;
763 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
764 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
765 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
767 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
++;
769 *pkgInfo
= package
->infoW
;
770 if (package
->infoW
.Name
)
772 TRACE("Name[%d] = %s\n", i
- 1, debugstr_w(package
->infoW
.Name
));
773 pkgInfo
->Name
= nextString
;
774 lstrcpyW(nextString
, package
->infoW
.Name
);
775 nextString
+= lstrlenW(nextString
) + 1;
778 pkgInfo
->Name
= NULL
;
779 if (package
->infoW
.Comment
)
781 TRACE("Comment[%d] = %s\n", i
- 1, debugstr_w(package
->infoW
.Comment
));
782 pkgInfo
->Comment
= nextString
;
783 lstrcpyW(nextString
, package
->infoW
.Comment
);
784 nextString
+= lstrlenW(nextString
) + 1;
787 pkgInfo
->Comment
= NULL
;
791 ret
= SEC_E_INSUFFICIENT_MEMORY
;
794 LeaveCriticalSection(&cs
);
795 TRACE("<-- 0x%08x\n", ret
);
799 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
800 * structures) into an array of SecPkgInfoA structures, which it returns.
802 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
803 const SecPkgInfoW
*info
)
809 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
812 for (i
= 0; i
< cPackages
; i
++)
815 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
816 -1, NULL
, 0, NULL
, NULL
);
818 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
819 -1, NULL
, 0, NULL
, NULL
);
821 ret
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
826 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
827 for (i
= 0; i
< cPackages
; i
++)
829 PSecPkgInfoA pkgInfo
= ret
+ i
;
832 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
835 pkgInfo
->Name
= nextString
;
836 /* just repeat back to WideCharToMultiByte how many bytes
837 * it requires, since we asked it earlier
839 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
840 NULL
, 0, NULL
, NULL
);
841 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
842 pkgInfo
->Name
, bytes
, NULL
, NULL
);
843 nextString
+= lstrlenA(nextString
) + 1;
846 pkgInfo
->Name
= NULL
;
849 pkgInfo
->Comment
= nextString
;
850 /* just repeat back to WideCharToMultiByte how many bytes
851 * it requires, since we asked it earlier
853 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
854 NULL
, 0, NULL
, NULL
);
855 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
856 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
857 nextString
+= lstrlenA(nextString
) + 1;
860 pkgInfo
->Comment
= NULL
;
869 /***********************************************************************
870 * EnumerateSecurityPackagesA (SECUR32.@)
872 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesA(PULONG pcPackages
,
873 PSecPkgInfoA
*ppPackageInfo
)
878 ret
= EnumerateSecurityPackagesW(pcPackages
, &info
);
879 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
881 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
882 if (*pcPackages
&& !*ppPackageInfo
)
885 ret
= SEC_E_INSUFFICIENT_MEMORY
;
887 FreeContextBuffer(info
);
892 /***********************************************************************
893 * GetComputerObjectNameA (SECUR32.@)
895 * Get the local computer's name using the format specified.
898 * NameFormat [I] The format for the name.
899 * lpNameBuffer [O] Pointer to buffer to receive the name.
900 * nSize [I/O] Size in characters of buffer.
903 * TRUE If the name was written to lpNameBuffer.
904 * FALSE If the name couldn't be written.
907 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
908 * name will be returned in *nSize.
910 * nSize returns the number of characters written when lpNameBuffer is not
911 * NULL or the size of the buffer needed to hold the name when the buffer
912 * is too short or lpNameBuffer is NULL.
914 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
916 BOOLEAN WINAPI
GetComputerObjectNameA(
917 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
920 LPWSTR bufferW
= NULL
;
921 ULONG sizeW
= *nSize
;
922 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
924 bufferW
= HeapAlloc(GetProcessHeap(), 0, sizeW
* sizeof(WCHAR
));
925 if (bufferW
== NULL
) {
926 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
930 rc
= GetComputerObjectNameW(NameFormat
, bufferW
, &sizeW
);
932 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
933 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
938 HeapFree(GetProcessHeap(), 0, bufferW
);
942 /***********************************************************************
943 * GetComputerObjectNameW (SECUR32.@)
945 BOOLEAN WINAPI
GetComputerObjectNameW(
946 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
948 LSA_HANDLE policyHandle
;
949 LSA_OBJECT_ATTRIBUTES objectAttributes
;
950 PPOLICY_DNS_DOMAIN_INFO domainInfo
;
953 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
955 if (NameFormat
== NameUnknown
)
957 SetLastError(ERROR_INVALID_PARAMETER
);
961 ZeroMemory(&objectAttributes
, sizeof(objectAttributes
));
962 objectAttributes
.Length
= sizeof(objectAttributes
);
964 ntStatus
= LsaOpenPolicy(NULL
, &objectAttributes
,
965 POLICY_VIEW_LOCAL_INFORMATION
,
967 if (ntStatus
!= STATUS_SUCCESS
)
969 SetLastError(LsaNtStatusToWinError(ntStatus
));
970 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
974 ntStatus
= LsaQueryInformationPolicy(policyHandle
,
975 PolicyDnsDomainInformation
,
976 (PVOID
*)&domainInfo
);
977 if (ntStatus
!= STATUS_SUCCESS
)
979 SetLastError(LsaNtStatusToWinError(ntStatus
));
980 WARN("LsaQueryInformationPolicy failed with NT status %u\n",
982 LsaClose(policyHandle
);
990 case NameSamCompatible
:
992 WCHAR name
[MAX_COMPUTERNAME_LENGTH
+ 1];
993 DWORD size
= sizeof(name
)/sizeof(name
[0]);
994 if (GetComputerNameW(name
, &size
))
996 DWORD len
= domainInfo
->Name
.Length
+ size
+ 3;
1002 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1007 WCHAR bs
[] = { '\\', 0 };
1008 WCHAR ds
[] = { '$', 0 };
1009 lstrcpyW(lpNameBuffer
, domainInfo
->Name
.Buffer
);
1010 lstrcatW(lpNameBuffer
, bs
);
1011 lstrcatW(lpNameBuffer
, name
);
1012 lstrcatW(lpNameBuffer
, ds
);
1016 else /* just requesting length required */
1024 SetLastError(ERROR_INTERNAL_ERROR
);
1029 case NameFullyQualifiedDN
:
1033 case NameUserPrincipal
:
1034 case NameCanonicalEx
:
1035 case NameServicePrincipal
:
1037 FIXME("NameFormat %d not implemented\n", NameFormat
);
1038 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
1042 SetLastError(ERROR_INVALID_PARAMETER
);
1048 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
1052 LsaFreeMemory(domainInfo
);
1053 LsaClose(policyHandle
);
1058 /***********************************************************************
1059 * GetUserNameExA (SECUR32.@)
1061 BOOLEAN WINAPI
GetUserNameExA(
1062 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
1065 LPWSTR bufferW
= NULL
;
1066 ULONG sizeW
= *nSize
;
1067 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
1069 bufferW
= HeapAlloc(GetProcessHeap(), 0, sizeW
* sizeof(WCHAR
));
1070 if (bufferW
== NULL
) {
1071 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1075 rc
= GetUserNameExW(NameFormat
, bufferW
, &sizeW
);
1077 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
1080 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
1087 SetLastError(ERROR_MORE_DATA
);
1092 HeapFree(GetProcessHeap(), 0, bufferW
);
1096 BOOLEAN WINAPI
GetUserNameExW(
1097 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
1100 WCHAR samname
[UNLEN
+ 1 + MAX_COMPUTERNAME_LENGTH
+ 1];
1103 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
1107 case NameSamCompatible
:
1109 /* This assumes the current user is always a local account */
1110 len
= MAX_COMPUTERNAME_LENGTH
+ 1;
1111 if (GetComputerNameW(samname
, &len
))
1113 out
= samname
+ lstrlenW(samname
);
1116 if (GetUserNameW(out
, &len
))
1118 status
= (lstrlenW(samname
) < *nSize
);
1121 lstrcpyW(lpNameBuffer
, samname
);
1122 *nSize
= lstrlenW(samname
);
1126 SetLastError(ERROR_MORE_DATA
);
1127 *nSize
= lstrlenW(samname
) + 1;
1138 case NameFullyQualifiedDN
:
1142 case NameUserPrincipal
:
1143 case NameCanonicalEx
:
1144 case NameServicePrincipal
:
1146 SetLastError(ERROR_NONE_MAPPED
);
1150 SetLastError(ERROR_INVALID_PARAMETER
);
1157 BOOLEAN WINAPI
TranslateNameA(
1158 LPCSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1159 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPSTR lpTranslatedName
,
1162 FIXME("%p %d %d %p %p\n", lpAccountName
, AccountNameFormat
,
1163 DesiredNameFormat
, lpTranslatedName
, nSize
);
1167 BOOLEAN WINAPI
TranslateNameW(
1168 LPCWSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1169 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPWSTR lpTranslatedName
,
1172 FIXME("%p %d %d %p %p\n", lpAccountName
, AccountNameFormat
,
1173 DesiredNameFormat
, lpTranslatedName
, nSize
);
1177 /***********************************************************************
1178 * DllMain (SECUR32.0)
1180 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
1182 if (fdwReason
== DLL_PROCESS_ATTACH
)
1184 DisableThreadLibraryCalls(hinstDLL
);
1185 SECUR32_initializeProviders();
1187 else if (fdwReason
== DLL_PROCESS_DETACH
)
1189 SECUR32_freeProviders();