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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "secur32_priv.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(secur32
);
40 typedef struct _SecurePackageTable
44 SecurePackage table
[1];
47 typedef struct _SecureProviderTable
51 SecureProvider table
[1];
52 } SecureProviderTable
;
58 /* Makes sure table has space for at least howBig entries. If table is NULL,
59 * returns a newly allocated table. Otherwise returns the address of the
60 * modified table, which may not be the same was when called.
62 static SecurePackageTable
*_resizePackageTable(SecurePackageTable
*table
,
65 /* Makes sure table has space for at least howBig entries. If table is NULL,
66 * returns a newly allocated table. Otherwise returns the address of the
67 * modified table, which may not be the same was when called.
69 static SecureProviderTable
*_resizeProviderTable(SecureProviderTable
*table
,
72 /* Tries to load moduleName as a provider. If successful, enumerates what
73 * packages it can and adds them to the package and provider tables. Resizes
74 * tables as necessary.
76 static void _tryLoadProvider(PWSTR moduleName
);
78 /* Initialization: read securityproviders value and attempt to open each dll
79 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
80 * Two undocumented functions, AddSecurityPackage(A/W) and
81 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
82 * unregister a dll, but I'm not sure.
84 static void SECUR32_initializeProviders(void);
86 /* Frees all loaded packages and providers */
87 static void SECUR32_freeProviders(void);
93 static CRITICAL_SECTION cs
;
94 static SecurePackageTable
*packageTable
= NULL
;
95 static SecureProviderTable
*providerTable
= NULL
;
97 static SecurityFunctionTableA securityFunctionTableA
= {
98 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2
,
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 NULL
, /* Reserved3 */
117 NULL
, /* Reserved4 */
118 ExportSecurityContext
,
119 ImportSecurityContextA
,
121 NULL
, /* Reserved8 */
122 QuerySecurityContextToken
,
125 SetContextAttributesA
128 static SecurityFunctionTableW securityFunctionTableW
= {
129 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2
,
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 NULL
, /* Reserved3 */
148 NULL
, /* 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 /* Allocates or resizes table to have space for at least howBig packages.
176 * Uses Heap functions, because needs to be able to reallocate.
178 static SecurePackageTable
*_resizePackageTable(SecurePackageTable
*table
,
181 SecurePackageTable
*ret
;
183 EnterCriticalSection(&cs
);
186 if (table
->numAllocated
< howBig
)
188 ret
= HeapReAlloc(GetProcessHeap(), 0, table
,
189 sizeof(SecurePackageTable
) + (howBig
- 1) * sizeof(SecurePackage
));
192 ret
->numAllocated
= howBig
;
201 DWORD numAllocated
= (howBig
> 1 ? howBig
: 1);
203 ret
= HeapAlloc(GetProcessHeap(), 0,
204 sizeof(SecurePackageTable
) +
205 (numAllocated
- 1) * sizeof(SecurePackage
));
208 ret
->numAllocated
= numAllocated
;
209 ret
->numPackages
= 0;
212 LeaveCriticalSection(&cs
);
216 /* Allocates or resizes table to have space for at least howBig providers.
217 * Uses Heap functions, because needs to be able to reallocate.
219 static SecureProviderTable
*_resizeProviderTable(SecureProviderTable
*table
,
222 SecureProviderTable
*ret
;
224 EnterCriticalSection(&cs
);
227 if (table
->numAllocated
< howBig
)
229 ret
= HeapReAlloc(GetProcessHeap(), 0, table
,
230 sizeof(SecureProviderTable
) +
231 (howBig
- 1) * sizeof(SecureProvider
));
234 ret
->numAllocated
= howBig
;
243 DWORD numAllocated
= (howBig
> 1 ? howBig
: 1);
245 ret
= HeapAlloc(GetProcessHeap(), 0,
246 sizeof(SecureProviderTable
) +
247 (numAllocated
- 1) * sizeof(SecureProvider
));
250 ret
->numAllocated
= numAllocated
;
251 ret
->numProviders
= 0;
254 LeaveCriticalSection(&cs
);
258 PWSTR
SECUR32_strdupW(PCWSTR str
)
264 ret
= (PWSTR
)SECUR32_ALLOC((lstrlenW(str
) + 1) * sizeof(WCHAR
));
273 PWSTR
SECUR32_AllocWideFromMultiByte(PCSTR str
)
279 int charsNeeded
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
283 ret
= (PWSTR
)SECUR32_ALLOC(charsNeeded
* sizeof(WCHAR
));
285 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, charsNeeded
);
295 PSTR
SECUR32_AllocMultiByteFromWide(PCWSTR str
)
301 int charsNeeded
= WideCharToMultiByte(CP_ACP
, 0, str
, -1, NULL
, 0,
306 ret
= (PSTR
)SECUR32_ALLOC(charsNeeded
);
308 WideCharToMultiByte(CP_ACP
, 0, str
, -1, ret
, charsNeeded
,
319 static void _makeFnTableA(PSecurityFunctionTableA fnTableA
,
320 const PSecurityFunctionTableA inFnTableA
,
321 const PSecurityFunctionTableW inFnTableW
)
327 /* The size of the version 1 table is based on platform sdk's
328 * sspi.h, though the sample ssp also provided with platform sdk
329 * implies only functions through QuerySecurityPackageInfoA are
330 * implemented (yikes)
332 size_t tableSize
= inFnTableA
->dwVersion
== 1 ?
333 (LPBYTE
)&inFnTableA
->SetContextAttributesA
-
334 (LPBYTE
)inFnTableA
: sizeof(SecurityFunctionTableA
);
336 memcpy(fnTableA
, inFnTableA
, tableSize
);
337 /* override this, since we can do it internally anyway */
338 fnTableA
->QuerySecurityPackageInfoA
=
339 QuerySecurityPackageInfoA
;
343 /* functions with thunks */
344 if (inFnTableW
->AcquireCredentialsHandleW
)
345 fnTableA
->AcquireCredentialsHandleA
=
346 thunk_AcquireCredentialsHandleA
;
347 if (inFnTableW
->InitializeSecurityContextW
)
348 fnTableA
->InitializeSecurityContextA
=
349 thunk_InitializeSecurityContextA
;
350 if (inFnTableW
->ImportSecurityContextW
)
351 fnTableA
->ImportSecurityContextA
=
352 thunk_ImportSecurityContextA
;
353 if (inFnTableW
->AddCredentialsW
)
354 fnTableA
->AddCredentialsA
=
355 thunk_AddCredentialsA
;
356 if (inFnTableW
->QueryCredentialsAttributesW
)
357 fnTableA
->QueryCredentialsAttributesA
=
358 thunk_QueryCredentialsAttributesA
;
359 if (inFnTableW
->QueryContextAttributesW
)
360 fnTableA
->QueryContextAttributesA
=
361 thunk_QueryContextAttributesA
;
362 if (inFnTableW
->SetContextAttributesW
)
363 fnTableA
->SetContextAttributesA
=
364 thunk_SetContextAttributesA
;
365 /* this can't be thunked, there's no extra param to know which
366 * package to forward to */
367 fnTableA
->EnumerateSecurityPackagesA
= NULL
;
368 /* functions with no thunks needed */
369 fnTableA
->AcceptSecurityContext
= inFnTableW
->AcceptSecurityContext
;
370 fnTableA
->CompleteAuthToken
= inFnTableW
->CompleteAuthToken
;
371 fnTableA
->DeleteSecurityContext
= inFnTableW
->DeleteSecurityContext
;
372 fnTableA
->ImpersonateSecurityContext
=
373 inFnTableW
->ImpersonateSecurityContext
;
374 fnTableA
->RevertSecurityContext
= inFnTableW
->RevertSecurityContext
;
375 fnTableA
->MakeSignature
= inFnTableW
->MakeSignature
;
376 fnTableA
->VerifySignature
= inFnTableW
->VerifySignature
;
377 fnTableA
->FreeContextBuffer
= inFnTableW
->FreeContextBuffer
;
378 fnTableA
->QuerySecurityPackageInfoA
=
379 QuerySecurityPackageInfoA
;
380 fnTableA
->ExportSecurityContext
=
381 inFnTableW
->ExportSecurityContext
;
382 fnTableA
->QuerySecurityContextToken
=
383 inFnTableW
->QuerySecurityContextToken
;
384 fnTableA
->EncryptMessage
= inFnTableW
->EncryptMessage
;
385 fnTableA
->DecryptMessage
= inFnTableW
->DecryptMessage
;
390 static void _makeFnTableW(PSecurityFunctionTableW fnTableW
,
391 const PSecurityFunctionTableA inFnTableA
,
392 const PSecurityFunctionTableW inFnTableW
)
398 /* The size of the version 1 table is based on platform sdk's
399 * sspi.h, though the sample ssp also provided with platform sdk
400 * implies only functions through QuerySecurityPackageInfoA are
401 * implemented (yikes)
403 size_t tableSize
= inFnTableW
->dwVersion
== 1 ?
404 (LPBYTE
)&inFnTableW
->SetContextAttributesW
-
405 (LPBYTE
)inFnTableW
: sizeof(SecurityFunctionTableW
);
407 memcpy(fnTableW
, inFnTableW
, tableSize
);
408 /* override this, since we can do it internally anyway */
409 fnTableW
->QuerySecurityPackageInfoW
=
410 QuerySecurityPackageInfoW
;
414 /* functions with thunks */
415 if (inFnTableA
->AcquireCredentialsHandleA
)
416 fnTableW
->AcquireCredentialsHandleW
=
417 thunk_AcquireCredentialsHandleW
;
418 if (inFnTableA
->InitializeSecurityContextA
)
419 fnTableW
->InitializeSecurityContextW
=
420 thunk_InitializeSecurityContextW
;
421 if (inFnTableA
->ImportSecurityContextA
)
422 fnTableW
->ImportSecurityContextW
=
423 thunk_ImportSecurityContextW
;
424 if (inFnTableA
->AddCredentialsA
)
425 fnTableW
->AddCredentialsW
=
426 thunk_AddCredentialsW
;
427 if (inFnTableA
->QueryCredentialsAttributesA
)
428 fnTableW
->QueryCredentialsAttributesW
=
429 thunk_QueryCredentialsAttributesW
;
430 if (inFnTableA
->QueryContextAttributesA
)
431 fnTableW
->QueryContextAttributesW
=
432 thunk_QueryContextAttributesW
;
433 if (inFnTableA
->SetContextAttributesA
)
434 fnTableW
->SetContextAttributesW
=
435 thunk_SetContextAttributesW
;
436 /* this can't be thunked, there's no extra param to know which
437 * package to forward to */
438 fnTableW
->EnumerateSecurityPackagesW
= NULL
;
439 /* functions with no thunks needed */
440 fnTableW
->AcceptSecurityContext
= inFnTableA
->AcceptSecurityContext
;
441 fnTableW
->CompleteAuthToken
= inFnTableA
->CompleteAuthToken
;
442 fnTableW
->DeleteSecurityContext
= inFnTableA
->DeleteSecurityContext
;
443 fnTableW
->ImpersonateSecurityContext
=
444 inFnTableA
->ImpersonateSecurityContext
;
445 fnTableW
->RevertSecurityContext
= inFnTableA
->RevertSecurityContext
;
446 fnTableW
->MakeSignature
= inFnTableA
->MakeSignature
;
447 fnTableW
->VerifySignature
= inFnTableA
->VerifySignature
;
448 fnTableW
->FreeContextBuffer
= inFnTableA
->FreeContextBuffer
;
449 fnTableW
->QuerySecurityPackageInfoW
=
450 QuerySecurityPackageInfoW
;
451 fnTableW
->ExportSecurityContext
=
452 inFnTableA
->ExportSecurityContext
;
453 fnTableW
->QuerySecurityContextToken
=
454 inFnTableA
->QuerySecurityContextToken
;
455 fnTableW
->EncryptMessage
= inFnTableA
->EncryptMessage
;
456 fnTableW
->DecryptMessage
= inFnTableA
->DecryptMessage
;
461 static void _copyPackageInfo(PSecPkgInfoW info
, const SecPkgInfoA
*inInfoA
,
462 const SecPkgInfoW
*inInfoW
)
464 if (info
&& (inInfoA
|| inInfoW
))
466 /* odd, I know, but up until Name and Comment the structures are
469 memcpy(info
, inInfoW
? inInfoW
: (PSecPkgInfoW
)inInfoA
, sizeof(*info
));
472 info
->Name
= SECUR32_strdupW(inInfoW
->Name
);
473 info
->Comment
= SECUR32_strdupW(inInfoW
->Comment
);
477 info
->Name
= SECUR32_AllocWideFromMultiByte(inInfoA
->Name
);
478 info
->Comment
= SECUR32_AllocWideFromMultiByte(inInfoA
->Comment
);
483 SecureProvider
*SECUR32_addProvider(PSecurityFunctionTableA fnTableA
,
484 PSecurityFunctionTableW fnTableW
, PWSTR moduleName
)
488 EnterCriticalSection(&cs
);
489 providerTable
= _resizeProviderTable(providerTable
,
490 providerTable
? providerTable
->numProviders
+ 1 : 1);
493 ret
= &providerTable
->table
[providerTable
->numProviders
++];
495 if (fnTableA
|| fnTableW
)
497 _makeFnTableA(&ret
->fnTableA
, fnTableA
, fnTableW
);
498 _makeFnTableW(&ret
->fnTableW
, fnTableA
, fnTableW
);
503 ret
->moduleName
= SECUR32_strdupW(moduleName
);
509 LeaveCriticalSection(&cs
);
513 void SECUR32_addPackages(SecureProvider
*provider
, ULONG toAdd
,
514 const SecPkgInfoA
*infoA
, const SecPkgInfoW
*infoW
)
517 assert(infoA
|| infoW
);
519 EnterCriticalSection(&cs
);
520 packageTable
= _resizePackageTable(packageTable
,
521 packageTable
? packageTable
->numPackages
+ toAdd
: toAdd
);
526 for (i
= 0; i
< toAdd
; i
++)
528 SecurePackage
*package
=
529 &packageTable
->table
[packageTable
->numPackages
+ i
];
531 package
->provider
= provider
;
532 _copyPackageInfo(&package
->infoW
,
533 infoA
? &infoA
[i
] : NULL
,
534 infoW
? &infoW
[i
] : NULL
);
536 packageTable
->numPackages
+= toAdd
;
538 LeaveCriticalSection(&cs
);
541 static void _tryLoadProvider(PWSTR moduleName
)
543 HMODULE lib
= LoadLibraryW(moduleName
);
547 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
548 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(lib
,
549 SECURITY_ENTRYPOINT_ANSIW
);
550 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
551 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(lib
,
552 SECURITY_ENTRYPOINT_ANSIA
);
554 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
555 debugstr_w(moduleName
), pInitSecurityInterfaceA
,
556 pInitSecurityInterfaceW
);
557 if (pInitSecurityInterfaceW
|| pInitSecurityInterfaceA
)
559 PSecurityFunctionTableA fnTableA
= NULL
;
560 PSecurityFunctionTableW fnTableW
= NULL
;
562 PSecPkgInfoA infoA
= NULL
;
563 PSecPkgInfoW infoW
= NULL
;
564 SECURITY_STATUS ret
= SEC_E_OK
;
566 if (pInitSecurityInterfaceA
)
567 fnTableA
= pInitSecurityInterfaceA();
568 if (pInitSecurityInterfaceW
)
569 fnTableW
= pInitSecurityInterfaceW();
570 if (fnTableW
&& fnTableW
->EnumerateSecurityPackagesW
)
571 ret
= fnTableW
->EnumerateSecurityPackagesW(&toAdd
, &infoW
);
572 else if (fnTableA
&& fnTableA
->EnumerateSecurityPackagesA
)
573 ret
= fnTableA
->EnumerateSecurityPackagesA(&toAdd
, &infoA
);
574 if (ret
== SEC_E_OK
&& toAdd
> 0 && (infoW
|| infoA
))
576 SecureProvider
*provider
= SECUR32_addProvider(NULL
, NULL
,
580 SECUR32_addPackages(provider
, toAdd
, infoA
, infoW
);
582 fnTableW
->FreeContextBuffer(infoW
);
584 fnTableA
->FreeContextBuffer(infoA
);
590 WARN("failed to load %s\n", debugstr_w(moduleName
));
593 static const WCHAR securityProvidersKeyW
[] = {
594 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
595 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
596 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
598 static const WCHAR securityProvidersW
[] = {
599 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
602 static void SECUR32_initializeProviders(void)
608 InitializeCriticalSection(&cs
);
609 /* First load built-in providers */
610 SECUR32_initSchannelSP();
611 /* Now load providers from registry */
612 apiRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, securityProvidersKeyW
, 0,
614 if (apiRet
== ERROR_SUCCESS
)
616 WCHAR securityPkgNames
[MAX_PATH
]; /* arbitrary len */
617 DWORD size
= sizeof(securityPkgNames
) / sizeof(WCHAR
), type
;
619 apiRet
= RegQueryValueExW(key
, securityProvidersW
, NULL
, &type
,
620 (PBYTE
)securityPkgNames
, &size
);
621 if (apiRet
== ERROR_SUCCESS
&& type
== REG_SZ
)
625 for (ptr
= securityPkgNames
;
626 ptr
< (PWSTR
)((PBYTE
)securityPkgNames
+ size
); )
630 for (comma
= ptr
; *comma
&& *comma
!= ','; comma
++)
634 for (; *ptr
&& isspace(*ptr
) && ptr
< securityPkgNames
+ size
;
638 _tryLoadProvider(ptr
);
639 ptr
+= lstrlenW(ptr
) + 1;
646 SecurePackage
*SECUR32_findPackageW(PWSTR packageName
)
648 SecurePackage
*ret
= NULL
;
650 if (packageTable
&& packageName
)
654 for (i
= 0, ret
= NULL
; !ret
&& i
< packageTable
->numPackages
; i
++)
655 if (!lstrcmpiW(packageTable
->table
[i
].infoW
.Name
, packageName
))
656 ret
= &packageTable
->table
[i
];
657 if (ret
&& ret
->provider
&& !ret
->provider
->loaded
)
659 ret
->provider
->lib
= LoadLibraryW(ret
->provider
->moduleName
);
660 if (ret
->provider
->lib
)
662 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW
=
663 (INIT_SECURITY_INTERFACE_W
)GetProcAddress(ret
->provider
->lib
,
664 SECURITY_ENTRYPOINT_ANSIW
);
665 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA
=
666 (INIT_SECURITY_INTERFACE_A
)GetProcAddress(ret
->provider
->lib
,
667 SECURITY_ENTRYPOINT_ANSIA
);
668 PSecurityFunctionTableA fnTableA
= NULL
;
669 PSecurityFunctionTableW fnTableW
= NULL
;
671 if (pInitSecurityInterfaceA
)
672 fnTableA
= pInitSecurityInterfaceA();
673 if (pInitSecurityInterfaceW
)
674 fnTableW
= pInitSecurityInterfaceW();
675 _makeFnTableA(&ret
->provider
->fnTableA
, fnTableA
, fnTableW
);
676 _makeFnTableW(&ret
->provider
->fnTableW
, fnTableA
, fnTableW
);
677 ret
->provider
->loaded
= TRUE
;
686 SecurePackage
*SECUR32_findPackageA(PSTR packageName
)
690 if (packageTable
&& packageName
)
692 UNICODE_STRING package
;
694 RtlCreateUnicodeStringFromAsciiz(&package
, packageName
);
695 ret
= SECUR32_findPackageW(package
.Buffer
);
696 RtlFreeUnicodeString(&package
);
703 static void SECUR32_freeProviders(void)
708 EnterCriticalSection(&cs
);
711 for (i
= 0; i
< packageTable
->numPackages
; i
++)
713 SECUR32_FREE(packageTable
->table
[i
].infoW
.Name
);
714 SECUR32_FREE(packageTable
->table
[i
].infoW
.Comment
);
716 HeapFree(GetProcessHeap(), 0, packageTable
);
721 for (i
= 0; i
< providerTable
->numProviders
; i
++)
723 if (providerTable
->table
[i
].moduleName
)
724 SECUR32_FREE(providerTable
->table
[i
].moduleName
);
725 if (providerTable
->table
[i
].lib
)
726 FreeLibrary(providerTable
->table
[i
].lib
);
728 HeapFree(GetProcessHeap(), 0, providerTable
);
729 providerTable
= NULL
;
731 LeaveCriticalSection(&cs
);
732 DeleteCriticalSection(&cs
);
735 /***********************************************************************
736 * FreeContextBuffer (SECUR32.@)
738 * Doh--if pv was allocated by a crypto package, this may not be correct.
739 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
740 * be any guarantee, nor is there an alloc function in secur32.
742 SECURITY_STATUS WINAPI
FreeContextBuffer(PVOID pv
)
746 /* as it turns out, SECURITY_STATUSes are actually HRESULTS */
749 if (SECUR32_FREE(pv
) == NULL
)
752 ret
= HRESULT_FROM_WIN32(GetLastError());
755 ret
= HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
);
759 /***********************************************************************
760 * EnumerateSecurityPackagesW (SECUR32.@)
762 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesW(PULONG pcPackages
,
763 PSecPkgInfoW
*ppPackageInfo
)
765 SECURITY_STATUS ret
= SEC_E_OK
;
767 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
769 EnterCriticalSection(&cs
);
775 bytesNeeded
= packageTable
->numPackages
* sizeof(SecPkgInfoW
);
776 for (i
= 0; i
< packageTable
->numPackages
; i
++)
778 if (packageTable
->table
[i
].infoW
.Name
)
780 (lstrlenW(packageTable
->table
[i
].infoW
.Name
) + 1) *
782 if (packageTable
->table
[i
].infoW
.Comment
)
784 (lstrlenW(packageTable
->table
[i
].infoW
.Comment
) + 1) *
789 *ppPackageInfo
= (PSecPkgInfoW
)SECUR32_ALLOC(bytesNeeded
);
794 *pcPackages
= packageTable
->numPackages
;
795 nextString
= (PWSTR
)((PBYTE
)*ppPackageInfo
+
796 packageTable
->numPackages
* sizeof(SecPkgInfoW
));
797 for (i
= 0; i
< packageTable
->numPackages
; i
++)
799 PSecPkgInfoW pkgInfo
= *ppPackageInfo
+ i
;
801 memcpy(pkgInfo
, &packageTable
->table
[i
].infoW
,
802 sizeof(SecPkgInfoW
));
803 if (packageTable
->table
[i
].infoW
.Name
)
805 pkgInfo
->Name
= nextString
;
806 lstrcpyW(nextString
, packageTable
->table
[i
].infoW
.Name
);
807 nextString
+= lstrlenW(nextString
) + 1;
810 pkgInfo
->Name
= NULL
;
811 if (packageTable
->table
[i
].infoW
.Comment
)
813 pkgInfo
->Comment
= nextString
;
815 packageTable
->table
[i
].infoW
.Comment
);
816 nextString
+= lstrlenW(nextString
) + 1;
819 pkgInfo
->Comment
= NULL
;
823 ret
= SEC_E_INSUFFICIENT_MEMORY
;
826 LeaveCriticalSection(&cs
);
830 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
831 * structures) into an array of SecPkgInfoA structures, which it returns.
833 static PSecPkgInfoA
thunk_PSecPkgInfoWToA(ULONG cPackages
,
834 const PSecPkgInfoW info
)
840 size_t bytesNeeded
= cPackages
* sizeof(SecPkgInfoA
);
843 for (i
= 0; i
< cPackages
; i
++)
846 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
,
847 -1, NULL
, 0, NULL
, NULL
);
849 bytesNeeded
+= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
,
850 -1, NULL
, 0, NULL
, NULL
);
852 ret
= (PSecPkgInfoA
)SECUR32_ALLOC(bytesNeeded
);
857 nextString
= (PSTR
)((PBYTE
)ret
+ cPackages
* sizeof(SecPkgInfoA
));
858 for (i
= 0; i
< cPackages
; i
++)
860 PSecPkgInfoA pkgInfo
= ret
+ i
;
863 memcpy(pkgInfo
, &info
[i
], sizeof(SecPkgInfoA
));
866 pkgInfo
->Name
= nextString
;
867 /* just repeat back to WideCharToMultiByte how many bytes
868 * it requires, since we asked it earlier
870 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
871 NULL
, 0, NULL
, NULL
);
872 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Name
, -1,
873 pkgInfo
->Name
, bytes
, NULL
, NULL
);
874 nextString
+= lstrlenA(nextString
) + 1;
877 pkgInfo
->Name
= NULL
;
880 pkgInfo
->Comment
= nextString
;
881 /* just repeat back to WideCharToMultiByte how many bytes
882 * it requires, since we asked it earlier
884 bytes
= WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
885 NULL
, 0, NULL
, NULL
);
886 WideCharToMultiByte(CP_ACP
, 0, info
[i
].Comment
, -1,
887 pkgInfo
->Comment
, bytes
, NULL
, NULL
);
888 nextString
+= lstrlenA(nextString
) + 1;
891 pkgInfo
->Comment
= NULL
;
900 /***********************************************************************
901 * EnumerateSecurityPackagesA (SECUR32.@)
903 SECURITY_STATUS WINAPI
EnumerateSecurityPackagesA(PULONG pcPackages
,
904 PSecPkgInfoA
*ppPackageInfo
)
909 ret
= EnumerateSecurityPackagesW(pcPackages
, &info
);
910 if (ret
== SEC_E_OK
&& *pcPackages
&& info
)
912 *ppPackageInfo
= thunk_PSecPkgInfoWToA(*pcPackages
, info
);
913 if (*pcPackages
&& !*ppPackageInfo
)
916 ret
= SEC_E_INSUFFICIENT_MEMORY
;
918 FreeContextBuffer(info
);
923 /***********************************************************************
924 * GetComputerObjectNameA (SECUR32.@)
926 BOOLEAN WINAPI
GetComputerObjectNameA(
927 EXTENDED_NAME_FORMAT NameFormat
, LPSTR lpNameBuffer
, PULONG nSize
)
929 FIXME("%d %p %p\n", NameFormat
, lpNameBuffer
, nSize
);
933 /***********************************************************************
934 * GetComputerObjectNameW (SECUR32.@)
936 BOOLEAN WINAPI
GetComputerObjectNameW(
937 EXTENDED_NAME_FORMAT NameFormat
, LPWSTR lpNameBuffer
, PULONG nSize
)
939 FIXME("%d %p %p\n", NameFormat
, lpNameBuffer
, nSize
);
943 /***********************************************************************
944 * DllMain (SECUR32.0)
946 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
948 if (fdwReason
== DLL_PROCESS_ATTACH
)
950 DisableThreadLibraryCalls(hinstDLL
);
951 SECUR32_initializeProviders();
953 else if (fdwReason
== DLL_PROCESS_DETACH
)
955 SECUR32_freeProviders();