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 #include <lsass/lsass.h>
25 #include <wine/debug.h>
26 WINE_DEFAULT_DEBUG_CHANNEL(secur32
);
30 typedef struct _SecurePackageTable
37 typedef struct _SecureProviderTable
42 } SecureProviderTable
;
44 static void SECUR32_initializeProviders(void);
46 static CRITICAL_SECTION cs
;
47 static CRITICAL_SECTION_DEBUG cs_debug
=
50 { &cs_debug
.ProcessLocksList
, &cs_debug
.ProcessLocksList
},
51 0, 0, { (DWORD_PTR
)(__FILE__
": cs") }
53 static CRITICAL_SECTION cs
= { &cs_debug
, -1, 0, 0, 0, 0 };
54 static SecurePackageTable
*packageTable
= NULL
;
55 static SecureProviderTable
*providerTable
= NULL
;
57 static SecurityFunctionTableA securityFunctionTableA
= {
58 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
59 EnumerateSecurityPackagesA
,
60 QueryCredentialsAttributesA
,
61 AcquireCredentialsHandleA
,
62 FreeCredentialsHandle
,
64 InitializeSecurityContextA
,
65 AcceptSecurityContext
,
67 DeleteSecurityContext
,
69 QueryContextAttributesA
,
70 ImpersonateSecurityContext
,
71 RevertSecurityContext
,
75 QuerySecurityPackageInfoA
,
76 EncryptMessage
, /* Reserved3 */
77 DecryptMessage
, /* Reserved4 */
78 ExportSecurityContext
,
79 ImportSecurityContextA
,
82 QuerySecurityContextToken
,
88 static SecurityFunctionTableW securityFunctionTableW
= {
89 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
90 EnumerateSecurityPackagesW
,
91 QueryCredentialsAttributesW
,
92 AcquireCredentialsHandleW
,
93 FreeCredentialsHandle
,
95 InitializeSecurityContextW
,
96 AcceptSecurityContext
,
98 DeleteSecurityContext
,
100 QueryContextAttributesW
,
101 ImpersonateSecurityContext
,
102 RevertSecurityContext
,
106 QuerySecurityPackageInfoW
,
107 EncryptMessage
, /* Reserved3 */
108 DecryptMessage
, /* Reserved4 */
109 ExportSecurityContext
,
110 ImportSecurityContextW
,
112 NULL
, /* Reserved8 */
113 QuerySecurityContextToken
,
119 /***********************************************************************
120 * InitSecurityInterfaceA (SECUR32.@)
122 PSecurityFunctionTableA WINAPI
InitSecurityInterfaceA(void)
124 TRACE("InitSecurityInterfaceA() called\n");
125 return &securityFunctionTableA
;
128 /***********************************************************************
129 * InitSecurityInterfaceW (SECUR32.@)
131 PSecurityFunctionTableW WINAPI
InitSecurityInterfaceW(void)
133 TRACE("InitSecurityInterfaceW() called\n");
134 return &securityFunctionTableW
;
137 static PWSTR
SECUR32_strdupW(PCWSTR str
)
143 ret
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str
) + 1) * sizeof(WCHAR
));
152 PWSTR
SECUR32_AllocWideFromMultiByte(PCSTR str
)
158 int charsNeeded
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
162 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
* sizeof(WCHAR
));
164 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, charsNeeded
);
174 PSTR
SECUR32_AllocMultiByteFromWide(PCWSTR str
)
180 int charsNeeded
= WideCharToMultiByte(CP_ACP
, 0, str
, -1, NULL
, 0,
185 ret
= HeapAlloc(GetProcessHeap(), 0, charsNeeded
);
187 WideCharToMultiByte(CP_ACP
, 0, str
, -1, ret
, charsNeeded
,
198 static void _makeFnTableA(PSecurityFunctionTableA fnTableA
,
199 const SecurityFunctionTableA
*inFnTableA
,
200 const SecurityFunctionTableW
*inFnTableW
)
206 /* The size of the version 1 table is based on platform sdk's
207 * sspi.h, though the sample ssp also provided with platform sdk
208 * implies only functions through QuerySecurityPackageInfoA are
209 * implemented (yikes)
211 size_t tableSize
= inFnTableA
->dwVersion
== 1 ?
212 (const BYTE
*)&inFnTableA
->SetContextAttributesA
-
213 (const BYTE
*)inFnTableA
: sizeof(SecurityFunctionTableA
);
215 memcpy(fnTableA
, inFnTableA
, tableSize
);
216 /* override this, since we can do it internally anyway */
217 fnTableA
->QuerySecurityPackageInfoA
=
218 QuerySecurityPackageInfoA
;
222 /* functions with thunks */
223 if (inFnTableW
->AcquireCredentialsHandleW
)
224 fnTableA
->AcquireCredentialsHandleA
=
225 thunk_AcquireCredentialsHandleA
;
226 if (inFnTableW
->InitializeSecurityContextW
)
227 fnTableA
->InitializeSecurityContextA
=
228 thunk_InitializeSecurityContextA
;
229 if (inFnTableW
->ImportSecurityContextW
)
230 fnTableA
->ImportSecurityContextA
=
231 thunk_ImportSecurityContextA
;
232 if (inFnTableW
->AddCredentialsW
)
233 fnTableA
->AddCredentialsA
=
234 thunk_AddCredentialsA
;
235 if (inFnTableW
->QueryCredentialsAttributesW
)
236 fnTableA
->QueryCredentialsAttributesA
=
237 thunk_QueryCredentialsAttributesA
;
238 if (inFnTableW
->QueryContextAttributesW
)
239 fnTableA
->QueryContextAttributesA
=
240 thunk_QueryContextAttributesA
;
241 if (inFnTableW
->SetContextAttributesW
)
242 fnTableA
->SetContextAttributesA
=
243 thunk_SetContextAttributesA
;
244 /* this can't be thunked, there's no extra param to know which
245 * package to forward to */
246 fnTableA
->EnumerateSecurityPackagesA
= NULL
;
247 /* functions with no thunks needed */
248 fnTableA
->AcceptSecurityContext
= inFnTableW
->AcceptSecurityContext
;
249 fnTableA
->CompleteAuthToken
= inFnTableW
->CompleteAuthToken
;
250 fnTableA
->DeleteSecurityContext
= inFnTableW
->DeleteSecurityContext
;
251 fnTableA
->ImpersonateSecurityContext
=
252 inFnTableW
->ImpersonateSecurityContext
;
253 fnTableA
->RevertSecurityContext
= inFnTableW
->RevertSecurityContext
;
254 fnTableA
->MakeSignature
= inFnTableW
->MakeSignature
;
255 fnTableA
->VerifySignature
= inFnTableW
->VerifySignature
;
256 fnTableA
->FreeContextBuffer
= inFnTableW
->FreeContextBuffer
;
257 fnTableA
->QuerySecurityPackageInfoA
=
258 QuerySecurityPackageInfoA
;
259 fnTableA
->ExportSecurityContext
=
260 inFnTableW
->ExportSecurityContext
;
261 fnTableA
->QuerySecurityContextToken
=
262 inFnTableW
->QuerySecurityContextToken
;
263 fnTableA
->EncryptMessage
= inFnTableW
->EncryptMessage
;
264 fnTableA
->DecryptMessage
= inFnTableW
->DecryptMessage
;
269 static void _makeFnTableW(PSecurityFunctionTableW fnTableW
,
270 const SecurityFunctionTableA
*inFnTableA
,
271 const SecurityFunctionTableW
*inFnTableW
)
277 /* The size of the version 1 table is based on platform sdk's
278 * sspi.h, though the sample ssp also provided with platform sdk
279 * implies only functions through QuerySecurityPackageInfoA are
280 * implemented (yikes)
282 size_t tableSize
= inFnTableW
->dwVersion
== 1 ?
283 (const BYTE
*)&inFnTableW
->SetContextAttributesW
-
284 (const BYTE
*)inFnTableW
: sizeof(SecurityFunctionTableW
);
286 memcpy(fnTableW
, inFnTableW
, tableSize
);
287 /* override this, since we can do it internally anyway */
288 fnTableW
->QuerySecurityPackageInfoW
=
289 QuerySecurityPackageInfoW
;
293 /* functions with thunks */
294 if (inFnTableA
->AcquireCredentialsHandleA
)
295 fnTableW
->AcquireCredentialsHandleW
=
296 thunk_AcquireCredentialsHandleW
;
297 if (inFnTableA
->InitializeSecurityContextA
)
298 fnTableW
->InitializeSecurityContextW
=
299 thunk_InitializeSecurityContextW
;
300 if (inFnTableA
->ImportSecurityContextA
)
301 fnTableW
->ImportSecurityContextW
=
302 thunk_ImportSecurityContextW
;
303 if (inFnTableA
->AddCredentialsA
)
304 fnTableW
->AddCredentialsW
=
305 thunk_AddCredentialsW
;
306 if (inFnTableA
->QueryCredentialsAttributesA
)
307 fnTableW
->QueryCredentialsAttributesW
=
308 thunk_QueryCredentialsAttributesW
;
309 if (inFnTableA
->QueryContextAttributesA
)
310 fnTableW
->QueryContextAttributesW
=
311 thunk_QueryContextAttributesW
;
312 if (inFnTableA
->SetContextAttributesA
)
313 fnTableW
->SetContextAttributesW
=
314 thunk_SetContextAttributesW
;
315 /* this can't be thunked, there's no extra param to know which
316 * package to forward to */
317 fnTableW
->EnumerateSecurityPackagesW
= NULL
;
318 /* functions with no thunks needed */
319 fnTableW
->AcceptSecurityContext
= inFnTableA
->AcceptSecurityContext
;
320 fnTableW
->CompleteAuthToken
= inFnTableA
->CompleteAuthToken
;
321 fnTableW
->DeleteSecurityContext
= inFnTableA
->DeleteSecurityContext
;
322 fnTableW
->ImpersonateSecurityContext
=
323 inFnTableA
->ImpersonateSecurityContext
;
324 fnTableW
->RevertSecurityContext
= inFnTableA
->RevertSecurityContext
;
325 fnTableW
->MakeSignature
= inFnTableA
->MakeSignature
;
326 fnTableW
->VerifySignature
= inFnTableA
->VerifySignature
;
327 fnTableW
->FreeContextBuffer
= inFnTableA
->FreeContextBuffer
;
328 fnTableW
->QuerySecurityPackageInfoW
=
329 QuerySecurityPackageInfoW
;
330 fnTableW
->ExportSecurityContext
=
331 inFnTableA
->ExportSecurityContext
;
332 fnTableW
->QuerySecurityContextToken
=
333 inFnTableA
->QuerySecurityContextToken
;
334 fnTableW
->EncryptMessage
= inFnTableA
->EncryptMessage
;
335 fnTableW
->DecryptMessage
= inFnTableA
->DecryptMessage
;
340 static void _copyPackageInfo(PSecPkgInfoW info
, const SecPkgInfoA
*inInfoA
,
341 const SecPkgInfoW
*inInfoW
)
343 if (info
&& (inInfoA
|| inInfoW
))
345 /* odd, I know, but up until Name and Comment the structures are
348 memcpy(info
, inInfoW
? inInfoW
: (const SecPkgInfoW
*)inInfoA
, sizeof(*info
));
351 info
->Name
= SECUR32_strdupW(inInfoW
->Name
);
352 info
->Comment
= SECUR32_strdupW(inInfoW
->Comment
);
356 info
->Name
= SECUR32_AllocWideFromMultiByte(inInfoA
->Name
);
357 info
->Comment
= SECUR32_AllocWideFromMultiByte(inInfoA
->Comment
);
363 SecureProvider
*SECUR32_addProvider(const SecurityFunctionTableA
*fnTableA
,
364 const SecurityFunctionTableW
*fnTableW
, PCWSTR moduleName
)
368 EnterCriticalSection(&cs
);
372 providerTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable
));
375 LeaveCriticalSection(&cs
);
379 list_init(&providerTable
->table
);
382 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider
));
385 LeaveCriticalSection(&cs
);
389 list_add_tail(&providerTable
->table
, &ret
->entry
);
392 if (fnTableA
|| fnTableW
)
394 ret
->moduleName
= moduleName
? SECUR32_strdupW(moduleName
) : NULL
;
395 _makeFnTableA(&ret
->fnTableA
, fnTableA
, fnTableW
);
396 _makeFnTableW(&ret
->fnTableW
, fnTableA
, fnTableW
);
397 ret
->loaded
= !moduleName
;
401 ret
->moduleName
= SECUR32_strdupW(moduleName
);
405 LeaveCriticalSection(&cs
);
410 void SECUR32_addPackages(SecureProvider
*provider
, ULONG toAdd
,
411 const SecPkgInfoA
*infoA
, const SecPkgInfoW
*infoW
)
416 assert(infoA
|| infoW
);
418 EnterCriticalSection(&cs
);
422 packageTable
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable
));
425 LeaveCriticalSection(&cs
);
429 packageTable
->numPackages
= 0;
430 list_init(&packageTable
->table
);
433 for (i
= 0; i
< toAdd
; i
++)
435 SecurePackage
*package
= HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage
));
439 list_add_tail(&packageTable
->table
, &package
->entry
);
441 package
->provider
= provider
;
442 _copyPackageInfo(&package
->infoW
,
443 infoA
? &infoA
[i
] : NULL
,
444 infoW
? &infoW
[i
] : NULL
);
446 packageTable
->numPackages
+= toAdd
;
448 LeaveCriticalSection(&cs
);
451 static void _tryLoadProvider(PWSTR moduleName
)
453 HMODULE lib
= LoadLibraryW(moduleName
);
457 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
458 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(lib
,
459 SECURITY_ENTRYPOINT_ANSIW
);
460 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
461 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(lib
,
462 SECURITY_ENTRYPOINT_ANSIA
);
464 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
465 debugstr_w(moduleName
), pInitSecurityInterfaceA
,
466 pInitSecurityInterfaceW
);
467 if (pInitSecurityInterfaceW
|| pInitSecurityInterfaceA
)
469 PSecurityFunctionTableA fnTableA
= NULL
;
470 PSecurityFunctionTableW fnTableW
= NULL
;
472 PSecPkgInfoA infoA
= NULL
;
473 PSecPkgInfoW infoW
= NULL
;
474 SECURITY_STATUS ret
= SEC_E_OK
;
476 if (pInitSecurityInterfaceA
)
477 fnTableA
= pInitSecurityInterfaceA();
478 if (pInitSecurityInterfaceW
)
479 fnTableW
= pInitSecurityInterfaceW();
480 if (fnTableW
&& fnTableW
->EnumerateSecurityPackagesW
)
482 if (fnTableW
!= &securityFunctionTableW
)
483 ret
= fnTableW
->EnumerateSecurityPackagesW(&toAdd
, &infoW
);
485 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
487 else if (fnTableA
&& fnTableA
->EnumerateSecurityPackagesA
)
489 if (fnTableA
!= &securityFunctionTableA
)
490 ret
= fnTableA
->EnumerateSecurityPackagesA(&toAdd
, &infoA
);
492 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
494 if (ret
== SEC_E_OK
&& toAdd
> 0 && (infoW
|| infoA
))
496 SecureProvider
*provider
= SECUR32_addProvider(NULL
, NULL
,
500 SECUR32_addPackages(provider
, toAdd
, infoA
, infoW
);
502 fnTableW
->FreeContextBuffer(infoW
);
504 fnTableA
->FreeContextBuffer(infoA
);
510 WARN("failed to load %s\n", debugstr_w(moduleName
));
513 static const WCHAR securityProvidersKeyW
[] = {
514 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
515 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
516 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
518 static const WCHAR securityProvidersW
[] = {
519 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
522 /* FIXME: we're missing SECUR32_freeProviders, so all of this gets leaked */
523 static void SECUR32_initializeProviders(void)
528 /* Now load providers from registry */
529 apiRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, securityProvidersKeyW
, 0,
531 if (apiRet
== ERROR_SUCCESS
)
533 WCHAR securityPkgNames
[MAX_PATH
]; /* arbitrary len */
534 DWORD size
= sizeof(securityPkgNames
) / sizeof(WCHAR
), type
;
536 apiRet
= RegQueryValueExW(key
, securityProvidersW
, NULL
, &type
,
537 (PBYTE
)securityPkgNames
, &size
);
538 if (apiRet
== ERROR_SUCCESS
&& type
== REG_SZ
)
542 size
= size
/ sizeof(WCHAR
);
543 for (ptr
= securityPkgNames
;
544 ptr
< securityPkgNames
+ size
; )
548 for (comma
= ptr
; *comma
&& *comma
!= ','; comma
++)
552 for (; *ptr
&& isspace(*ptr
) && ptr
< securityPkgNames
+ size
;
556 _tryLoadProvider(ptr
);
557 ptr
+= lstrlenW(ptr
) + 1;
564 SecurePackage
*SECUR32_findPackageW(PCWSTR packageName
)
566 SecurePackage
*ret
= NULL
;
567 BOOL matched
= FALSE
;
571 SECUR32_initializeProviders();
574 if (packageTable
&& packageName
)
576 LIST_FOR_EACH_ENTRY(ret
, &packageTable
->table
, SecurePackage
, entry
)
578 matched
= !lstrcmpiW(ret
->infoW
.Name
, packageName
);
586 if (ret
->provider
&& !ret
->provider
->loaded
)
588 ret
->provider
->lib
= LoadLibraryW(ret
->provider
->moduleName
);
589 if (ret
->provider
->lib
)
591 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
592 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(ret
->provider
->lib
,
593 SECURITY_ENTRYPOINT_ANSIW
);
594 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
595 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(ret
->provider
->lib
,
596 SECURITY_ENTRYPOINT_ANSIA
);
597 PSecurityFunctionTableA fnTableA
= NULL
;
598 PSecurityFunctionTableW fnTableW
= NULL
;
600 if (pInitSecurityInterfaceA
)
601 fnTableA
= pInitSecurityInterfaceA();
602 if (pInitSecurityInterfaceW
)
603 fnTableW
= pInitSecurityInterfaceW();
604 /* don't update built-in SecurityFunctionTable */
605 if (fnTableA
!= &securityFunctionTableA
)
606 _makeFnTableA(&ret
->provider
->fnTableA
, fnTableA
, fnTableW
);
607 if (fnTableW
!= &securityFunctionTableW
)
608 _makeFnTableW(&ret
->provider
->fnTableW
, fnTableA
, fnTableW
);
609 ret
->provider
->loaded
= TRUE
;
618 SecurePackage
*SECUR32_findPackageA(PCSTR packageName
)
624 UNICODE_STRING package
;
626 RtlCreateUnicodeStringFromAsciiz(&package
, packageName
);
627 ret
= SECUR32_findPackageW(package
.Buffer
);
628 RtlFreeUnicodeString(&package
);
635 /***********************************************************************
636 * FreeContextBuffer (SECUR32.@)
638 * Doh--if pv was allocated by a crypto package, this may not be correct.
639 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
640 * be any guarantee, nor is there an alloc function in secur32.
642 SECURITY_STATUS WINAPI
FreeContextBuffer(PVOID pv
)
644 HeapFree(GetProcessHeap(), 0, pv
);
649 /***********************************************************************
650 * EnumerateSecurityPackagesW (SECUR32.@)
652 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesW(PULONG pcPackages
,
653 PSecPkgInfoW
*ppPackageInfo
)
655 SECURITY_STATUS ret
= SEC_E_OK
;
657 TRACE("(%p, %p)\n", pcPackages
, ppPackageInfo
);
661 SECUR32_initializeProviders();
664 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
666 EnterCriticalSection(&cs
);
669 SecurePackage
*package
;
672 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
673 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
675 if (package
->infoW
.Name
)
676 bytesNeeded
+= (lstrlenW(package
->infoW
.Name
) + 1) * sizeof(WCHAR
);
677 if (package
->infoW
.Comment
)
678 bytesNeeded
+= (lstrlenW(package
->infoW
.Comment
) + 1) * sizeof(WCHAR
);
682 *ppPackageInfo
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
688 *pcPackages
= packageTable
->numPackages
;
689 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
690 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
691 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
693 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
++;
695 *pkgInfo
= package
->infoW
;
696 if (package
->infoW
.Name
)
698 TRACE("Name[%d] = %s\n", i
- 1, debugstr_w(package
->infoW
.Name
));
699 pkgInfo
->Name
= nextString
;
700 lstrcpyW(nextString
, package
->infoW
.Name
);
701 nextString
+= lstrlenW(nextString
) + 1;
704 pkgInfo
->Name
= NULL
;
705 if (package
->infoW
.Comment
)
707 TRACE("Comment[%d] = %s\n", i
- 1, debugstr_w(package
->infoW
.Comment
));
708 pkgInfo
->Comment
= nextString
;
709 lstrcpyW(nextString
, package
->infoW
.Comment
);
710 nextString
+= lstrlenW(nextString
) + 1;
713 pkgInfo
->Comment
= NULL
;
717 ret
= SEC_E_INSUFFICIENT_MEMORY
;
720 LeaveCriticalSection(&cs
);
721 TRACE("<-- 0x%08x\n", ret
);
725 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
726 * structures) into an array of SecPkgInfoA structures, which it returns.
728 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
729 const SecPkgInfoW
*info
)
735 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
738 for (i
= 0; i
< cPackages
; i
++)
741 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
742 -1, NULL
, 0, NULL
, NULL
);
744 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
745 -1, NULL
, 0, NULL
, NULL
);
747 ret
= HeapAlloc(GetProcessHeap(), 0, bytesNeeded
);
752 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
753 for (i
= 0; i
< cPackages
; i
++)
755 PSecPkgInfoA pkgInfo
= ret
+ i
;
758 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
761 pkgInfo
->Name
= nextString
;
762 /* just repeat back to WideCharToMultiByte how many bytes
763 * it requires, since we asked it earlier
765 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
766 NULL
, 0, NULL
, NULL
);
767 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
768 pkgInfo
->Name
, bytes
, NULL
, NULL
);
769 nextString
+= lstrlenA(nextString
) + 1;
772 pkgInfo
->Name
= NULL
;
775 pkgInfo
->Comment
= 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
].Comment
, -1,
780 NULL
, 0, NULL
, NULL
);
781 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
782 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
783 nextString
+= lstrlenA(nextString
) + 1;
786 pkgInfo
->Comment
= NULL
;
795 /***********************************************************************
796 * EnumerateSecurityPackagesA (SECUR32.@)
798 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesA(PULONG pcPackages
,
799 PSecPkgInfoA
*ppPackageInfo
)
804 ret
= EnumerateSecurityPackagesW(pcPackages
, &info
);
805 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
807 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
808 if (*pcPackages
&& !*ppPackageInfo
)
811 ret
= SEC_E_INSUFFICIENT_MEMORY
;
813 FreeContextBuffer(info
);
818 /***********************************************************************
819 * GetComputerObjectNameA (SECUR32.@)
821 * Get the local computer's name using the format specified.
824 * NameFormat [I] The format for the name.
825 * lpNameBuffer [O] Pointer to buffer to receive the name.
826 * nSize [I/O] Size in characters of buffer.
829 * TRUE If the name was written to lpNameBuffer.
830 * FALSE If the name couldn't be written.
833 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
834 * name will be returned in *nSize.
836 * nSize returns the number of characters written when lpNameBuffer is not
837 * NULL or the size of the buffer needed to hold the name when the buffer
838 * is too short or lpNameBuffer is NULL.
840 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
842 BOOLEAN WINAPI
GetComputerObjectNameA(
843 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
846 LPWSTR bufferW
= NULL
;
847 ULONG sizeW
= *nSize
;
848 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
850 bufferW
= HeapAlloc(GetProcessHeap(), 0, sizeW
* sizeof(WCHAR
));
851 if (bufferW
== NULL
) {
852 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
856 rc
= GetComputerObjectNameW(NameFormat
, bufferW
, &sizeW
);
858 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
859 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
864 HeapFree(GetProcessHeap(), 0, bufferW
);
868 /***********************************************************************
869 * GetComputerObjectNameW (SECUR32.@)
871 BOOLEAN WINAPI
GetComputerObjectNameW(
872 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
874 LSA_HANDLE policyHandle
;
875 LSA_OBJECT_ATTRIBUTES objectAttributes
;
876 PPOLICY_DNS_DOMAIN_INFO domainInfo
;
879 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
881 if (NameFormat
== NameUnknown
)
883 SetLastError(ERROR_INVALID_PARAMETER
);
887 ZeroMemory(&objectAttributes
, sizeof(objectAttributes
));
888 objectAttributes
.Length
= sizeof(objectAttributes
);
890 ntStatus
= LsaOpenPolicy(NULL
, &objectAttributes
,
891 POLICY_VIEW_LOCAL_INFORMATION
,
893 if (ntStatus
!= STATUS_SUCCESS
)
895 SetLastError(LsaNtStatusToWinError(ntStatus
));
896 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
900 ntStatus
= LsaQueryInformationPolicy(policyHandle
,
901 PolicyDnsDomainInformation
,
902 (PVOID
*)&domainInfo
);
903 if (ntStatus
!= STATUS_SUCCESS
)
905 SetLastError(LsaNtStatusToWinError(ntStatus
));
906 WARN("LsaQueryInformationPolicy failed with NT status %u\n",
908 LsaClose(policyHandle
);
916 case NameSamCompatible
:
918 WCHAR name
[MAX_COMPUTERNAME_LENGTH
+ 1];
919 DWORD size
= sizeof(name
)/sizeof(name
[0]);
920 if (GetComputerNameW(name
, &size
))
922 DWORD len
= domainInfo
->Name
.Length
+ size
+ 3;
928 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
933 WCHAR bs
[] = { '\\', 0 };
934 WCHAR ds
[] = { '$', 0 };
935 lstrcpyW(lpNameBuffer
, domainInfo
->Name
.Buffer
);
936 lstrcatW(lpNameBuffer
, bs
);
937 lstrcatW(lpNameBuffer
, name
);
938 lstrcatW(lpNameBuffer
, ds
);
942 else /* just requesting length required */
950 SetLastError(ERROR_INTERNAL_ERROR
);
955 case NameFullyQualifiedDN
:
959 case NameUserPrincipal
:
960 case NameCanonicalEx
:
961 case NameServicePrincipal
:
963 FIXME("NameFormat %d not implemented\n", NameFormat
);
964 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
968 SetLastError(ERROR_INVALID_PARAMETER
);
974 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
978 LsaFreeMemory(domainInfo
);
979 LsaClose(policyHandle
);
984 /***********************************************************************
985 * GetUserNameExA (SECUR32.@)
987 BOOLEAN WINAPI
GetUserNameExA(
988 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
991 LPWSTR bufferW
= NULL
;
992 ULONG sizeW
= *nSize
;
993 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
995 bufferW
= HeapAlloc(GetProcessHeap(), 0, sizeW
* sizeof(WCHAR
));
996 if (bufferW
== NULL
) {
997 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1001 rc
= GetUserNameExW(NameFormat
, bufferW
, &sizeW
);
1003 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
1006 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
1013 SetLastError(ERROR_MORE_DATA
);
1018 HeapFree(GetProcessHeap(), 0, bufferW
);
1022 BOOLEAN WINAPI
GetUserNameExW(
1023 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
1025 TRACE("(%d %p %p)\n", NameFormat
, lpNameBuffer
, nSize
);
1029 case NameSamCompatible
:
1031 WCHAR samname
[UNLEN
+ 1 + MAX_COMPUTERNAME_LENGTH
+ 1];
1035 /* This assumes the current user is always a local account */
1036 len
= MAX_COMPUTERNAME_LENGTH
+ 1;
1037 if (GetComputerNameW(samname
, &len
))
1039 out
= samname
+ lstrlenW(samname
);
1042 if (GetUserNameW(out
, &len
))
1044 if (lstrlenW(samname
) < *nSize
)
1046 lstrcpyW(lpNameBuffer
, samname
);
1047 *nSize
= lstrlenW(samname
);
1051 SetLastError(ERROR_MORE_DATA
);
1052 *nSize
= lstrlenW(samname
) + 1;
1059 case NameFullyQualifiedDN
:
1063 case NameUserPrincipal
:
1064 case NameCanonicalEx
:
1065 case NameServicePrincipal
:
1067 SetLastError(ERROR_NONE_MAPPED
);
1071 SetLastError(ERROR_INVALID_PARAMETER
);
1076 BOOLEAN WINAPI
TranslateNameA(
1077 LPCSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1078 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPSTR lpTranslatedName
,
1081 FIXME("%p %d %d %p %p\n", lpAccountName
, AccountNameFormat
,
1082 DesiredNameFormat
, lpTranslatedName
, nSize
);
1086 BOOLEAN WINAPI
TranslateNameW(
1087 LPCWSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1088 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPWSTR lpTranslatedName
,
1091 FIXME("%p %d %d %p %p\n", lpAccountName
, AccountNameFormat
,
1092 DesiredNameFormat
, lpTranslatedName
, nSize
);