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"
36 #include "wine/list.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(secur32
);
45 typedef struct _SecurePackageTable
52 typedef struct _SecureProviderTable
57 } SecureProviderTable
;
63 /* Tries to load moduleName as a provider. If successful, enumerates what
64 * packages it can and adds them to the package and provider tables. Resizes
65 * tables as necessary.
67 static void _tryLoadProvider(PWSTR moduleName
);
69 /* Initialization: read securityproviders value and attempt to open each dll
70 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
71 * Two undocumented functions, AddSecurityPackage(A/W) and
72 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
73 * unregister a dll, but I'm not sure.
75 static void SECUR32_initializeProviders(void);
77 /* Frees all loaded packages and providers */
78 static void SECUR32_freeProviders(void);
84 static CRITICAL_SECTION cs
;
85 static SecurePackageTable
*packageTable
= NULL
;
86 static SecureProviderTable
*providerTable
= NULL
;
88 static SecurityFunctionTableA securityFunctionTableA
= {
89 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
90 EnumerateSecurityPackagesA
,
91 QueryCredentialsAttributesA
,
92 AcquireCredentialsHandleA
,
93 FreeCredentialsHandle
,
95 InitializeSecurityContextA
,
96 AcceptSecurityContext
,
98 DeleteSecurityContext
,
100 QueryContextAttributesA
,
101 ImpersonateSecurityContext
,
102 RevertSecurityContext
,
106 QuerySecurityPackageInfoA
,
107 NULL
, /* Reserved3 */
108 NULL
, /* Reserved4 */
109 ExportSecurityContext
,
110 ImportSecurityContextA
,
112 NULL
, /* Reserved8 */
113 QuerySecurityContextToken
,
116 SetContextAttributesA
119 static SecurityFunctionTableW securityFunctionTableW
= {
120 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
121 EnumerateSecurityPackagesW
,
122 QueryCredentialsAttributesW
,
123 AcquireCredentialsHandleW
,
124 FreeCredentialsHandle
,
125 NULL
, /* Reserved2 */
126 InitializeSecurityContextW
,
127 AcceptSecurityContext
,
129 DeleteSecurityContext
,
131 QueryContextAttributesW
,
132 ImpersonateSecurityContext
,
133 RevertSecurityContext
,
137 QuerySecurityPackageInfoW
,
138 NULL
, /* Reserved3 */
139 NULL
, /* Reserved4 */
140 ExportSecurityContext
,
141 ImportSecurityContextW
,
143 NULL
, /* Reserved8 */
144 QuerySecurityContextToken
,
147 SetContextAttributesW
150 /***********************************************************************
151 * InitSecurityInterfaceA (SECUR32.@)
153 PSecurityFunctionTableA WINAPI
InitSecurityInterfaceA(void)
155 return &securityFunctionTableA
;
158 /***********************************************************************
159 * InitSecurityInterfaceW (SECUR32.@)
161 PSecurityFunctionTableW WINAPI
InitSecurityInterfaceW(void)
163 return &securityFunctionTableW
;
166 PWSTR
SECUR32_strdupW(PCWSTR str
)
172 ret
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str
) + 1) * sizeof(WCHAR
));
181 PWSTR
SECUR32_AllocWideFromMultiByte(PCSTR str
)
187 int charsNeeded
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
191 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
* sizeof(WCHAR
));
193 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, charsNeeded
);
203 PSTR
SECUR32_AllocMultiByteFromWide(PCWSTR str
)
209 int charsNeeded
= WideCharToMultiByte(CP_ACP
, 0, str
, -1, NULL
, 0,
214 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
);
216 WideCharToMultiByte(CP_ACP
, 0, str
, -1, ret
, charsNeeded
,
227 static void _makeFnTableA(PSecurityFunctionTableA fnTableA
,
228 const SecurityFunctionTableA
*inFnTableA
,
229 const SecurityFunctionTableW
*inFnTableW
)
235 /* The size of the version 1 table is based on platform sdk's
236 * sspi.h, though the sample ssp also provided with platform sdk
237 * implies only functions through QuerySecurityPackageInfoA are
238 * implemented (yikes)
240 size_t tableSize
= inFnTableA
->dwVersion
== 1 ?
241 (const BYTE
*)&inFnTableA
->SetContextAttributesA
-
242 (const BYTE
*)inFnTableA
: sizeof(SecurityFunctionTableA
);
244 memcpy(fnTableA
, inFnTableA
, tableSize
);
245 /* override this, since we can do it internally anyway */
246 fnTableA
->QuerySecurityPackageInfoA
=
247 QuerySecurityPackageInfoA
;
251 /* functions with thunks */
252 if (inFnTableW
->AcquireCredentialsHandleW
)
253 fnTableA
->AcquireCredentialsHandleA
=
254 thunk_AcquireCredentialsHandleA
;
255 if (inFnTableW
->InitializeSecurityContextW
)
256 fnTableA
->InitializeSecurityContextA
=
257 thunk_InitializeSecurityContextA
;
258 if (inFnTableW
->ImportSecurityContextW
)
259 fnTableA
->ImportSecurityContextA
=
260 thunk_ImportSecurityContextA
;
261 if (inFnTableW
->AddCredentialsW
)
262 fnTableA
->AddCredentialsA
=
263 thunk_AddCredentialsA
;
264 if (inFnTableW
->QueryCredentialsAttributesW
)
265 fnTableA
->QueryCredentialsAttributesA
=
266 thunk_QueryCredentialsAttributesA
;
267 if (inFnTableW
->QueryContextAttributesW
)
268 fnTableA
->QueryContextAttributesA
=
269 thunk_QueryContextAttributesA
;
270 if (inFnTableW
->SetContextAttributesW
)
271 fnTableA
->SetContextAttributesA
=
272 thunk_SetContextAttributesA
;
273 /* this can't be thunked, there's no extra param to know which
274 * package to forward to */
275 fnTableA
->EnumerateSecurityPackagesA
= NULL
;
276 /* functions with no thunks needed */
277 fnTableA
->AcceptSecurityContext
= inFnTableW
->AcceptSecurityContext
;
278 fnTableA
->CompleteAuthToken
= inFnTableW
->CompleteAuthToken
;
279 fnTableA
->DeleteSecurityContext
= inFnTableW
->DeleteSecurityContext
;
280 fnTableA
->ImpersonateSecurityContext
=
281 inFnTableW
->ImpersonateSecurityContext
;
282 fnTableA
->RevertSecurityContext
= inFnTableW
->RevertSecurityContext
;
283 fnTableA
->MakeSignature
= inFnTableW
->MakeSignature
;
284 fnTableA
->VerifySignature
= inFnTableW
->VerifySignature
;
285 fnTableA
->FreeContextBuffer
= inFnTableW
->FreeContextBuffer
;
286 fnTableA
->QuerySecurityPackageInfoA
=
287 QuerySecurityPackageInfoA
;
288 fnTableA
->ExportSecurityContext
=
289 inFnTableW
->ExportSecurityContext
;
290 fnTableA
->QuerySecurityContextToken
=
291 inFnTableW
->QuerySecurityContextToken
;
292 fnTableA
->EncryptMessage
= inFnTableW
->EncryptMessage
;
293 fnTableA
->DecryptMessage
= inFnTableW
->DecryptMessage
;
298 static void _makeFnTableW(PSecurityFunctionTableW fnTableW
,
299 const SecurityFunctionTableA
*inFnTableA
,
300 const SecurityFunctionTableW
*inFnTableW
)
306 /* The size of the version 1 table is based on platform sdk's
307 * sspi.h, though the sample ssp also provided with platform sdk
308 * implies only functions through QuerySecurityPackageInfoA are
309 * implemented (yikes)
311 size_t tableSize
= inFnTableW
->dwVersion
== 1 ?
312 (const BYTE
*)&inFnTableW
->SetContextAttributesW
-
313 (const BYTE
*)inFnTableW
: sizeof(SecurityFunctionTableW
);
315 memcpy(fnTableW
, inFnTableW
, tableSize
);
316 /* override this, since we can do it internally anyway */
317 fnTableW
->QuerySecurityPackageInfoW
=
318 QuerySecurityPackageInfoW
;
322 /* functions with thunks */
323 if (inFnTableA
->AcquireCredentialsHandleA
)
324 fnTableW
->AcquireCredentialsHandleW
=
325 thunk_AcquireCredentialsHandleW
;
326 if (inFnTableA
->InitializeSecurityContextA
)
327 fnTableW
->InitializeSecurityContextW
=
328 thunk_InitializeSecurityContextW
;
329 if (inFnTableA
->ImportSecurityContextA
)
330 fnTableW
->ImportSecurityContextW
=
331 thunk_ImportSecurityContextW
;
332 if (inFnTableA
->AddCredentialsA
)
333 fnTableW
->AddCredentialsW
=
334 thunk_AddCredentialsW
;
335 if (inFnTableA
->QueryCredentialsAttributesA
)
336 fnTableW
->QueryCredentialsAttributesW
=
337 thunk_QueryCredentialsAttributesW
;
338 if (inFnTableA
->QueryContextAttributesA
)
339 fnTableW
->QueryContextAttributesW
=
340 thunk_QueryContextAttributesW
;
341 if (inFnTableA
->SetContextAttributesA
)
342 fnTableW
->SetContextAttributesW
=
343 thunk_SetContextAttributesW
;
344 /* this can't be thunked, there's no extra param to know which
345 * package to forward to */
346 fnTableW
->EnumerateSecurityPackagesW
= NULL
;
347 /* functions with no thunks needed */
348 fnTableW
->AcceptSecurityContext
= inFnTableA
->AcceptSecurityContext
;
349 fnTableW
->CompleteAuthToken
= inFnTableA
->CompleteAuthToken
;
350 fnTableW
->DeleteSecurityContext
= inFnTableA
->DeleteSecurityContext
;
351 fnTableW
->ImpersonateSecurityContext
=
352 inFnTableA
->ImpersonateSecurityContext
;
353 fnTableW
->RevertSecurityContext
= inFnTableA
->RevertSecurityContext
;
354 fnTableW
->MakeSignature
= inFnTableA
->MakeSignature
;
355 fnTableW
->VerifySignature
= inFnTableA
->VerifySignature
;
356 fnTableW
->FreeContextBuffer
= inFnTableA
->FreeContextBuffer
;
357 fnTableW
->QuerySecurityPackageInfoW
=
358 QuerySecurityPackageInfoW
;
359 fnTableW
->ExportSecurityContext
=
360 inFnTableA
->ExportSecurityContext
;
361 fnTableW
->QuerySecurityContextToken
=
362 inFnTableA
->QuerySecurityContextToken
;
363 fnTableW
->EncryptMessage
= inFnTableA
->EncryptMessage
;
364 fnTableW
->DecryptMessage
= inFnTableA
->DecryptMessage
;
369 static void _copyPackageInfo(PSecPkgInfoW info
, const SecPkgInfoA
*inInfoA
,
370 const SecPkgInfoW
*inInfoW
)
372 if (info
&& (inInfoA
|| inInfoW
))
374 /* odd, I know, but up until Name and Comment the structures are
377 memcpy(info
, inInfoW
? inInfoW
: (const SecPkgInfoW
*)inInfoA
, sizeof(*info
));
380 info
->Name
= SECUR32_strdupW(inInfoW
->Name
);
381 info
->Comment
= SECUR32_strdupW(inInfoW
->Comment
);
385 info
->Name
= SECUR32_AllocWideFromMultiByte(inInfoA
->Name
);
386 info
->Comment
= SECUR32_AllocWideFromMultiByte(inInfoA
->Comment
);
391 SecureProvider
*SECUR32_addProvider(const SecurityFunctionTableA
*fnTableA
,
392 const SecurityFunctionTableW
*fnTableW
, PCWSTR moduleName
)
396 EnterCriticalSection(&cs
);
400 providerTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable
));
403 LeaveCriticalSection(&cs
);
407 list_init(&providerTable
->table
);
410 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider
));
413 LeaveCriticalSection(&cs
);
417 list_add_tail(&providerTable
->table
, &ret
->entry
);
420 if (fnTableA
|| fnTableW
)
422 ret
->moduleName
= moduleName
? SECUR32_strdupW(moduleName
) : NULL
;
423 _makeFnTableA(&ret
->fnTableA
, fnTableA
, fnTableW
);
424 _makeFnTableW(&ret
->fnTableW
, fnTableA
, fnTableW
);
425 ret
->loaded
= moduleName
? FALSE
: TRUE
;
429 ret
->moduleName
= SECUR32_strdupW(moduleName
);
433 LeaveCriticalSection(&cs
);
437 void SECUR32_addPackages(SecureProvider
*provider
, ULONG toAdd
,
438 const SecPkgInfoA
*infoA
, const SecPkgInfoW
*infoW
)
443 assert(infoA
|| infoW
);
445 EnterCriticalSection(&cs
);
449 packageTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable
));
452 LeaveCriticalSection(&cs
);
456 packageTable
->numPackages
= 0;
457 list_init(&packageTable
->table
);
460 for (i
= 0; i
< toAdd
; i
++)
462 SecurePackage
*package
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage
));
466 list_add_tail(&packageTable
->table
, &package
->entry
);
468 package
->provider
= provider
;
469 _copyPackageInfo(&package
->infoW
,
470 infoA
? &infoA
[i
] : NULL
,
471 infoW
? &infoW
[i
] : NULL
);
473 packageTable
->numPackages
+= toAdd
;
475 LeaveCriticalSection(&cs
);
478 static void _tryLoadProvider(PWSTR moduleName
)
480 HMODULE lib
= LoadLibraryW(moduleName
);
484 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
485 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(lib
,
486 SECURITY_ENTRYPOINT_ANSIW
);
487 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
488 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(lib
,
489 SECURITY_ENTRYPOINT_ANSIA
);
491 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
492 debugstr_w(moduleName
), pInitSecurityInterfaceA
,
493 pInitSecurityInterfaceW
);
494 if (pInitSecurityInterfaceW
|| pInitSecurityInterfaceA
)
496 PSecurityFunctionTableA fnTableA
= NULL
;
497 PSecurityFunctionTableW fnTableW
= NULL
;
499 PSecPkgInfoA infoA
= NULL
;
500 PSecPkgInfoW infoW
= NULL
;
501 SECURITY_STATUS ret
= SEC_E_OK
;
503 if (pInitSecurityInterfaceA
)
504 fnTableA
= pInitSecurityInterfaceA();
505 if (pInitSecurityInterfaceW
)
506 fnTableW
= pInitSecurityInterfaceW();
507 if (fnTableW
&& fnTableW
->EnumerateSecurityPackagesW
)
509 if (fnTableW
!= &securityFunctionTableW
)
510 ret
= fnTableW
->EnumerateSecurityPackagesW(&toAdd
, &infoW
);
512 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
514 else if (fnTableA
&& fnTableA
->EnumerateSecurityPackagesA
)
516 if (fnTableA
!= &securityFunctionTableA
)
517 ret
= fnTableA
->EnumerateSecurityPackagesA(&toAdd
, &infoA
);
519 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
521 if (ret
== SEC_E_OK
&& toAdd
> 0 && (infoW
|| infoA
))
523 SecureProvider
*provider
= SECUR32_addProvider(NULL
, NULL
,
527 SECUR32_addPackages(provider
, toAdd
, infoA
, infoW
);
529 fnTableW
->FreeContextBuffer(infoW
);
531 fnTableA
->FreeContextBuffer(infoA
);
537 WARN("failed to load %s\n", debugstr_w(moduleName
));
540 static const WCHAR securityProvidersKeyW
[] = {
541 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
542 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
543 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
545 static const WCHAR securityProvidersW
[] = {
546 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
549 static void SECUR32_initializeProviders(void)
555 InitializeCriticalSection(&cs
);
556 cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": cs");
557 /* First load built-in providers */
558 SECUR32_initSchannelSP();
559 /* Do not load Negotiate yet. This breaks for some user on the wine-users
560 * mailing list as of 2006-09-12. Without Negotiate, applications should
561 * fall back to NTLM and that should work.*/
563 SECUR32_initNegotiateSP();
565 SECUR32_initNTLMSP();
566 /* Now load providers from registry */
567 apiRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, securityProvidersKeyW
, 0,
569 if (apiRet
== ERROR_SUCCESS
)
571 WCHAR securityPkgNames
[MAX_PATH
]; /* arbitrary len */
572 DWORD size
= sizeof(securityPkgNames
) / sizeof(WCHAR
), type
;
574 apiRet
= RegQueryValueExW(key
, securityProvidersW
, NULL
, &type
,
575 (PBYTE
)securityPkgNames
, &size
);
576 if (apiRet
== ERROR_SUCCESS
&& type
== REG_SZ
)
580 size
= size
/ sizeof(WCHAR
);
581 for (ptr
= securityPkgNames
;
582 ptr
< securityPkgNames
+ size
; )
586 for (comma
= ptr
; *comma
&& *comma
!= ','; comma
++)
590 for (; *ptr
&& isspace(*ptr
) && ptr
< securityPkgNames
+ size
;
594 _tryLoadProvider(ptr
);
595 ptr
+= lstrlenW(ptr
) + 1;
602 SecurePackage
*SECUR32_findPackageW(PCWSTR packageName
)
604 SecurePackage
*ret
= NULL
;
605 BOOL matched
= FALSE
;
607 if (packageTable
&& packageName
)
609 LIST_FOR_EACH_ENTRY(ret
, &packageTable
->table
, SecurePackage
, entry
)
611 matched
= !lstrcmpiW(ret
->infoW
.Name
, packageName
);
619 if (ret
->provider
&& !ret
->provider
->loaded
)
621 ret
->provider
->lib
= LoadLibraryW(ret
->provider
->moduleName
);
622 if (ret
->provider
->lib
)
624 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
625 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(ret
->provider
->lib
,
626 SECURITY_ENTRYPOINT_ANSIW
);
627 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
628 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(ret
->provider
->lib
,
629 SECURITY_ENTRYPOINT_ANSIA
);
630 PSecurityFunctionTableA fnTableA
= NULL
;
631 PSecurityFunctionTableW fnTableW
= NULL
;
633 if (pInitSecurityInterfaceA
)
634 fnTableA
= pInitSecurityInterfaceA();
635 if (pInitSecurityInterfaceW
)
636 fnTableW
= pInitSecurityInterfaceW();
637 /* dont't update built-in SecurityFunctionTable */
638 if (fnTableA
!= &securityFunctionTableA
)
639 _makeFnTableA(&ret
->provider
->fnTableA
, fnTableA
, fnTableW
);
640 if (fnTableW
!= &securityFunctionTableW
)
641 _makeFnTableW(&ret
->provider
->fnTableW
, fnTableA
, fnTableW
);
642 ret
->provider
->loaded
= TRUE
;
651 SecurePackage
*SECUR32_findPackageA(PCSTR packageName
)
655 if (packageTable
&& packageName
)
657 UNICODE_STRING package
;
659 RtlCreateUnicodeStringFromAsciiz(&package
, packageName
);
660 ret
= SECUR32_findPackageW(package
.Buffer
);
661 RtlFreeUnicodeString(&package
);
668 static void SECUR32_freeProviders(void)
670 SecurePackage
*package
;
671 SecureProvider
*provider
;
674 EnterCriticalSection(&cs
);
678 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
680 HeapFree(GetProcessHeap(), 0, package
->infoW
.Name
);
681 HeapFree(GetProcessHeap(), 0, package
->infoW
.Comment
);
684 HeapFree(GetProcessHeap(), 0, packageTable
);
690 LIST_FOR_EACH_ENTRY(provider
, &providerTable
->table
, SecureProvider
, entry
)
692 HeapFree(GetProcessHeap(), 0, provider
->moduleName
);
694 FreeLibrary(provider
->lib
);
697 HeapFree(GetProcessHeap(), 0, providerTable
);
698 providerTable
= NULL
;
701 LeaveCriticalSection(&cs
);
702 cs
.DebugInfo
->Spare
[0] = 0;
703 DeleteCriticalSection(&cs
);
706 /***********************************************************************
707 * FreeContextBuffer (SECUR32.@)
709 * Doh--if pv was allocated by a crypto package, this may not be correct.
710 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
711 * be any guarantee, nor is there an alloc function in secur32.
713 SECURITY_STATUS WINAPI
FreeContextBuffer(PVOID pv
)
715 HeapFree(GetProcessHeap(), 0, pv
);
720 /***********************************************************************
721 * EnumerateSecurityPackagesW (SECUR32.@)
723 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesW(PULONG pcPackages
,
724 PSecPkgInfoW
*ppPackageInfo
)
726 SECURITY_STATUS ret
= SEC_E_OK
;
728 TRACE("(%p, %p)\n", pcPackages
, ppPackageInfo
);
730 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
732 EnterCriticalSection(&cs
);
735 SecurePackage
*package
;
738 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
739 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
741 if (package
->infoW
.Name
)
742 bytesNeeded
+= (lstrlenW(package
->infoW
.Name
) + 1) * sizeof(WCHAR
);
743 if (package
->infoW
.Comment
)
744 bytesNeeded
+= (lstrlenW(package
->infoW
.Comment
) + 1) * sizeof(WCHAR
);
748 *ppPackageInfo
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
754 *pcPackages
= packageTable
->numPackages
;
755 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
756 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
757 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
759 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
++;
761 *pkgInfo
= package
->infoW
;
762 if (package
->infoW
.Name
)
764 TRACE("Name[%d] = %s\n", i
- 1, debugstr_w(package
->infoW
.Name
));
765 pkgInfo
->Name
= nextString
;
766 lstrcpyW(nextString
, package
->infoW
.Name
);
767 nextString
+= lstrlenW(nextString
) + 1;
770 pkgInfo
->Name
= NULL
;
771 if (package
->infoW
.Comment
)
773 TRACE("Comment[%d] = %s\n", i
- 1, debugstr_w(package
->infoW
.Comment
));
774 pkgInfo
->Comment
= nextString
;
775 lstrcpyW(nextString
, package
->infoW
.Comment
);
776 nextString
+= lstrlenW(nextString
) + 1;
779 pkgInfo
->Comment
= NULL
;
783 ret
= SEC_E_INSUFFICIENT_MEMORY
;
786 LeaveCriticalSection(&cs
);
787 TRACE("<-- 0x%08x\n", ret
);
791 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
792 * structures) into an array of SecPkgInfoA structures, which it returns.
794 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
795 const SecPkgInfoW
*info
)
801 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
804 for (i
= 0; i
< cPackages
; i
++)
807 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
808 -1, NULL
, 0, NULL
, NULL
);
810 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
811 -1, NULL
, 0, NULL
, NULL
);
813 ret
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
818 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
819 for (i
= 0; i
< cPackages
; i
++)
821 PSecPkgInfoA pkgInfo
= ret
+ i
;
824 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
827 pkgInfo
->Name
= nextString
;
828 /* just repeat back to WideCharToMultiByte how many bytes
829 * it requires, since we asked it earlier
831 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
832 NULL
, 0, NULL
, NULL
);
833 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
834 pkgInfo
->Name
, bytes
, NULL
, NULL
);
835 nextString
+= lstrlenA(nextString
) + 1;
838 pkgInfo
->Name
= NULL
;
841 pkgInfo
->Comment
= nextString
;
842 /* just repeat back to WideCharToMultiByte how many bytes
843 * it requires, since we asked it earlier
845 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
846 NULL
, 0, NULL
, NULL
);
847 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
848 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
849 nextString
+= lstrlenA(nextString
) + 1;
852 pkgInfo
->Comment
= NULL
;
861 /***********************************************************************
862 * EnumerateSecurityPackagesA (SECUR32.@)
864 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesA(PULONG pcPackages
,
865 PSecPkgInfoA
*ppPackageInfo
)
870 ret
= EnumerateSecurityPackagesW(pcPackages
, &info
);
871 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
873 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
874 if (*pcPackages
&& !*ppPackageInfo
)
877 ret
= SEC_E_INSUFFICIENT_MEMORY
;
879 FreeContextBuffer(info
);
884 /***********************************************************************
885 * GetComputerObjectNameA (SECUR32.@)
887 * Get the local computer's name using the format specified.
890 * NameFormat [I] The format for the name.
891 * lpNameBuffer [O] Pointer to buffer to receive the name.
892 * nSize [I/O] Size in characters of buffer.
895 * TRUE If the name was written to lpNameBuffer.
896 * FALSE If the name couldn't be written.
899 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
900 * name will be returned in *nSize.
902 * nSize returns the number of characters written when lpNameBuffer is not
903 * NULL or the size of the buffer needed to hold the name when the buffer
904 * is too short or lpNameBuffer is NULL.
906 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
908 BOOLEAN WINAPI
GetComputerObjectNameA(
909 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
912 LPWSTR bufferW
= NULL
;
913 ULONG sizeW
= *nSize
;
914 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
916 bufferW
= HeapAlloc(GetProcessHeap(), 0, sizeW
* sizeof(WCHAR
));
917 if (bufferW
== NULL
) {
918 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
922 rc
= GetComputerObjectNameW(NameFormat
, bufferW
, &sizeW
);
924 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
925 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
930 HeapFree(GetProcessHeap(), 0, bufferW
);
934 /***********************************************************************
935 * GetComputerObjectNameW (SECUR32.@)
937 BOOLEAN WINAPI
GetComputerObjectNameW(
938 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
940 LSA_HANDLE policyHandle
;
941 LSA_OBJECT_ATTRIBUTES objectAttributes
;
942 PPOLICY_DNS_DOMAIN_INFO domainInfo
;
945 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
947 if (NameFormat
== NameUnknown
)
949 SetLastError(ERROR_INVALID_PARAMETER
);
953 ZeroMemory(&objectAttributes
, sizeof(objectAttributes
));
954 objectAttributes
.Length
= sizeof(objectAttributes
);
956 ntStatus
= LsaOpenPolicy(NULL
, &objectAttributes
,
957 POLICY_VIEW_LOCAL_INFORMATION
,
959 if (ntStatus
!= STATUS_SUCCESS
)
961 SetLastError(LsaNtStatusToWinError(ntStatus
));
962 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
966 ntStatus
= LsaQueryInformationPolicy(policyHandle
,
967 PolicyDnsDomainInformation
,
968 (PVOID
*)&domainInfo
);
969 if (ntStatus
!= STATUS_SUCCESS
)
971 SetLastError(LsaNtStatusToWinError(ntStatus
));
972 WARN("LsaQueryInformationPolicy failed with NT status %u\n",
974 LsaClose(policyHandle
);
982 case NameSamCompatible
:
984 WCHAR name
[MAX_COMPUTERNAME_LENGTH
+ 1];
985 DWORD size
= sizeof(name
);
986 if (GetComputerNameW(name
, &size
))
988 int len
= domainInfo
->Name
.Length
+ size
+ 3;
994 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
999 WCHAR bs
[] = { '\\', 0 };
1000 WCHAR ds
[] = { '$', 0 };
1001 lstrcpyW(lpNameBuffer
, domainInfo
->Name
.Buffer
);
1002 lstrcatW(lpNameBuffer
, bs
);
1003 lstrcatW(lpNameBuffer
, name
);
1004 lstrcatW(lpNameBuffer
, ds
);
1008 else /* just requesting length required */
1016 SetLastError(ERROR_INTERNAL_ERROR
);
1021 case NameFullyQualifiedDN
:
1025 case NameUserPrincipal
:
1026 case NameCanonicalEx
:
1027 case NameServicePrincipal
:
1029 FIXME("NameFormat %d not implemented\n", NameFormat
);
1030 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
1034 SetLastError(ERROR_INVALID_PARAMETER
);
1040 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
1044 LsaFreeMemory(domainInfo
);
1045 LsaClose(policyHandle
);
1050 /***********************************************************************
1051 * GetUserNameExA (SECUR32.@)
1053 BOOLEAN WINAPI
GetUserNameExA(
1054 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
1056 FIXME("%d %p %p\n", NameFormat
, lpNameBuffer
, nSize
);
1060 BOOLEAN WINAPI
GetUserNameExW(
1061 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
1063 FIXME("%d %p %p\n", NameFormat
, lpNameBuffer
, nSize
);
1067 BOOLEAN WINAPI
TranslateNameA(
1068 LPCSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1069 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPSTR lpTranslatedName
,
1072 FIXME("%p %d %d %p %p\n", lpAccountName
, AccountNameFormat
,
1073 DesiredNameFormat
, lpTranslatedName
, nSize
);
1077 BOOLEAN WINAPI
TranslateNameW(
1078 LPCWSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1079 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPWSTR lpTranslatedName
,
1082 FIXME("%p %d %d %p %p\n", lpAccountName
, AccountNameFormat
,
1083 DesiredNameFormat
, lpTranslatedName
, nSize
);
1087 /***********************************************************************
1088 * DllMain (SECUR32.0)
1090 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
1092 if (fdwReason
== DLL_PROCESS_ATTACH
)
1094 DisableThreadLibraryCalls(hinstDLL
);
1095 SECUR32_initializeProviders();
1097 else if (fdwReason
== DLL_PROCESS_DETACH
)
1099 SECUR32_freeProviders();