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
24 #define WIN32_NO_STATUS
37 #include "wine/list.h"
38 #include "wine/debug.h"
39 #include "secur32_priv.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(secur32
);
49 typedef struct _SecurePackageTable
56 typedef struct _SecureProviderTable
61 } SecureProviderTable
;
67 /* Tries to load moduleName as a provider. If successful, enumerates what
68 * packages it can and adds them to the package and provider tables. Resizes
69 * tables as necessary.
71 static void _tryLoadProvider(PWSTR moduleName
);
73 /* Initialization: read securityproviders value and attempt to open each dll
74 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
75 * Two undocumented functions, AddSecurityPackage(A/W) and
76 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
77 * unregister a dll, but I'm not sure.
79 static void SECUR32_initializeProviders(void);
81 /* Frees all loaded packages and providers */
82 static void SECUR32_freeProviders(void);
88 static CRITICAL_SECTION cs
;
89 static CRITICAL_SECTION_DEBUG cs_debug
=
92 { &cs_debug
.ProcessLocksList
, &cs_debug
.ProcessLocksList
},
93 0, 0, { (DWORD_PTR
)(__FILE__
": cs") }
95 static CRITICAL_SECTION cs
= { &cs_debug
, -1, 0, 0, 0, 0 };
96 static SecurePackageTable
*packageTable
= NULL
;
97 static SecureProviderTable
*providerTable
= NULL
;
99 static SecurityFunctionTableA securityFunctionTableA
= {
100 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
101 EnumerateSecurityPackagesA
,
102 QueryCredentialsAttributesA
,
103 AcquireCredentialsHandleA
,
104 FreeCredentialsHandle
,
105 NULL
, /* Reserved2 */
106 InitializeSecurityContextA
,
107 AcceptSecurityContext
,
109 DeleteSecurityContext
,
111 QueryContextAttributesA
,
112 ImpersonateSecurityContext
,
113 RevertSecurityContext
,
117 QuerySecurityPackageInfoA
,
118 EncryptMessage
, /* Reserved3 */
119 DecryptMessage
, /* Reserved4 */
120 ExportSecurityContext
,
121 ImportSecurityContextA
,
123 NULL
, /* Reserved8 */
124 QuerySecurityContextToken
,
127 SetContextAttributesA
130 static SecurityFunctionTableW securityFunctionTableW
= {
131 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
132 EnumerateSecurityPackagesW
,
133 QueryCredentialsAttributesW
,
134 AcquireCredentialsHandleW
,
135 FreeCredentialsHandle
,
136 NULL
, /* Reserved2 */
137 InitializeSecurityContextW
,
138 AcceptSecurityContext
,
140 DeleteSecurityContext
,
142 QueryContextAttributesW
,
143 ImpersonateSecurityContext
,
144 RevertSecurityContext
,
148 QuerySecurityPackageInfoW
,
149 EncryptMessage
, /* Reserved3 */
150 DecryptMessage
, /* Reserved4 */
151 ExportSecurityContext
,
152 ImportSecurityContextW
,
154 NULL
, /* Reserved8 */
155 QuerySecurityContextToken
,
158 SetContextAttributesW
161 /***********************************************************************
162 * InitSecurityInterfaceA (SECUR32.@)
164 PSecurityFunctionTableA WINAPI
InitSecurityInterfaceA(void)
166 return &securityFunctionTableA
;
169 /***********************************************************************
170 * InitSecurityInterfaceW (SECUR32.@)
172 PSecurityFunctionTableW WINAPI
InitSecurityInterfaceW(void)
174 return &securityFunctionTableW
;
177 static WCHAR
*strdupW( const WCHAR
*str
)
180 if (str
&& (ret
= malloc( (wcslen(str
) + 1) * sizeof(WCHAR
) ))) wcscpy( ret
, str
);
184 static void _makeFnTableA(PSecurityFunctionTableA fnTableA
,
185 const SecurityFunctionTableA
*inFnTableA
,
186 const SecurityFunctionTableW
*inFnTableW
)
192 /* The size of the version 1 table is based on platform sdk's
193 * sspi.h, though the sample ssp also provided with platform sdk
194 * implies only functions through QuerySecurityPackageInfoA are
195 * implemented (yikes)
197 size_t tableSize
= inFnTableA
->dwVersion
== 1 ?
198 offsetof(SecurityFunctionTableA
, SetContextAttributesA
) :
199 sizeof(SecurityFunctionTableA
);
201 memcpy(fnTableA
, inFnTableA
, tableSize
);
202 /* override this, since we can do it internally anyway */
203 fnTableA
->QuerySecurityPackageInfoA
=
204 QuerySecurityPackageInfoA
;
208 /* functions with thunks */
209 if (inFnTableW
->AcquireCredentialsHandleW
)
210 fnTableA
->AcquireCredentialsHandleA
=
211 thunk_AcquireCredentialsHandleA
;
212 if (inFnTableW
->InitializeSecurityContextW
)
213 fnTableA
->InitializeSecurityContextA
=
214 thunk_InitializeSecurityContextA
;
215 if (inFnTableW
->ImportSecurityContextW
)
216 fnTableA
->ImportSecurityContextA
=
217 thunk_ImportSecurityContextA
;
218 if (inFnTableW
->AddCredentialsW
)
219 fnTableA
->AddCredentialsA
=
220 thunk_AddCredentialsA
;
221 if (inFnTableW
->QueryCredentialsAttributesW
)
222 fnTableA
->QueryCredentialsAttributesA
=
223 thunk_QueryCredentialsAttributesA
;
224 if (inFnTableW
->QueryContextAttributesW
)
225 fnTableA
->QueryContextAttributesA
=
226 thunk_QueryContextAttributesA
;
227 if (inFnTableW
->SetContextAttributesW
)
228 fnTableA
->SetContextAttributesA
=
229 thunk_SetContextAttributesA
;
230 /* this can't be thunked, there's no extra param to know which
231 * package to forward to */
232 fnTableA
->EnumerateSecurityPackagesA
= NULL
;
233 /* functions with no thunks needed */
234 fnTableA
->AcceptSecurityContext
= inFnTableW
->AcceptSecurityContext
;
235 fnTableA
->CompleteAuthToken
= inFnTableW
->CompleteAuthToken
;
236 fnTableA
->DeleteSecurityContext
= inFnTableW
->DeleteSecurityContext
;
237 fnTableA
->ImpersonateSecurityContext
=
238 inFnTableW
->ImpersonateSecurityContext
;
239 fnTableA
->RevertSecurityContext
= inFnTableW
->RevertSecurityContext
;
240 fnTableA
->MakeSignature
= inFnTableW
->MakeSignature
;
241 fnTableA
->VerifySignature
= inFnTableW
->VerifySignature
;
242 fnTableA
->FreeContextBuffer
= inFnTableW
->FreeContextBuffer
;
243 fnTableA
->QuerySecurityPackageInfoA
=
244 QuerySecurityPackageInfoA
;
245 fnTableA
->ExportSecurityContext
=
246 inFnTableW
->ExportSecurityContext
;
247 fnTableA
->QuerySecurityContextToken
=
248 inFnTableW
->QuerySecurityContextToken
;
249 fnTableA
->EncryptMessage
= inFnTableW
->EncryptMessage
;
250 fnTableA
->DecryptMessage
= inFnTableW
->DecryptMessage
;
255 static void _makeFnTableW(PSecurityFunctionTableW fnTableW
,
256 const SecurityFunctionTableA
*inFnTableA
,
257 const SecurityFunctionTableW
*inFnTableW
)
263 /* The size of the version 1 table is based on platform sdk's
264 * sspi.h, though the sample ssp also provided with platform sdk
265 * implies only functions through QuerySecurityPackageInfoA are
266 * implemented (yikes)
268 size_t tableSize
= inFnTableW
->dwVersion
== 1 ?
269 offsetof(SecurityFunctionTableW
, SetContextAttributesW
) :
270 sizeof(SecurityFunctionTableW
);
272 memcpy(fnTableW
, inFnTableW
, tableSize
);
273 /* override this, since we can do it internally anyway */
274 fnTableW
->QuerySecurityPackageInfoW
=
275 QuerySecurityPackageInfoW
;
279 /* functions with thunks */
280 if (inFnTableA
->AcquireCredentialsHandleA
)
281 fnTableW
->AcquireCredentialsHandleW
=
282 thunk_AcquireCredentialsHandleW
;
283 if (inFnTableA
->InitializeSecurityContextA
)
284 fnTableW
->InitializeSecurityContextW
=
285 thunk_InitializeSecurityContextW
;
286 if (inFnTableA
->ImportSecurityContextA
)
287 fnTableW
->ImportSecurityContextW
=
288 thunk_ImportSecurityContextW
;
289 if (inFnTableA
->AddCredentialsA
)
290 fnTableW
->AddCredentialsW
=
291 thunk_AddCredentialsW
;
292 if (inFnTableA
->QueryCredentialsAttributesA
)
293 fnTableW
->QueryCredentialsAttributesW
=
294 thunk_QueryCredentialsAttributesW
;
295 if (inFnTableA
->QueryContextAttributesA
)
296 fnTableW
->QueryContextAttributesW
=
297 thunk_QueryContextAttributesW
;
298 if (inFnTableA
->SetContextAttributesA
)
299 fnTableW
->SetContextAttributesW
=
300 thunk_SetContextAttributesW
;
301 /* this can't be thunked, there's no extra param to know which
302 * package to forward to */
303 fnTableW
->EnumerateSecurityPackagesW
= NULL
;
304 /* functions with no thunks needed */
305 fnTableW
->AcceptSecurityContext
= inFnTableA
->AcceptSecurityContext
;
306 fnTableW
->CompleteAuthToken
= inFnTableA
->CompleteAuthToken
;
307 fnTableW
->DeleteSecurityContext
= inFnTableA
->DeleteSecurityContext
;
308 fnTableW
->ImpersonateSecurityContext
=
309 inFnTableA
->ImpersonateSecurityContext
;
310 fnTableW
->RevertSecurityContext
= inFnTableA
->RevertSecurityContext
;
311 fnTableW
->MakeSignature
= inFnTableA
->MakeSignature
;
312 fnTableW
->VerifySignature
= inFnTableA
->VerifySignature
;
313 fnTableW
->FreeContextBuffer
= inFnTableA
->FreeContextBuffer
;
314 fnTableW
->QuerySecurityPackageInfoW
=
315 QuerySecurityPackageInfoW
;
316 fnTableW
->ExportSecurityContext
=
317 inFnTableA
->ExportSecurityContext
;
318 fnTableW
->QuerySecurityContextToken
=
319 inFnTableA
->QuerySecurityContextToken
;
320 fnTableW
->EncryptMessage
= inFnTableA
->EncryptMessage
;
321 fnTableW
->DecryptMessage
= inFnTableA
->DecryptMessage
;
326 static WCHAR
*strdupAW( const char *str
)
331 int len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
332 if ((ret
= malloc( len
* sizeof(WCHAR
) ))) MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
337 static void _copyPackageInfo(PSecPkgInfoW info
, const SecPkgInfoA
*inInfoA
,
338 const SecPkgInfoW
*inInfoW
)
340 if (info
&& (inInfoA
|| inInfoW
))
342 /* odd, I know, but up until Name and Comment the structures are
345 memcpy(info
, inInfoW
? inInfoW
: (const SecPkgInfoW
*)inInfoA
, sizeof(*info
));
348 info
->Name
= strdupW(inInfoW
->Name
);
349 info
->Comment
= strdupW(inInfoW
->Comment
);
353 info
->Name
= strdupAW(inInfoA
->Name
);
354 info
->Comment
= strdupAW(inInfoA
->Comment
);
359 SecureProvider
*SECUR32_addProvider(const SecurityFunctionTableA
*fnTableA
,
360 const SecurityFunctionTableW
*fnTableW
, PCWSTR moduleName
)
364 EnterCriticalSection(&cs
);
368 if (!(providerTable
= malloc(sizeof(*ret
))))
370 LeaveCriticalSection(&cs
);
374 list_init(&providerTable
->table
);
377 if (!(ret
= malloc(sizeof(*ret
))))
379 LeaveCriticalSection(&cs
);
383 list_add_tail(&providerTable
->table
, &ret
->entry
);
386 if (fnTableA
|| fnTableW
)
388 ret
->moduleName
= moduleName
? strdupW(moduleName
) : NULL
;
389 _makeFnTableA(&ret
->fnTableA
, fnTableA
, fnTableW
);
390 _makeFnTableW(&ret
->fnTableW
, fnTableA
, fnTableW
);
391 ret
->loaded
= !moduleName
;
395 ret
->moduleName
= strdupW(moduleName
);
399 LeaveCriticalSection(&cs
);
403 void SECUR32_addPackages(SecureProvider
*provider
, ULONG toAdd
,
404 const SecPkgInfoA
*infoA
, const SecPkgInfoW
*infoW
)
409 assert(infoA
|| infoW
);
411 EnterCriticalSection(&cs
);
415 if (!(packageTable
= malloc(sizeof(*packageTable
))))
417 LeaveCriticalSection(&cs
);
421 packageTable
->numPackages
= 0;
422 list_init(&packageTable
->table
);
425 for (i
= 0; i
< toAdd
; i
++)
427 SecurePackage
*package
;
429 if (!(package
= malloc(sizeof(*package
)))) continue;
431 list_add_tail(&packageTable
->table
, &package
->entry
);
433 package
->provider
= provider
;
434 _copyPackageInfo(&package
->infoW
, infoA
? &infoA
[i
] : NULL
, infoW
? &infoW
[i
] : NULL
);
436 packageTable
->numPackages
+= toAdd
;
438 LeaveCriticalSection(&cs
);
441 static void _tryLoadProvider(PWSTR moduleName
)
443 HMODULE lib
= LoadLibraryW(moduleName
);
447 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
448 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(lib
,
449 SECURITY_ENTRYPOINT_ANSIW
);
450 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
451 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(lib
,
452 SECURITY_ENTRYPOINT_ANSIA
);
454 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
455 debugstr_w(moduleName
), pInitSecurityInterfaceA
,
456 pInitSecurityInterfaceW
);
457 if (pInitSecurityInterfaceW
|| pInitSecurityInterfaceA
)
459 PSecurityFunctionTableA fnTableA
= NULL
;
460 PSecurityFunctionTableW fnTableW
= NULL
;
462 PSecPkgInfoA infoA
= NULL
;
463 PSecPkgInfoW infoW
= NULL
;
464 SECURITY_STATUS ret
= SEC_E_OK
;
466 if (pInitSecurityInterfaceA
)
467 fnTableA
= pInitSecurityInterfaceA();
468 if (pInitSecurityInterfaceW
)
469 fnTableW
= pInitSecurityInterfaceW();
470 if (fnTableW
&& fnTableW
->EnumerateSecurityPackagesW
)
472 if (fnTableW
!= &securityFunctionTableW
)
473 ret
= fnTableW
->EnumerateSecurityPackagesW(&toAdd
, &infoW
);
475 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
477 else if (fnTableA
&& fnTableA
->EnumerateSecurityPackagesA
)
479 if (fnTableA
!= &securityFunctionTableA
)
480 ret
= fnTableA
->EnumerateSecurityPackagesA(&toAdd
, &infoA
);
482 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
484 if (ret
== SEC_E_OK
&& toAdd
> 0 && (infoW
|| infoA
))
486 SecureProvider
*provider
= SECUR32_addProvider(NULL
, NULL
,
490 SECUR32_addPackages(provider
, toAdd
, infoA
, infoW
);
492 fnTableW
->FreeContextBuffer(infoW
);
494 fnTableA
->FreeContextBuffer(infoA
);
500 WARN("failed to load %s\n", debugstr_w(moduleName
));
503 static void SECUR32_initializeProviders(void)
509 /* First load built-in providers */
510 SECUR32_initSchannelSP();
511 /* Load SSP/AP packages (Kerberos and others) */
512 load_auth_packages();
513 /* Load the Negotiate provider last so apps stumble over the working NTLM
514 * provider first. Attempting to fix bug #16905 while keeping the
515 * application reported on wine-users on 2006-09-12 working. */
516 SECUR32_initNegotiateSP();
517 /* Now load providers from registry */
518 apiRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\CurrentControlSet\\Control\\SecurityProviders", 0,
520 if (apiRet
== ERROR_SUCCESS
)
522 WCHAR securityPkgNames
[MAX_PATH
]; /* arbitrary len */
523 DWORD size
= sizeof(securityPkgNames
), type
;
525 apiRet
= RegQueryValueExW(key
, L
"SecurityProviders", NULL
, &type
, (PBYTE
)securityPkgNames
, &size
);
526 if (apiRet
== ERROR_SUCCESS
&& type
== REG_SZ
)
530 size
= size
/ sizeof(WCHAR
);
531 for (ptr
= securityPkgNames
;
532 ptr
< securityPkgNames
+ size
; )
536 for (comma
= ptr
; *comma
&& *comma
!= ','; comma
++)
540 for (; *ptr
&& iswspace(*ptr
) && ptr
< securityPkgNames
+ size
;
544 _tryLoadProvider(ptr
);
545 ptr
+= lstrlenW(ptr
) + 1;
552 SecurePackage
*SECUR32_findPackageW(PCWSTR packageName
)
554 SecurePackage
*ret
= NULL
;
555 BOOL matched
= FALSE
;
557 if (packageTable
&& packageName
)
559 LIST_FOR_EACH_ENTRY(ret
, &packageTable
->table
, SecurePackage
, entry
)
561 matched
= !lstrcmpiW(ret
->infoW
.Name
, packageName
);
564 if (!matched
) return NULL
;
566 if (ret
->provider
&& !ret
->provider
->loaded
)
568 ret
->provider
->lib
= LoadLibraryW(ret
->provider
->moduleName
);
569 if (ret
->provider
->lib
)
571 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
572 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(ret
->provider
->lib
,
573 SECURITY_ENTRYPOINT_ANSIW
);
574 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
575 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(ret
->provider
->lib
,
576 SECURITY_ENTRYPOINT_ANSIA
);
577 PSecurityFunctionTableA fnTableA
= NULL
;
578 PSecurityFunctionTableW fnTableW
= NULL
;
580 if (pInitSecurityInterfaceA
)
581 fnTableA
= pInitSecurityInterfaceA();
582 if (pInitSecurityInterfaceW
)
583 fnTableW
= pInitSecurityInterfaceW();
584 /* don't update built-in SecurityFunctionTable */
585 if (fnTableA
!= &securityFunctionTableA
)
586 _makeFnTableA(&ret
->provider
->fnTableA
, fnTableA
, fnTableW
);
587 if (fnTableW
!= &securityFunctionTableW
)
588 _makeFnTableW(&ret
->provider
->fnTableW
, fnTableA
, fnTableW
);
589 ret
->provider
->loaded
= TRUE
;
598 SecurePackage
*SECUR32_findPackageA(PCSTR packageName
)
602 if (packageTable
&& packageName
)
604 UNICODE_STRING package
;
606 RtlCreateUnicodeStringFromAsciiz(&package
, packageName
);
607 ret
= SECUR32_findPackageW(package
.Buffer
);
608 RtlFreeUnicodeString(&package
);
615 static void SECUR32_freeProviders(void)
618 EnterCriticalSection(&cs
);
620 SECUR32_deinitSchannelSP();
624 SecurePackage
*package
, *package_next
;
625 LIST_FOR_EACH_ENTRY_SAFE(package
, package_next
, &packageTable
->table
,
626 SecurePackage
, entry
)
628 free(package
->infoW
.Name
);
629 free(package
->infoW
.Comment
);
639 SecureProvider
*provider
, *provider_next
;
640 LIST_FOR_EACH_ENTRY_SAFE(provider
, provider_next
, &providerTable
->table
, SecureProvider
, entry
)
642 free(provider
->moduleName
);
643 if (provider
->lib
) FreeLibrary(provider
->lib
);
648 providerTable
= NULL
;
651 LeaveCriticalSection(&cs
);
652 DeleteCriticalSection(&cs
);
655 /***********************************************************************
656 * FreeContextBuffer (SECUR32.@)
658 * Doh--if pv was allocated by a crypto package, this may not be correct.
659 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
660 * be any guarantee, nor is there an alloc function in secur32.
662 SECURITY_STATUS WINAPI
FreeContextBuffer( void *pv
)
664 RtlFreeHeap( GetProcessHeap(), 0, pv
);
668 /***********************************************************************
669 * EnumerateSecurityPackagesW (SECUR32.@)
671 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesW(PULONG pcPackages
,
672 PSecPkgInfoW
*ppPackageInfo
)
674 SECURITY_STATUS ret
= SEC_E_OK
;
676 TRACE("(%p, %p)\n", pcPackages
, ppPackageInfo
);
678 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
680 EnterCriticalSection(&cs
);
683 SecurePackage
*package
;
686 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
687 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
689 if (package
->infoW
.Name
)
690 bytesNeeded
+= (lstrlenW(package
->infoW
.Name
) + 1) * sizeof(WCHAR
);
691 if (package
->infoW
.Comment
)
692 bytesNeeded
+= (lstrlenW(package
->infoW
.Comment
) + 1) * sizeof(WCHAR
);
696 /* freed with FeeContextBuffer */
697 if ((*ppPackageInfo
= RtlAllocateHeap(GetProcessHeap(), 0, bytesNeeded
)))
702 *pcPackages
= packageTable
->numPackages
;
703 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
704 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
705 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
707 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
++;
709 *pkgInfo
= package
->infoW
;
710 if (package
->infoW
.Name
)
712 TRACE("Name[%d] = %s\n", i
- 1, debugstr_w(package
->infoW
.Name
));
713 pkgInfo
->Name
= nextString
;
714 lstrcpyW(nextString
, package
->infoW
.Name
);
715 nextString
+= lstrlenW(nextString
) + 1;
718 pkgInfo
->Name
= NULL
;
719 if (package
->infoW
.Comment
)
721 TRACE("Comment[%d] = %s\n", i
- 1, debugstr_w(package
->infoW
.Comment
));
722 pkgInfo
->Comment
= nextString
;
723 lstrcpyW(nextString
, package
->infoW
.Comment
);
724 nextString
+= lstrlenW(nextString
) + 1;
727 pkgInfo
->Comment
= NULL
;
731 ret
= SEC_E_INSUFFICIENT_MEMORY
;
734 LeaveCriticalSection(&cs
);
735 TRACE("<-- 0x%08x\n", ret
);
739 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
740 * structures) into an array of SecPkgInfoA structures, which it returns.
742 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
743 const SecPkgInfoW
*info
)
749 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
752 for (i
= 0; i
< cPackages
; i
++)
755 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
756 -1, NULL
, 0, NULL
, NULL
);
758 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
759 -1, NULL
, 0, NULL
, NULL
);
761 /* freed with FreeContextBuffer */
762 if ((ret
= RtlAllocateHeap(GetProcessHeap(), 0, bytesNeeded
)))
766 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
767 for (i
= 0; i
< cPackages
; i
++)
769 PSecPkgInfoA pkgInfo
= ret
+ i
;
772 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
775 pkgInfo
->Name
= nextString
;
776 /* just repeat back to WideCharToMultiByte how many bytes
777 * it requires, since we asked it earlier
779 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
780 NULL
, 0, NULL
, NULL
);
781 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
782 pkgInfo
->Name
, bytes
, NULL
, NULL
);
783 nextString
+= lstrlenA(nextString
) + 1;
786 pkgInfo
->Name
= NULL
;
789 pkgInfo
->Comment
= nextString
;
790 /* just repeat back to WideCharToMultiByte how many bytes
791 * it requires, since we asked it earlier
793 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
794 NULL
, 0, NULL
, NULL
);
795 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
796 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
797 nextString
+= lstrlenA(nextString
) + 1;
800 pkgInfo
->Comment
= NULL
;
809 /***********************************************************************
810 * EnumerateSecurityPackagesA (SECUR32.@)
812 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesA(PULONG pcPackages
,
813 PSecPkgInfoA
*ppPackageInfo
)
818 ret
= EnumerateSecurityPackagesW(pcPackages
, &info
);
819 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
821 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
822 if (*pcPackages
&& !*ppPackageInfo
)
825 ret
= SEC_E_INSUFFICIENT_MEMORY
;
827 FreeContextBuffer(info
);
832 /***********************************************************************
833 * GetComputerObjectNameA (SECUR32.@)
835 * Get the local computer's name using the format specified.
838 * NameFormat [I] The format for the name.
839 * lpNameBuffer [O] Pointer to buffer to receive the name.
840 * nSize [I/O] Size in characters of buffer.
843 * TRUE If the name was written to lpNameBuffer.
844 * FALSE If the name couldn't be written.
847 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
848 * name will be returned in *nSize.
850 * nSize returns the number of characters written when lpNameBuffer is not
851 * NULL or the size of the buffer needed to hold the name when the buffer
852 * is too short or lpNameBuffer is NULL.
854 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
856 BOOLEAN WINAPI
GetComputerObjectNameA(
857 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
860 LPWSTR bufferW
= NULL
;
861 ULONG sizeW
= *nSize
;
863 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
866 if (!(bufferW
= malloc(sizeW
* sizeof(WCHAR
)))) {
867 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
871 rc
= GetComputerObjectNameW(NameFormat
, bufferW
, &sizeW
);
873 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
874 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
883 /***********************************************************************
884 * GetComputerObjectNameW (SECUR32.@)
886 BOOLEAN WINAPI
GetComputerObjectNameW(
887 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
889 LSA_HANDLE policyHandle
;
890 LSA_OBJECT_ATTRIBUTES objectAttributes
;
891 PPOLICY_DNS_DOMAIN_INFO domainInfo
;
895 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
897 if (NameFormat
== NameUnknown
)
899 SetLastError(ERROR_INVALID_PARAMETER
);
903 ZeroMemory(&objectAttributes
, sizeof(objectAttributes
));
904 objectAttributes
.Length
= sizeof(objectAttributes
);
906 ntStatus
= LsaOpenPolicy(NULL
, &objectAttributes
,
907 POLICY_VIEW_LOCAL_INFORMATION
,
909 if (ntStatus
!= STATUS_SUCCESS
)
911 SetLastError(LsaNtStatusToWinError(ntStatus
));
912 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
916 ntStatus
= LsaQueryInformationPolicy(policyHandle
,
917 PolicyDnsDomainInformation
,
918 (PVOID
*)&domainInfo
);
919 if (ntStatus
!= STATUS_SUCCESS
)
921 SetLastError(LsaNtStatusToWinError(ntStatus
));
922 WARN("LsaQueryInformationPolicy failed with NT status %u\n",
924 LsaClose(policyHandle
);
932 case NameSamCompatible
:
934 WCHAR name
[MAX_COMPUTERNAME_LENGTH
+ 1];
935 DWORD size
= ARRAY_SIZE(name
);
936 if (GetComputerNameW(name
, &size
))
938 DWORD len
= domainInfo
->Name
.Length
+ size
+ 3;
939 if (lpNameBuffer
&& *nSize
>= len
)
941 if (domainInfo
->Name
.Buffer
)
943 lstrcpyW(lpNameBuffer
, domainInfo
->Name
.Buffer
);
944 lstrcatW(lpNameBuffer
, L
"\\");
948 lstrcatW(lpNameBuffer
, name
);
949 lstrcatW(lpNameBuffer
, L
"$");
952 else /* just requesting length required */
955 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
961 SetLastError(ERROR_INTERNAL_ERROR
);
966 case NameFullyQualifiedDN
:
968 WCHAR name
[MAX_COMPUTERNAME_LENGTH
+ 1];
972 size
= ARRAY_SIZE(name
);
973 if (!GetComputerNameW(name
, &size
))
979 len
= wcslen(L
"CN=") + size
+ 1 + wcslen(L
"CN=Computers") + 1 + wcslen(L
"DC=");
980 if (domainInfo
->DnsDomainName
.Buffer
)
982 suffix
= wcsrchr(domainInfo
->DnsDomainName
.Buffer
, '.');
986 len
+= 1 + wcslen(L
"DC=") + wcslen(suffix
);
988 len
+= wcslen(domainInfo
->DnsDomainName
.Buffer
);
993 if (lpNameBuffer
&& *nSize
> len
)
995 lstrcpyW(lpNameBuffer
, L
"CN=");
996 lstrcatW(lpNameBuffer
, name
);
997 lstrcatW(lpNameBuffer
, L
",");
998 lstrcatW(lpNameBuffer
, L
"CN=Computers");
999 if (domainInfo
->DnsDomainName
.Buffer
)
1001 lstrcatW(lpNameBuffer
, L
",");
1002 lstrcatW(lpNameBuffer
, L
"DC=");
1003 lstrcatW(lpNameBuffer
, domainInfo
->DnsDomainName
.Buffer
);
1006 lstrcatW(lpNameBuffer
, L
",");
1007 lstrcatW(lpNameBuffer
, L
"DC=");
1008 lstrcatW(lpNameBuffer
, suffix
);
1013 else /* just requesting length required */
1015 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1024 case NameUserPrincipal
:
1025 case NameCanonicalEx
:
1026 case NameServicePrincipal
:
1028 FIXME("NameFormat %d not implemented\n", NameFormat
);
1029 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
1033 SetLastError(ERROR_INVALID_PARAMETER
);
1039 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
1043 LsaFreeMemory(domainInfo
);
1044 LsaClose(policyHandle
);
1049 SECURITY_STATUS WINAPI
AddSecurityPackageA(LPSTR name
, SECURITY_PACKAGE_OPTIONS
*options
)
1051 FIXME("(%s %p)\n", debugstr_a(name
), options
);
1055 SECURITY_STATUS WINAPI
AddSecurityPackageW(LPWSTR name
, SECURITY_PACKAGE_OPTIONS
*options
)
1057 FIXME("(%s %p)\n", debugstr_w(name
), options
);
1061 /***********************************************************************
1062 * GetUserNameExA (SECUR32.@)
1064 BOOLEAN WINAPI
GetUserNameExA(
1065 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
1068 LPWSTR bufferW
= NULL
;
1069 ULONG sizeW
= *nSize
;
1070 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
1072 bufferW
= malloc(sizeW
* sizeof(WCHAR
));
1073 if (bufferW
== NULL
) {
1074 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1078 rc
= GetUserNameExW(NameFormat
, bufferW
, &sizeW
);
1080 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
1083 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
1090 SetLastError(ERROR_MORE_DATA
);
1099 BOOLEAN WINAPI
GetUserNameExW(
1100 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
1102 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
1106 case NameSamCompatible
:
1108 WCHAR samname
[UNLEN
+ 1 + MAX_COMPUTERNAME_LENGTH
+ 1];
1112 /* This assumes the current user is always a local account */
1113 len
= MAX_COMPUTERNAME_LENGTH
+ 1;
1114 if (GetComputerNameW(samname
, &len
))
1116 out
= samname
+ lstrlenW(samname
);
1119 if (GetUserNameW(out
, &len
))
1121 if (lstrlenW(samname
) < *nSize
)
1123 lstrcpyW(lpNameBuffer
, samname
);
1124 *nSize
= lstrlenW(samname
);
1128 SetLastError(ERROR_MORE_DATA
);
1129 *nSize
= lstrlenW(samname
) + 1;
1136 case NameFullyQualifiedDN
:
1140 case NameUserPrincipal
:
1141 case NameCanonicalEx
:
1142 case NameServicePrincipal
:
1144 SetLastError(ERROR_NONE_MAPPED
);
1148 SetLastError(ERROR_INVALID_PARAMETER
);
1153 BOOLEAN WINAPI
TranslateNameA(
1154 LPCSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1155 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPSTR lpTranslatedName
,
1158 FIXME("%p %d %d %p %p\n", lpAccountName
, AccountNameFormat
,
1159 DesiredNameFormat
, lpTranslatedName
, nSize
);
1163 BOOLEAN WINAPI
TranslateNameW(
1164 LPCWSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1165 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPWSTR lpTranslatedName
,
1168 FIXME("%p %d %d %p %p\n", lpAccountName
, AccountNameFormat
,
1169 DesiredNameFormat
, lpTranslatedName
, nSize
);
1173 /***********************************************************************
1174 * DllMain (SECUR32.0)
1176 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD reason
, LPVOID reserved
)
1180 case DLL_PROCESS_ATTACH
:
1181 hsecur32
= hinstDLL
;
1182 DisableThreadLibraryCalls(hinstDLL
);
1183 SECUR32_initializeProviders();
1185 case DLL_PROCESS_DETACH
:
1186 if (reserved
) break;
1187 SECUR32_freeProviders();