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
);
47 typedef struct _SecurePackageTable
54 typedef struct _SecureProviderTable
59 } SecureProviderTable
;
65 /* Tries to load moduleName as a provider. If successful, enumerates what
66 * packages it can and adds them to the package and provider tables. Resizes
67 * tables as necessary.
69 static void _tryLoadProvider(PWSTR moduleName
);
71 /* Initialization: read securityproviders value and attempt to open each dll
72 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
73 * Two undocumented functions, AddSecurityPackage(A/W) and
74 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
75 * unregister a dll, but I'm not sure.
77 static void SECUR32_initializeProviders(void);
79 /* Frees all loaded packages and providers */
80 static void SECUR32_freeProviders(void);
86 static CRITICAL_SECTION cs
;
87 static CRITICAL_SECTION_DEBUG cs_debug
=
90 { &cs_debug
.ProcessLocksList
, &cs_debug
.ProcessLocksList
},
91 0, 0, { (DWORD_PTR
)(__FILE__
": cs") }
93 static CRITICAL_SECTION cs
= { &cs_debug
, -1, 0, 0, 0, 0 };
94 static SecurePackageTable
*packageTable
= NULL
;
95 static SecureProviderTable
*providerTable
= NULL
;
97 static SecurityFunctionTableA securityFunctionTableA
= {
98 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
99 EnumerateSecurityPackagesA
,
100 QueryCredentialsAttributesA
,
101 AcquireCredentialsHandleA
,
102 FreeCredentialsHandle
,
103 NULL
, /* Reserved2 */
104 InitializeSecurityContextA
,
105 AcceptSecurityContext
,
107 DeleteSecurityContext
,
109 QueryContextAttributesA
,
110 ImpersonateSecurityContext
,
111 RevertSecurityContext
,
115 QuerySecurityPackageInfoA
,
116 EncryptMessage
, /* Reserved3 */
117 DecryptMessage
, /* Reserved4 */
118 ExportSecurityContext
,
119 ImportSecurityContextA
,
121 NULL
, /* Reserved8 */
122 QuerySecurityContextToken
,
125 SetContextAttributesA
128 static SecurityFunctionTableW securityFunctionTableW
= {
129 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION
,
130 EnumerateSecurityPackagesW
,
131 QueryCredentialsAttributesW
,
132 AcquireCredentialsHandleW
,
133 FreeCredentialsHandle
,
134 NULL
, /* Reserved2 */
135 InitializeSecurityContextW
,
136 AcceptSecurityContext
,
138 DeleteSecurityContext
,
140 QueryContextAttributesW
,
141 ImpersonateSecurityContext
,
142 RevertSecurityContext
,
146 QuerySecurityPackageInfoW
,
147 EncryptMessage
, /* Reserved3 */
148 DecryptMessage
, /* Reserved4 */
149 ExportSecurityContext
,
150 ImportSecurityContextW
,
152 NULL
, /* Reserved8 */
153 QuerySecurityContextToken
,
156 SetContextAttributesW
159 /***********************************************************************
160 * InitSecurityInterfaceA (SECUR32.@)
162 PSecurityFunctionTableA WINAPI
InitSecurityInterfaceA(void)
164 return &securityFunctionTableA
;
167 /***********************************************************************
168 * InitSecurityInterfaceW (SECUR32.@)
170 PSecurityFunctionTableW WINAPI
InitSecurityInterfaceW(void)
172 return &securityFunctionTableW
;
175 static void _makeFnTableA(PSecurityFunctionTableA fnTableA
,
176 const SecurityFunctionTableA
*inFnTableA
,
177 const SecurityFunctionTableW
*inFnTableW
)
183 /* The size of the version 1 table is based on platform sdk's
184 * sspi.h, though the sample ssp also provided with platform sdk
185 * implies only functions through QuerySecurityPackageInfoA are
186 * implemented (yikes)
188 size_t tableSize
= inFnTableA
->dwVersion
== 1 ?
189 offsetof(SecurityFunctionTableA
, SetContextAttributesA
) :
190 sizeof(SecurityFunctionTableA
);
192 memcpy(fnTableA
, inFnTableA
, tableSize
);
193 /* override this, since we can do it internally anyway */
194 fnTableA
->QuerySecurityPackageInfoA
=
195 QuerySecurityPackageInfoA
;
199 /* functions with thunks */
200 if (inFnTableW
->AcquireCredentialsHandleW
)
201 fnTableA
->AcquireCredentialsHandleA
=
202 thunk_AcquireCredentialsHandleA
;
203 if (inFnTableW
->InitializeSecurityContextW
)
204 fnTableA
->InitializeSecurityContextA
=
205 thunk_InitializeSecurityContextA
;
206 if (inFnTableW
->ImportSecurityContextW
)
207 fnTableA
->ImportSecurityContextA
=
208 thunk_ImportSecurityContextA
;
209 if (inFnTableW
->AddCredentialsW
)
210 fnTableA
->AddCredentialsA
=
211 thunk_AddCredentialsA
;
212 if (inFnTableW
->QueryCredentialsAttributesW
)
213 fnTableA
->QueryCredentialsAttributesA
=
214 thunk_QueryCredentialsAttributesA
;
215 if (inFnTableW
->QueryContextAttributesW
)
216 fnTableA
->QueryContextAttributesA
=
217 thunk_QueryContextAttributesA
;
218 if (inFnTableW
->SetContextAttributesW
)
219 fnTableA
->SetContextAttributesA
=
220 thunk_SetContextAttributesA
;
221 /* this can't be thunked, there's no extra param to know which
222 * package to forward to */
223 fnTableA
->EnumerateSecurityPackagesA
= NULL
;
224 /* functions with no thunks needed */
225 fnTableA
->AcceptSecurityContext
= inFnTableW
->AcceptSecurityContext
;
226 fnTableA
->CompleteAuthToken
= inFnTableW
->CompleteAuthToken
;
227 fnTableA
->DeleteSecurityContext
= inFnTableW
->DeleteSecurityContext
;
228 fnTableA
->ImpersonateSecurityContext
=
229 inFnTableW
->ImpersonateSecurityContext
;
230 fnTableA
->RevertSecurityContext
= inFnTableW
->RevertSecurityContext
;
231 fnTableA
->MakeSignature
= inFnTableW
->MakeSignature
;
232 fnTableA
->VerifySignature
= inFnTableW
->VerifySignature
;
233 fnTableA
->FreeContextBuffer
= inFnTableW
->FreeContextBuffer
;
234 fnTableA
->QuerySecurityPackageInfoA
=
235 QuerySecurityPackageInfoA
;
236 fnTableA
->ExportSecurityContext
=
237 inFnTableW
->ExportSecurityContext
;
238 fnTableA
->QuerySecurityContextToken
=
239 inFnTableW
->QuerySecurityContextToken
;
240 fnTableA
->EncryptMessage
= inFnTableW
->EncryptMessage
;
241 fnTableA
->DecryptMessage
= inFnTableW
->DecryptMessage
;
246 static void _makeFnTableW(PSecurityFunctionTableW fnTableW
,
247 const SecurityFunctionTableA
*inFnTableA
,
248 const SecurityFunctionTableW
*inFnTableW
)
254 /* The size of the version 1 table is based on platform sdk's
255 * sspi.h, though the sample ssp also provided with platform sdk
256 * implies only functions through QuerySecurityPackageInfoA are
257 * implemented (yikes)
259 size_t tableSize
= inFnTableW
->dwVersion
== 1 ?
260 offsetof(SecurityFunctionTableW
, SetContextAttributesW
) :
261 sizeof(SecurityFunctionTableW
);
263 memcpy(fnTableW
, inFnTableW
, tableSize
);
264 /* override this, since we can do it internally anyway */
265 fnTableW
->QuerySecurityPackageInfoW
=
266 QuerySecurityPackageInfoW
;
270 /* functions with thunks */
271 if (inFnTableA
->AcquireCredentialsHandleA
)
272 fnTableW
->AcquireCredentialsHandleW
=
273 thunk_AcquireCredentialsHandleW
;
274 if (inFnTableA
->InitializeSecurityContextA
)
275 fnTableW
->InitializeSecurityContextW
=
276 thunk_InitializeSecurityContextW
;
277 if (inFnTableA
->ImportSecurityContextA
)
278 fnTableW
->ImportSecurityContextW
=
279 thunk_ImportSecurityContextW
;
280 if (inFnTableA
->AddCredentialsA
)
281 fnTableW
->AddCredentialsW
=
282 thunk_AddCredentialsW
;
283 if (inFnTableA
->QueryCredentialsAttributesA
)
284 fnTableW
->QueryCredentialsAttributesW
=
285 thunk_QueryCredentialsAttributesW
;
286 if (inFnTableA
->QueryContextAttributesA
)
287 fnTableW
->QueryContextAttributesW
=
288 thunk_QueryContextAttributesW
;
289 if (inFnTableA
->SetContextAttributesA
)
290 fnTableW
->SetContextAttributesW
=
291 thunk_SetContextAttributesW
;
292 /* this can't be thunked, there's no extra param to know which
293 * package to forward to */
294 fnTableW
->EnumerateSecurityPackagesW
= NULL
;
295 /* functions with no thunks needed */
296 fnTableW
->AcceptSecurityContext
= inFnTableA
->AcceptSecurityContext
;
297 fnTableW
->CompleteAuthToken
= inFnTableA
->CompleteAuthToken
;
298 fnTableW
->DeleteSecurityContext
= inFnTableA
->DeleteSecurityContext
;
299 fnTableW
->ImpersonateSecurityContext
=
300 inFnTableA
->ImpersonateSecurityContext
;
301 fnTableW
->RevertSecurityContext
= inFnTableA
->RevertSecurityContext
;
302 fnTableW
->MakeSignature
= inFnTableA
->MakeSignature
;
303 fnTableW
->VerifySignature
= inFnTableA
->VerifySignature
;
304 fnTableW
->FreeContextBuffer
= inFnTableA
->FreeContextBuffer
;
305 fnTableW
->QuerySecurityPackageInfoW
=
306 QuerySecurityPackageInfoW
;
307 fnTableW
->ExportSecurityContext
=
308 inFnTableA
->ExportSecurityContext
;
309 fnTableW
->QuerySecurityContextToken
=
310 inFnTableA
->QuerySecurityContextToken
;
311 fnTableW
->EncryptMessage
= inFnTableA
->EncryptMessage
;
312 fnTableW
->DecryptMessage
= inFnTableA
->DecryptMessage
;
317 static WCHAR
*strdupAW( const char *str
)
322 int len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
323 if ((ret
= malloc( len
* sizeof(WCHAR
) ))) MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
328 static void _copyPackageInfo(PSecPkgInfoW info
, const SecPkgInfoA
*inInfoA
,
329 const SecPkgInfoW
*inInfoW
)
331 if (info
&& (inInfoA
|| inInfoW
))
333 /* odd, I know, but up until Name and Comment the structures are
336 memcpy(info
, inInfoW
? inInfoW
: (const SecPkgInfoW
*)inInfoA
, sizeof(*info
));
339 info
->Name
= wcsdup(inInfoW
->Name
);
340 info
->Comment
= wcsdup(inInfoW
->Comment
);
344 info
->Name
= strdupAW(inInfoA
->Name
);
345 info
->Comment
= strdupAW(inInfoA
->Comment
);
350 SecureProvider
*SECUR32_addProvider(const SecurityFunctionTableA
*fnTableA
,
351 const SecurityFunctionTableW
*fnTableW
, PCWSTR moduleName
)
355 EnterCriticalSection(&cs
);
359 if (!(providerTable
= malloc(sizeof(*providerTable
))))
361 LeaveCriticalSection(&cs
);
365 list_init(&providerTable
->table
);
368 if (!(ret
= malloc(sizeof(*ret
))))
370 LeaveCriticalSection(&cs
);
374 list_add_tail(&providerTable
->table
, &ret
->entry
);
377 if (fnTableA
|| fnTableW
)
379 ret
->moduleName
= wcsdup(moduleName
);
380 _makeFnTableA(&ret
->fnTableA
, fnTableA
, fnTableW
);
381 _makeFnTableW(&ret
->fnTableW
, fnTableA
, fnTableW
);
382 ret
->loaded
= !moduleName
;
386 ret
->moduleName
= wcsdup(moduleName
);
390 LeaveCriticalSection(&cs
);
394 void SECUR32_addPackages(SecureProvider
*provider
, ULONG toAdd
,
395 const SecPkgInfoA
*infoA
, const SecPkgInfoW
*infoW
)
400 assert(infoA
|| infoW
);
402 EnterCriticalSection(&cs
);
406 if (!(packageTable
= malloc(sizeof(*packageTable
))))
408 LeaveCriticalSection(&cs
);
412 packageTable
->numPackages
= 0;
413 list_init(&packageTable
->table
);
416 for (i
= 0; i
< toAdd
; i
++)
418 SecurePackage
*package
;
420 if (!(package
= malloc(sizeof(*package
)))) continue;
422 list_add_tail(&packageTable
->table
, &package
->entry
);
424 package
->provider
= provider
;
425 _copyPackageInfo(&package
->infoW
, infoA
? &infoA
[i
] : NULL
, infoW
? &infoW
[i
] : NULL
);
427 packageTable
->numPackages
+= toAdd
;
429 LeaveCriticalSection(&cs
);
432 static void _tryLoadProvider(PWSTR moduleName
)
434 HMODULE lib
= LoadLibraryW(moduleName
);
438 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
439 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(lib
,
440 SECURITY_ENTRYPOINT_ANSIW
);
441 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
442 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(lib
,
443 SECURITY_ENTRYPOINT_ANSIA
);
445 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
446 debugstr_w(moduleName
), pInitSecurityInterfaceA
,
447 pInitSecurityInterfaceW
);
448 if (pInitSecurityInterfaceW
|| pInitSecurityInterfaceA
)
450 PSecurityFunctionTableA fnTableA
= NULL
;
451 PSecurityFunctionTableW fnTableW
= NULL
;
453 PSecPkgInfoA infoA
= NULL
;
454 PSecPkgInfoW infoW
= NULL
;
455 SECURITY_STATUS ret
= SEC_E_OK
;
457 if (pInitSecurityInterfaceA
)
458 fnTableA
= pInitSecurityInterfaceA();
459 if (pInitSecurityInterfaceW
)
460 fnTableW
= pInitSecurityInterfaceW();
461 if (fnTableW
&& fnTableW
->EnumerateSecurityPackagesW
)
463 if (fnTableW
!= &securityFunctionTableW
)
464 ret
= fnTableW
->EnumerateSecurityPackagesW(&toAdd
, &infoW
);
466 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
468 else if (fnTableA
&& fnTableA
->EnumerateSecurityPackagesA
)
470 if (fnTableA
!= &securityFunctionTableA
)
471 ret
= fnTableA
->EnumerateSecurityPackagesA(&toAdd
, &infoA
);
473 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName
));
475 if (ret
== SEC_E_OK
&& toAdd
> 0 && (infoW
|| infoA
))
477 SecureProvider
*provider
= SECUR32_addProvider(NULL
, NULL
,
481 SECUR32_addPackages(provider
, toAdd
, infoA
, infoW
);
483 fnTableW
->FreeContextBuffer(infoW
);
485 fnTableA
->FreeContextBuffer(infoA
);
491 WARN("failed to load %s\n", debugstr_w(moduleName
));
494 static void SECUR32_initializeProviders(void)
500 /* First load built-in providers */
501 SECUR32_initSchannelSP();
502 /* Load SSP/AP packages (Kerberos and others) */
503 load_auth_packages();
504 /* Now load providers from registry */
505 apiRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\CurrentControlSet\\Control\\SecurityProviders", 0,
507 if (apiRet
== ERROR_SUCCESS
)
509 WCHAR securityPkgNames
[MAX_PATH
]; /* arbitrary len */
510 DWORD size
= sizeof(securityPkgNames
), type
;
512 apiRet
= RegQueryValueExW(key
, L
"SecurityProviders", NULL
, &type
, (PBYTE
)securityPkgNames
, &size
);
513 if (apiRet
== ERROR_SUCCESS
&& type
== REG_SZ
)
517 size
= size
/ sizeof(WCHAR
);
518 for (ptr
= securityPkgNames
;
519 ptr
< securityPkgNames
+ size
; )
523 for (comma
= ptr
; *comma
&& *comma
!= ','; comma
++)
527 for (; *ptr
&& iswspace(*ptr
) && ptr
< securityPkgNames
+ size
;
531 _tryLoadProvider(ptr
);
532 ptr
+= lstrlenW(ptr
) + 1;
539 SecurePackage
*SECUR32_findPackageW(PCWSTR packageName
)
541 SecurePackage
*ret
= NULL
;
542 BOOL matched
= FALSE
;
544 if (packageTable
&& packageName
)
546 LIST_FOR_EACH_ENTRY(ret
, &packageTable
->table
, SecurePackage
, entry
)
548 matched
= !lstrcmpiW(ret
->infoW
.Name
, packageName
);
551 if (!matched
) return NULL
;
553 if (ret
->provider
&& !ret
->provider
->loaded
)
555 ret
->provider
->lib
= LoadLibraryW(ret
->provider
->moduleName
);
556 if (ret
->provider
->lib
)
558 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
559 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(ret
->provider
->lib
,
560 SECURITY_ENTRYPOINT_ANSIW
);
561 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
562 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(ret
->provider
->lib
,
563 SECURITY_ENTRYPOINT_ANSIA
);
564 PSecurityFunctionTableA fnTableA
= NULL
;
565 PSecurityFunctionTableW fnTableW
= NULL
;
567 if (pInitSecurityInterfaceA
)
568 fnTableA
= pInitSecurityInterfaceA();
569 if (pInitSecurityInterfaceW
)
570 fnTableW
= pInitSecurityInterfaceW();
571 /* don't update built-in SecurityFunctionTable */
572 if (fnTableA
!= &securityFunctionTableA
)
573 _makeFnTableA(&ret
->provider
->fnTableA
, fnTableA
, fnTableW
);
574 if (fnTableW
!= &securityFunctionTableW
)
575 _makeFnTableW(&ret
->provider
->fnTableW
, fnTableA
, fnTableW
);
576 ret
->provider
->loaded
= TRUE
;
585 SecurePackage
*SECUR32_findPackageA(PCSTR packageName
)
589 if (packageTable
&& packageName
)
591 UNICODE_STRING package
;
593 RtlCreateUnicodeStringFromAsciiz(&package
, packageName
);
594 ret
= SECUR32_findPackageW(package
.Buffer
);
595 RtlFreeUnicodeString(&package
);
602 static void SECUR32_freeProviders(void)
605 EnterCriticalSection(&cs
);
607 SECUR32_deinitSchannelSP();
611 SecurePackage
*package
, *package_next
;
612 LIST_FOR_EACH_ENTRY_SAFE(package
, package_next
, &packageTable
->table
,
613 SecurePackage
, entry
)
615 free(package
->infoW
.Name
);
616 free(package
->infoW
.Comment
);
626 SecureProvider
*provider
, *provider_next
;
627 LIST_FOR_EACH_ENTRY_SAFE(provider
, provider_next
, &providerTable
->table
, SecureProvider
, entry
)
629 free(provider
->moduleName
);
630 if (provider
->lib
) FreeLibrary(provider
->lib
);
635 providerTable
= NULL
;
638 LeaveCriticalSection(&cs
);
639 DeleteCriticalSection(&cs
);
642 /***********************************************************************
643 * FreeContextBuffer (SECUR32.@)
645 * Doh--if pv was allocated by a crypto package, this may not be correct.
646 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
647 * be any guarantee, nor is there an alloc function in secur32.
649 SECURITY_STATUS WINAPI
FreeContextBuffer( void *pv
)
651 RtlFreeHeap( GetProcessHeap(), 0, pv
);
655 /***********************************************************************
656 * EnumerateSecurityPackagesW (SECUR32.@)
658 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesW(PULONG pcPackages
,
659 PSecPkgInfoW
*ppPackageInfo
)
661 SECURITY_STATUS ret
= SEC_E_OK
;
663 TRACE("(%p, %p)\n", pcPackages
, ppPackageInfo
);
665 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
667 EnterCriticalSection(&cs
);
670 SecurePackage
*package
;
673 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
674 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
676 if (package
->infoW
.Name
)
677 bytesNeeded
+= (lstrlenW(package
->infoW
.Name
) + 1) * sizeof(WCHAR
);
678 if (package
->infoW
.Comment
)
679 bytesNeeded
+= (lstrlenW(package
->infoW
.Comment
) + 1) * sizeof(WCHAR
);
683 /* freed with FeeContextBuffer */
684 if ((*ppPackageInfo
= RtlAllocateHeap(GetProcessHeap(), 0, bytesNeeded
)))
689 *pcPackages
= packageTable
->numPackages
;
690 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
691 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
692 LIST_FOR_EACH_ENTRY(package
, &packageTable
->table
, SecurePackage
, entry
)
694 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
++;
696 *pkgInfo
= package
->infoW
;
697 if (package
->infoW
.Name
)
699 TRACE("Name[%ld] = %s\n", i
- 1, debugstr_w(package
->infoW
.Name
));
700 pkgInfo
->Name
= nextString
;
701 lstrcpyW(nextString
, package
->infoW
.Name
);
702 nextString
+= lstrlenW(nextString
) + 1;
705 pkgInfo
->Name
= NULL
;
706 if (package
->infoW
.Comment
)
708 TRACE("Comment[%ld] = %s\n", i
- 1, debugstr_w(package
->infoW
.Comment
));
709 pkgInfo
->Comment
= nextString
;
710 lstrcpyW(nextString
, package
->infoW
.Comment
);
711 nextString
+= lstrlenW(nextString
) + 1;
714 pkgInfo
->Comment
= NULL
;
718 ret
= SEC_E_INSUFFICIENT_MEMORY
;
721 LeaveCriticalSection(&cs
);
722 TRACE("<-- 0x%08lx\n", ret
);
726 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
727 * structures) into an array of SecPkgInfoA structures, which it returns.
729 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
730 const SecPkgInfoW
*info
)
736 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
739 for (i
= 0; i
< cPackages
; i
++)
742 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
743 -1, NULL
, 0, NULL
, NULL
);
745 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
746 -1, NULL
, 0, NULL
, NULL
);
748 /* freed with FreeContextBuffer */
749 if ((ret
= RtlAllocateHeap(GetProcessHeap(), 0, bytesNeeded
)))
753 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
754 for (i
= 0; i
< cPackages
; i
++)
756 PSecPkgInfoA pkgInfo
= ret
+ i
;
759 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
762 pkgInfo
->Name
= nextString
;
763 /* just repeat back to WideCharToMultiByte how many bytes
764 * it requires, since we asked it earlier
766 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
767 NULL
, 0, NULL
, NULL
);
768 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
769 pkgInfo
->Name
, bytes
, NULL
, NULL
);
770 nextString
+= lstrlenA(nextString
) + 1;
773 pkgInfo
->Name
= NULL
;
776 pkgInfo
->Comment
= nextString
;
777 /* just repeat back to WideCharToMultiByte how many bytes
778 * it requires, since we asked it earlier
780 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
781 NULL
, 0, NULL
, NULL
);
782 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
783 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
784 nextString
+= lstrlenA(nextString
) + 1;
787 pkgInfo
->Comment
= NULL
;
796 /***********************************************************************
797 * EnumerateSecurityPackagesA (SECUR32.@)
799 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesA(PULONG pcPackages
,
800 PSecPkgInfoA
*ppPackageInfo
)
805 ret
= EnumerateSecurityPackagesW(pcPackages
, &info
);
806 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
808 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
809 if (*pcPackages
&& !*ppPackageInfo
)
812 ret
= SEC_E_INSUFFICIENT_MEMORY
;
814 FreeContextBuffer(info
);
820 static const char *debugstr_NameFormat( EXTENDED_NAME_FORMAT format
)
822 static const char * const names
[] =
825 "NameFullyQualifiedDN",
834 "NameServicePrincipal",
841 if (format
< ARRAY_SIZE(names
) && names
[format
]) return names
[format
];
842 return wine_dbg_sprintf( "%u", format
);
846 /***********************************************************************
847 * GetComputerObjectNameA (SECUR32.@)
849 * Get the local computer's name using the format specified.
852 * NameFormat [I] The format for the name.
853 * lpNameBuffer [O] Pointer to buffer to receive the name.
854 * nSize [I/O] Size in characters of buffer.
857 * TRUE If the name was written to lpNameBuffer.
858 * FALSE If the name couldn't be written.
861 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
862 * name will be returned in *nSize.
864 * nSize returns the number of characters written when lpNameBuffer is not
865 * NULL or the size of the buffer needed to hold the name when the buffer
866 * is too short or lpNameBuffer is NULL.
868 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
870 BOOLEAN WINAPI
GetComputerObjectNameA(
871 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
874 LPWSTR bufferW
= NULL
;
875 ULONG sizeW
= *nSize
;
877 TRACE("(%s %p %p)\n", debugstr_NameFormat(NameFormat
), lpNameBuffer
, nSize
);
880 if (!(bufferW
= malloc(sizeW
* sizeof(WCHAR
)))) {
881 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
885 rc
= GetComputerObjectNameW(NameFormat
, bufferW
, &sizeW
);
887 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
888 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
897 /***********************************************************************
898 * GetComputerObjectNameW (SECUR32.@)
900 BOOLEAN WINAPI
GetComputerObjectNameW(
901 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
903 LSA_HANDLE policyHandle
;
904 LSA_OBJECT_ATTRIBUTES objectAttributes
;
905 PPOLICY_DNS_DOMAIN_INFO domainInfo
;
909 TRACE("(%s %p %p)\n", debugstr_NameFormat(NameFormat
), lpNameBuffer
, nSize
);
911 if (NameFormat
== NameUnknown
)
913 SetLastError(ERROR_INVALID_PARAMETER
);
917 ZeroMemory(&objectAttributes
, sizeof(objectAttributes
));
918 objectAttributes
.Length
= sizeof(objectAttributes
);
920 ntStatus
= LsaOpenPolicy(NULL
, &objectAttributes
,
921 POLICY_VIEW_LOCAL_INFORMATION
,
923 if (ntStatus
!= STATUS_SUCCESS
)
925 SetLastError(LsaNtStatusToWinError(ntStatus
));
926 WARN("LsaOpenPolicy failed with NT status %lu\n", GetLastError());
930 ntStatus
= LsaQueryInformationPolicy(policyHandle
,
931 PolicyDnsDomainInformation
,
932 (PVOID
*)&domainInfo
);
933 if (ntStatus
!= STATUS_SUCCESS
)
935 SetLastError(LsaNtStatusToWinError(ntStatus
));
936 WARN("LsaQueryInformationPolicy failed with NT status %lu\n",
938 LsaClose(policyHandle
);
946 case NameSamCompatible
:
948 WCHAR name
[MAX_COMPUTERNAME_LENGTH
+ 1];
949 DWORD size
= ARRAY_SIZE(name
);
950 if (GetComputerNameW(name
, &size
))
952 DWORD len
= domainInfo
->Name
.Length
+ size
+ 3;
953 if (lpNameBuffer
&& *nSize
>= len
)
955 if (domainInfo
->Name
.Buffer
)
957 lstrcpyW(lpNameBuffer
, domainInfo
->Name
.Buffer
);
958 lstrcatW(lpNameBuffer
, L
"\\");
962 lstrcatW(lpNameBuffer
, name
);
963 lstrcatW(lpNameBuffer
, L
"$");
966 else /* just requesting length required */
969 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
975 SetLastError(ERROR_INTERNAL_ERROR
);
980 case NameFullyQualifiedDN
:
982 WCHAR name
[MAX_COMPUTERNAME_LENGTH
+ 1];
986 size
= ARRAY_SIZE(name
);
987 if (!GetComputerNameW(name
, &size
))
993 len
= wcslen(L
"CN=") + size
+ 1 + wcslen(L
"CN=Computers") + 1 + wcslen(L
"DC=");
994 if (domainInfo
->DnsDomainName
.Buffer
)
996 suffix
= wcsrchr(domainInfo
->DnsDomainName
.Buffer
, '.');
1000 len
+= 1 + wcslen(L
"DC=") + wcslen(suffix
);
1002 len
+= wcslen(domainInfo
->DnsDomainName
.Buffer
);
1007 if (lpNameBuffer
&& *nSize
> len
)
1009 lstrcpyW(lpNameBuffer
, L
"CN=");
1010 lstrcatW(lpNameBuffer
, name
);
1011 lstrcatW(lpNameBuffer
, L
",");
1012 lstrcatW(lpNameBuffer
, L
"CN=Computers");
1013 if (domainInfo
->DnsDomainName
.Buffer
)
1015 lstrcatW(lpNameBuffer
, L
",");
1016 lstrcatW(lpNameBuffer
, L
"DC=");
1017 lstrcatW(lpNameBuffer
, domainInfo
->DnsDomainName
.Buffer
);
1020 lstrcatW(lpNameBuffer
, L
",");
1021 lstrcatW(lpNameBuffer
, L
"DC=");
1022 lstrcatW(lpNameBuffer
, suffix
);
1027 else /* just requesting length required */
1029 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1038 case NameUserPrincipal
:
1039 case NameCanonicalEx
:
1040 case NameServicePrincipal
:
1042 FIXME("NameFormat %d not implemented\n", NameFormat
);
1043 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
1047 SetLastError(ERROR_INVALID_PARAMETER
);
1053 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO
);
1057 LsaFreeMemory(domainInfo
);
1058 LsaClose(policyHandle
);
1063 SECURITY_STATUS WINAPI
AddSecurityPackageA(LPSTR name
, SECURITY_PACKAGE_OPTIONS
*options
)
1065 FIXME("(%s %p)\n", debugstr_a(name
), options
);
1069 SECURITY_STATUS WINAPI
AddSecurityPackageW(LPWSTR name
, SECURITY_PACKAGE_OPTIONS
*options
)
1071 FIXME("(%s %p)\n", debugstr_w(name
), options
);
1075 SECURITY_STATUS WINAPI
DeleteSecurityPackageA(LPSTR name
)
1077 FIXME("(%s)\n", debugstr_a(name
));
1081 SECURITY_STATUS WINAPI
DeleteSecurityPackageW(LPWSTR name
)
1083 FIXME("(%s)\n", debugstr_w(name
));
1087 /***********************************************************************
1088 * GetUserNameExA (SECUR32.@)
1090 BOOLEAN WINAPI
GetUserNameExA(
1091 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
1094 LPWSTR bufferW
= NULL
;
1095 ULONG sizeW
= *nSize
;
1096 TRACE("(%s %p %p)\n", debugstr_NameFormat(NameFormat
), lpNameBuffer
, nSize
);
1098 bufferW
= malloc(sizeW
* sizeof(WCHAR
));
1099 if (bufferW
== NULL
) {
1100 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1104 rc
= GetUserNameExW(NameFormat
, bufferW
, &sizeW
);
1106 ULONG len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
1109 WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, lpNameBuffer
, *nSize
, NULL
, NULL
);
1116 SetLastError(ERROR_MORE_DATA
);
1125 BOOLEAN WINAPI
GetUserNameExW(
1126 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
1128 TRACE("(%s %p %p)\n", debugstr_NameFormat(NameFormat
), lpNameBuffer
, nSize
);
1132 case NameSamCompatible
:
1134 WCHAR samname
[UNLEN
+ 1 + MAX_COMPUTERNAME_LENGTH
+ 1];
1138 /* This assumes the current user is always a local account */
1139 len
= MAX_COMPUTERNAME_LENGTH
+ 1;
1140 if (GetComputerNameW(samname
, &len
))
1142 out
= samname
+ lstrlenW(samname
);
1145 if (GetUserNameW(out
, &len
))
1147 if (lstrlenW(samname
) < *nSize
)
1149 lstrcpyW(lpNameBuffer
, samname
);
1150 *nSize
= lstrlenW(samname
);
1154 SetLastError(ERROR_MORE_DATA
);
1155 *nSize
= lstrlenW(samname
) + 1;
1162 case NameFullyQualifiedDN
:
1166 case NameUserPrincipal
:
1167 case NameCanonicalEx
:
1168 case NameServicePrincipal
:
1170 FIXME("NameFormat %d not implemented\n", NameFormat
);
1171 SetLastError(ERROR_NONE_MAPPED
);
1175 SetLastError(ERROR_INVALID_PARAMETER
);
1180 BOOLEAN WINAPI
TranslateNameA(
1181 LPCSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1182 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPSTR lpTranslatedName
,
1185 FIXME("%p %s %s %p %p\n", lpAccountName
, debugstr_NameFormat(AccountNameFormat
),
1186 debugstr_NameFormat(DesiredNameFormat
), lpTranslatedName
, nSize
);
1190 BOOLEAN WINAPI
TranslateNameW(
1191 LPCWSTR lpAccountName
, EXTENDED_NAME_FORMAT AccountNameFormat
,
1192 EXTENDED_NAME_FORMAT DesiredNameFormat
, LPWSTR lpTranslatedName
,
1195 FIXME("%p %s %s %p %p\n", lpAccountName
, debugstr_NameFormat(AccountNameFormat
),
1196 debugstr_NameFormat(DesiredNameFormat
), lpTranslatedName
, nSize
);
1200 /***********************************************************************
1201 * DllMain (SECUR32.0)
1203 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD reason
, LPVOID reserved
)
1207 case DLL_PROCESS_ATTACH
:
1208 DisableThreadLibraryCalls(hinstDLL
);
1209 SECUR32_initializeProviders();
1211 case DLL_PROCESS_DETACH
:
1212 if (reserved
) break;
1213 SECUR32_freeProviders();