2004-03-02 05:57:35 +01:00
|
|
|
/* Copyright (C) 2004 Juan Lang
|
|
|
|
*
|
|
|
|
* This file implements loading of SSP DLLs.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2006-05-18 14:49:52 +02:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2004-03-02 05:57:35 +01:00
|
|
|
*/
|
2021-05-07 11:54:42 +02:00
|
|
|
|
2005-05-13 19:44:47 +02:00
|
|
|
#include <assert.h>
|
2004-03-02 05:57:35 +01:00
|
|
|
#include <stdarg.h>
|
2006-08-16 00:54:23 +02:00
|
|
|
|
|
|
|
#include "ntstatus.h"
|
|
|
|
#define WIN32_NO_STATUS
|
2004-03-02 05:57:35 +01:00
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "winnls.h"
|
|
|
|
#include "winreg.h"
|
|
|
|
#include "winternl.h"
|
|
|
|
#include "shlwapi.h"
|
|
|
|
#include "sspi.h"
|
2004-07-12 21:52:47 +02:00
|
|
|
#include "secext.h"
|
2005-07-18 11:11:14 +02:00
|
|
|
#include "ntsecapi.h"
|
2004-03-02 05:57:35 +01:00
|
|
|
#include "thunks.h"
|
2009-04-07 10:53:57 +02:00
|
|
|
#include "lmcons.h"
|
2004-03-02 05:57:35 +01:00
|
|
|
|
2005-08-30 10:55:20 +02:00
|
|
|
#include "wine/list.h"
|
2004-03-02 05:57:35 +01:00
|
|
|
#include "wine/debug.h"
|
2021-05-07 11:54:42 +02:00
|
|
|
#include "secur32_priv.h"
|
2004-03-02 05:57:35 +01:00
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(secur32);
|
|
|
|
|
2021-05-07 11:54:41 +02:00
|
|
|
HINSTANCE hsecur32;
|
|
|
|
|
2004-03-02 05:57:35 +01:00
|
|
|
/**
|
|
|
|
* Type definitions
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef struct _SecurePackageTable
|
|
|
|
{
|
|
|
|
DWORD numPackages;
|
|
|
|
DWORD numAllocated;
|
2005-08-30 10:55:20 +02:00
|
|
|
struct list table;
|
2004-03-02 05:57:35 +01:00
|
|
|
} SecurePackageTable;
|
|
|
|
|
|
|
|
typedef struct _SecureProviderTable
|
|
|
|
{
|
|
|
|
DWORD numProviders;
|
|
|
|
DWORD numAllocated;
|
2005-08-30 10:55:20 +02:00
|
|
|
struct list table;
|
2004-03-02 05:57:35 +01:00
|
|
|
} SecureProviderTable;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Prototypes
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Tries to load moduleName as a provider. If successful, enumerates what
|
|
|
|
* packages it can and adds them to the package and provider tables. Resizes
|
|
|
|
* tables as necessary.
|
|
|
|
*/
|
|
|
|
static void _tryLoadProvider(PWSTR moduleName);
|
|
|
|
|
|
|
|
/* Initialization: read securityproviders value and attempt to open each dll
|
|
|
|
* there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
|
|
|
|
* Two undocumented functions, AddSecurityPackage(A/W) and
|
|
|
|
* DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
|
|
|
|
* unregister a dll, but I'm not sure.
|
|
|
|
*/
|
|
|
|
static void SECUR32_initializeProviders(void);
|
|
|
|
|
|
|
|
/* Frees all loaded packages and providers */
|
|
|
|
static void SECUR32_freeProviders(void);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Globals
|
|
|
|
*/
|
|
|
|
|
|
|
|
static CRITICAL_SECTION cs;
|
2011-11-15 14:41:11 +01:00
|
|
|
static CRITICAL_SECTION_DEBUG cs_debug =
|
|
|
|
{
|
|
|
|
0, 0, &cs,
|
|
|
|
{ &cs_debug.ProcessLocksList, &cs_debug.ProcessLocksList },
|
|
|
|
0, 0, { (DWORD_PTR)(__FILE__ ": cs") }
|
|
|
|
};
|
|
|
|
static CRITICAL_SECTION cs = { &cs_debug, -1, 0, 0, 0, 0 };
|
2004-03-02 05:57:35 +01:00
|
|
|
static SecurePackageTable *packageTable = NULL;
|
|
|
|
static SecureProviderTable *providerTable = NULL;
|
|
|
|
|
|
|
|
static SecurityFunctionTableA securityFunctionTableA = {
|
2007-05-24 14:05:28 +02:00
|
|
|
SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
|
2004-03-02 05:57:35 +01:00
|
|
|
EnumerateSecurityPackagesA,
|
|
|
|
QueryCredentialsAttributesA,
|
|
|
|
AcquireCredentialsHandleA,
|
|
|
|
FreeCredentialsHandle,
|
|
|
|
NULL, /* Reserved2 */
|
|
|
|
InitializeSecurityContextA,
|
|
|
|
AcceptSecurityContext,
|
|
|
|
CompleteAuthToken,
|
|
|
|
DeleteSecurityContext,
|
|
|
|
ApplyControlToken,
|
|
|
|
QueryContextAttributesA,
|
|
|
|
ImpersonateSecurityContext,
|
|
|
|
RevertSecurityContext,
|
|
|
|
MakeSignature,
|
|
|
|
VerifySignature,
|
|
|
|
FreeContextBuffer,
|
|
|
|
QuerySecurityPackageInfoA,
|
2008-08-19 17:50:53 +02:00
|
|
|
EncryptMessage, /* Reserved3 */
|
|
|
|
DecryptMessage, /* Reserved4 */
|
2004-03-02 05:57:35 +01:00
|
|
|
ExportSecurityContext,
|
|
|
|
ImportSecurityContextA,
|
|
|
|
AddCredentialsA,
|
|
|
|
NULL, /* Reserved8 */
|
|
|
|
QuerySecurityContextToken,
|
|
|
|
EncryptMessage,
|
|
|
|
DecryptMessage,
|
|
|
|
SetContextAttributesA
|
|
|
|
};
|
|
|
|
|
|
|
|
static SecurityFunctionTableW securityFunctionTableW = {
|
2007-05-24 14:05:28 +02:00
|
|
|
SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
|
2004-03-02 05:57:35 +01:00
|
|
|
EnumerateSecurityPackagesW,
|
|
|
|
QueryCredentialsAttributesW,
|
|
|
|
AcquireCredentialsHandleW,
|
|
|
|
FreeCredentialsHandle,
|
|
|
|
NULL, /* Reserved2 */
|
|
|
|
InitializeSecurityContextW,
|
|
|
|
AcceptSecurityContext,
|
|
|
|
CompleteAuthToken,
|
|
|
|
DeleteSecurityContext,
|
|
|
|
ApplyControlToken,
|
|
|
|
QueryContextAttributesW,
|
|
|
|
ImpersonateSecurityContext,
|
|
|
|
RevertSecurityContext,
|
|
|
|
MakeSignature,
|
|
|
|
VerifySignature,
|
|
|
|
FreeContextBuffer,
|
|
|
|
QuerySecurityPackageInfoW,
|
2008-08-19 17:50:53 +02:00
|
|
|
EncryptMessage, /* Reserved3 */
|
|
|
|
DecryptMessage, /* Reserved4 */
|
2004-03-02 05:57:35 +01:00
|
|
|
ExportSecurityContext,
|
|
|
|
ImportSecurityContextW,
|
|
|
|
AddCredentialsW,
|
|
|
|
NULL, /* Reserved8 */
|
|
|
|
QuerySecurityContextToken,
|
|
|
|
EncryptMessage,
|
|
|
|
DecryptMessage,
|
|
|
|
SetContextAttributesW
|
|
|
|
};
|
|
|
|
|
2004-05-17 23:08:31 +02:00
|
|
|
/***********************************************************************
|
|
|
|
* InitSecurityInterfaceA (SECUR32.@)
|
|
|
|
*/
|
|
|
|
PSecurityFunctionTableA WINAPI InitSecurityInterfaceA(void)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
|
|
|
return &securityFunctionTableA;
|
|
|
|
}
|
|
|
|
|
2004-05-17 23:08:31 +02:00
|
|
|
/***********************************************************************
|
|
|
|
* InitSecurityInterfaceW (SECUR32.@)
|
|
|
|
*/
|
|
|
|
PSecurityFunctionTableW WINAPI InitSecurityInterfaceW(void)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
|
|
|
return &securityFunctionTableW;
|
|
|
|
}
|
|
|
|
|
2021-05-07 11:54:44 +02:00
|
|
|
static WCHAR *strdupW( const WCHAR *str )
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
2021-05-07 11:54:42 +02:00
|
|
|
WCHAR *ret = NULL;
|
2021-05-07 11:54:44 +02:00
|
|
|
if (str && (ret = malloc( (wcslen(str) + 1) * sizeof(WCHAR) ))) wcscpy( ret, str );
|
2004-03-02 05:57:35 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _makeFnTableA(PSecurityFunctionTableA fnTableA,
|
2006-01-24 14:00:32 +01:00
|
|
|
const SecurityFunctionTableA *inFnTableA,
|
|
|
|
const SecurityFunctionTableW *inFnTableW)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
|
|
|
if (fnTableA)
|
|
|
|
{
|
|
|
|
if (inFnTableA)
|
|
|
|
{
|
|
|
|
/* The size of the version 1 table is based on platform sdk's
|
|
|
|
* sspi.h, though the sample ssp also provided with platform sdk
|
|
|
|
* implies only functions through QuerySecurityPackageInfoA are
|
|
|
|
* implemented (yikes)
|
|
|
|
*/
|
|
|
|
size_t tableSize = inFnTableA->dwVersion == 1 ?
|
2019-02-19 20:44:31 +01:00
|
|
|
offsetof(SecurityFunctionTableA, SetContextAttributesA) :
|
|
|
|
sizeof(SecurityFunctionTableA);
|
2004-03-02 05:57:35 +01:00
|
|
|
|
|
|
|
memcpy(fnTableA, inFnTableA, tableSize);
|
|
|
|
/* override this, since we can do it internally anyway */
|
|
|
|
fnTableA->QuerySecurityPackageInfoA =
|
|
|
|
QuerySecurityPackageInfoA;
|
|
|
|
}
|
|
|
|
else if (inFnTableW)
|
|
|
|
{
|
|
|
|
/* functions with thunks */
|
|
|
|
if (inFnTableW->AcquireCredentialsHandleW)
|
|
|
|
fnTableA->AcquireCredentialsHandleA =
|
|
|
|
thunk_AcquireCredentialsHandleA;
|
|
|
|
if (inFnTableW->InitializeSecurityContextW)
|
|
|
|
fnTableA->InitializeSecurityContextA =
|
|
|
|
thunk_InitializeSecurityContextA;
|
|
|
|
if (inFnTableW->ImportSecurityContextW)
|
|
|
|
fnTableA->ImportSecurityContextA =
|
|
|
|
thunk_ImportSecurityContextA;
|
|
|
|
if (inFnTableW->AddCredentialsW)
|
|
|
|
fnTableA->AddCredentialsA =
|
|
|
|
thunk_AddCredentialsA;
|
|
|
|
if (inFnTableW->QueryCredentialsAttributesW)
|
|
|
|
fnTableA->QueryCredentialsAttributesA =
|
|
|
|
thunk_QueryCredentialsAttributesA;
|
|
|
|
if (inFnTableW->QueryContextAttributesW)
|
|
|
|
fnTableA->QueryContextAttributesA =
|
|
|
|
thunk_QueryContextAttributesA;
|
|
|
|
if (inFnTableW->SetContextAttributesW)
|
|
|
|
fnTableA->SetContextAttributesA =
|
|
|
|
thunk_SetContextAttributesA;
|
|
|
|
/* this can't be thunked, there's no extra param to know which
|
|
|
|
* package to forward to */
|
|
|
|
fnTableA->EnumerateSecurityPackagesA = NULL;
|
|
|
|
/* functions with no thunks needed */
|
|
|
|
fnTableA->AcceptSecurityContext = inFnTableW->AcceptSecurityContext;
|
|
|
|
fnTableA->CompleteAuthToken = inFnTableW->CompleteAuthToken;
|
|
|
|
fnTableA->DeleteSecurityContext = inFnTableW->DeleteSecurityContext;
|
|
|
|
fnTableA->ImpersonateSecurityContext =
|
|
|
|
inFnTableW->ImpersonateSecurityContext;
|
|
|
|
fnTableA->RevertSecurityContext = inFnTableW->RevertSecurityContext;
|
|
|
|
fnTableA->MakeSignature = inFnTableW->MakeSignature;
|
|
|
|
fnTableA->VerifySignature = inFnTableW->VerifySignature;
|
|
|
|
fnTableA->FreeContextBuffer = inFnTableW->FreeContextBuffer;
|
|
|
|
fnTableA->QuerySecurityPackageInfoA =
|
|
|
|
QuerySecurityPackageInfoA;
|
|
|
|
fnTableA->ExportSecurityContext =
|
|
|
|
inFnTableW->ExportSecurityContext;
|
|
|
|
fnTableA->QuerySecurityContextToken =
|
|
|
|
inFnTableW->QuerySecurityContextToken;
|
|
|
|
fnTableA->EncryptMessage = inFnTableW->EncryptMessage;
|
|
|
|
fnTableA->DecryptMessage = inFnTableW->DecryptMessage;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _makeFnTableW(PSecurityFunctionTableW fnTableW,
|
2006-01-24 14:00:32 +01:00
|
|
|
const SecurityFunctionTableA *inFnTableA,
|
|
|
|
const SecurityFunctionTableW *inFnTableW)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
|
|
|
if (fnTableW)
|
|
|
|
{
|
|
|
|
if (inFnTableW)
|
|
|
|
{
|
|
|
|
/* The size of the version 1 table is based on platform sdk's
|
|
|
|
* sspi.h, though the sample ssp also provided with platform sdk
|
|
|
|
* implies only functions through QuerySecurityPackageInfoA are
|
|
|
|
* implemented (yikes)
|
|
|
|
*/
|
|
|
|
size_t tableSize = inFnTableW->dwVersion == 1 ?
|
2019-02-19 20:44:31 +01:00
|
|
|
offsetof(SecurityFunctionTableW, SetContextAttributesW) :
|
|
|
|
sizeof(SecurityFunctionTableW);
|
2004-03-02 05:57:35 +01:00
|
|
|
|
|
|
|
memcpy(fnTableW, inFnTableW, tableSize);
|
|
|
|
/* override this, since we can do it internally anyway */
|
|
|
|
fnTableW->QuerySecurityPackageInfoW =
|
|
|
|
QuerySecurityPackageInfoW;
|
|
|
|
}
|
|
|
|
else if (inFnTableA)
|
|
|
|
{
|
|
|
|
/* functions with thunks */
|
|
|
|
if (inFnTableA->AcquireCredentialsHandleA)
|
|
|
|
fnTableW->AcquireCredentialsHandleW =
|
|
|
|
thunk_AcquireCredentialsHandleW;
|
|
|
|
if (inFnTableA->InitializeSecurityContextA)
|
|
|
|
fnTableW->InitializeSecurityContextW =
|
|
|
|
thunk_InitializeSecurityContextW;
|
|
|
|
if (inFnTableA->ImportSecurityContextA)
|
|
|
|
fnTableW->ImportSecurityContextW =
|
|
|
|
thunk_ImportSecurityContextW;
|
|
|
|
if (inFnTableA->AddCredentialsA)
|
|
|
|
fnTableW->AddCredentialsW =
|
|
|
|
thunk_AddCredentialsW;
|
|
|
|
if (inFnTableA->QueryCredentialsAttributesA)
|
|
|
|
fnTableW->QueryCredentialsAttributesW =
|
|
|
|
thunk_QueryCredentialsAttributesW;
|
|
|
|
if (inFnTableA->QueryContextAttributesA)
|
|
|
|
fnTableW->QueryContextAttributesW =
|
|
|
|
thunk_QueryContextAttributesW;
|
|
|
|
if (inFnTableA->SetContextAttributesA)
|
|
|
|
fnTableW->SetContextAttributesW =
|
|
|
|
thunk_SetContextAttributesW;
|
|
|
|
/* this can't be thunked, there's no extra param to know which
|
|
|
|
* package to forward to */
|
|
|
|
fnTableW->EnumerateSecurityPackagesW = NULL;
|
|
|
|
/* functions with no thunks needed */
|
|
|
|
fnTableW->AcceptSecurityContext = inFnTableA->AcceptSecurityContext;
|
|
|
|
fnTableW->CompleteAuthToken = inFnTableA->CompleteAuthToken;
|
|
|
|
fnTableW->DeleteSecurityContext = inFnTableA->DeleteSecurityContext;
|
|
|
|
fnTableW->ImpersonateSecurityContext =
|
|
|
|
inFnTableA->ImpersonateSecurityContext;
|
|
|
|
fnTableW->RevertSecurityContext = inFnTableA->RevertSecurityContext;
|
|
|
|
fnTableW->MakeSignature = inFnTableA->MakeSignature;
|
|
|
|
fnTableW->VerifySignature = inFnTableA->VerifySignature;
|
|
|
|
fnTableW->FreeContextBuffer = inFnTableA->FreeContextBuffer;
|
|
|
|
fnTableW->QuerySecurityPackageInfoW =
|
|
|
|
QuerySecurityPackageInfoW;
|
|
|
|
fnTableW->ExportSecurityContext =
|
|
|
|
inFnTableA->ExportSecurityContext;
|
|
|
|
fnTableW->QuerySecurityContextToken =
|
|
|
|
inFnTableA->QuerySecurityContextToken;
|
|
|
|
fnTableW->EncryptMessage = inFnTableA->EncryptMessage;
|
|
|
|
fnTableW->DecryptMessage = inFnTableA->DecryptMessage;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-07 11:54:44 +02:00
|
|
|
static WCHAR *strdupAW( const char *str )
|
|
|
|
{
|
|
|
|
WCHAR *ret = NULL;
|
|
|
|
if (str)
|
|
|
|
{
|
|
|
|
int len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
|
|
|
|
if ((ret = malloc( len * sizeof(WCHAR) ))) MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-05-13 19:44:47 +02:00
|
|
|
static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA,
|
|
|
|
const SecPkgInfoW *inInfoW)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
|
|
|
if (info && (inInfoA || inInfoW))
|
|
|
|
{
|
|
|
|
/* odd, I know, but up until Name and Comment the structures are
|
|
|
|
* identical
|
|
|
|
*/
|
2006-09-27 21:03:31 +02:00
|
|
|
memcpy(info, inInfoW ? inInfoW : (const SecPkgInfoW *)inInfoA, sizeof(*info));
|
2004-03-02 05:57:35 +01:00
|
|
|
if (inInfoW)
|
|
|
|
{
|
2021-05-07 11:54:44 +02:00
|
|
|
info->Name = strdupW(inInfoW->Name);
|
|
|
|
info->Comment = strdupW(inInfoW->Comment);
|
2004-03-02 05:57:35 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-07 11:54:44 +02:00
|
|
|
info->Name = strdupAW(inInfoA->Name);
|
|
|
|
info->Comment = strdupAW(inInfoA->Comment);
|
2004-03-02 05:57:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-24 14:00:32 +01:00
|
|
|
SecureProvider *SECUR32_addProvider(const SecurityFunctionTableA *fnTableA,
|
2007-03-26 22:29:02 +02:00
|
|
|
const SecurityFunctionTableW *fnTableW, PCWSTR moduleName)
|
2005-05-13 19:44:47 +02:00
|
|
|
{
|
|
|
|
SecureProvider *ret;
|
|
|
|
|
|
|
|
EnterCriticalSection(&cs);
|
2005-08-30 10:55:20 +02:00
|
|
|
|
|
|
|
if (!providerTable)
|
2005-05-13 19:44:47 +02:00
|
|
|
{
|
2021-09-15 12:31:03 +02:00
|
|
|
if (!(providerTable = malloc(sizeof(*providerTable))))
|
2006-05-01 15:56:53 +02:00
|
|
|
{
|
|
|
|
LeaveCriticalSection(&cs);
|
2005-08-30 10:55:20 +02:00
|
|
|
return NULL;
|
2006-05-01 15:56:53 +02:00
|
|
|
}
|
2005-08-30 10:55:20 +02:00
|
|
|
|
|
|
|
list_init(&providerTable->table);
|
|
|
|
}
|
|
|
|
|
2021-05-07 11:54:44 +02:00
|
|
|
if (!(ret = malloc(sizeof(*ret))))
|
2006-05-01 15:56:53 +02:00
|
|
|
{
|
|
|
|
LeaveCriticalSection(&cs);
|
2005-08-30 10:55:20 +02:00
|
|
|
return NULL;
|
2006-05-01 15:56:53 +02:00
|
|
|
}
|
2005-08-30 10:55:20 +02:00
|
|
|
|
|
|
|
list_add_tail(&providerTable->table, &ret->entry);
|
|
|
|
ret->lib = NULL;
|
|
|
|
|
|
|
|
if (fnTableA || fnTableW)
|
|
|
|
{
|
2021-05-07 11:54:44 +02:00
|
|
|
ret->moduleName = moduleName ? strdupW(moduleName) : NULL;
|
2005-08-30 10:55:20 +02:00
|
|
|
_makeFnTableA(&ret->fnTableA, fnTableA, fnTableW);
|
|
|
|
_makeFnTableW(&ret->fnTableW, fnTableA, fnTableW);
|
2012-08-14 23:18:43 +02:00
|
|
|
ret->loaded = !moduleName;
|
2005-05-13 19:44:47 +02:00
|
|
|
}
|
|
|
|
else
|
2005-08-30 10:55:20 +02:00
|
|
|
{
|
2021-05-07 11:54:44 +02:00
|
|
|
ret->moduleName = strdupW(moduleName);
|
2005-08-30 10:55:20 +02:00
|
|
|
ret->loaded = FALSE;
|
|
|
|
}
|
2021-05-07 11:54:44 +02:00
|
|
|
|
2005-05-13 19:44:47 +02:00
|
|
|
LeaveCriticalSection(&cs);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
|
|
|
|
const SecPkgInfoA *infoA, const SecPkgInfoW *infoW)
|
|
|
|
{
|
2005-08-30 10:55:20 +02:00
|
|
|
ULONG i;
|
|
|
|
|
2005-05-13 19:44:47 +02:00
|
|
|
assert(provider);
|
|
|
|
assert(infoA || infoW);
|
|
|
|
|
|
|
|
EnterCriticalSection(&cs);
|
2005-08-30 10:55:20 +02:00
|
|
|
|
|
|
|
if (!packageTable)
|
2005-05-13 19:44:47 +02:00
|
|
|
{
|
2021-05-07 11:54:44 +02:00
|
|
|
if (!(packageTable = malloc(sizeof(*packageTable))))
|
2006-05-01 15:56:53 +02:00
|
|
|
{
|
|
|
|
LeaveCriticalSection(&cs);
|
2005-08-30 10:55:20 +02:00
|
|
|
return;
|
2006-05-01 15:56:53 +02:00
|
|
|
}
|
2005-05-13 19:44:47 +02:00
|
|
|
|
2005-08-30 10:55:20 +02:00
|
|
|
packageTable->numPackages = 0;
|
|
|
|
list_init(&packageTable->table);
|
|
|
|
}
|
2021-05-07 11:54:44 +02:00
|
|
|
|
2005-08-30 10:55:20 +02:00
|
|
|
for (i = 0; i < toAdd; i++)
|
|
|
|
{
|
2021-05-07 11:54:44 +02:00
|
|
|
SecurePackage *package;
|
|
|
|
|
|
|
|
if (!(package = malloc(sizeof(*package)))) continue;
|
2005-05-13 19:44:47 +02:00
|
|
|
|
2005-08-30 10:55:20 +02:00
|
|
|
list_add_tail(&packageTable->table, &package->entry);
|
|
|
|
|
|
|
|
package->provider = provider;
|
2021-05-07 11:54:44 +02:00
|
|
|
_copyPackageInfo(&package->infoW, infoA ? &infoA[i] : NULL, infoW ? &infoW[i] : NULL);
|
2005-05-13 19:44:47 +02:00
|
|
|
}
|
2005-08-30 10:55:20 +02:00
|
|
|
packageTable->numPackages += toAdd;
|
|
|
|
|
2005-05-13 19:44:47 +02:00
|
|
|
LeaveCriticalSection(&cs);
|
|
|
|
}
|
|
|
|
|
2004-03-02 05:57:35 +01:00
|
|
|
static void _tryLoadProvider(PWSTR moduleName)
|
|
|
|
{
|
|
|
|
HMODULE lib = LoadLibraryW(moduleName);
|
|
|
|
|
|
|
|
if (lib)
|
|
|
|
{
|
|
|
|
INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
|
|
|
|
(INIT_SECURITY_INTERFACE_W)GetProcAddress(lib,
|
|
|
|
SECURITY_ENTRYPOINT_ANSIW);
|
|
|
|
INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
|
|
|
|
(INIT_SECURITY_INTERFACE_A)GetProcAddress(lib,
|
|
|
|
SECURITY_ENTRYPOINT_ANSIA);
|
|
|
|
|
|
|
|
TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
|
|
|
|
debugstr_w(moduleName), pInitSecurityInterfaceA,
|
|
|
|
pInitSecurityInterfaceW);
|
|
|
|
if (pInitSecurityInterfaceW || pInitSecurityInterfaceA)
|
|
|
|
{
|
|
|
|
PSecurityFunctionTableA fnTableA = NULL;
|
|
|
|
PSecurityFunctionTableW fnTableW = NULL;
|
|
|
|
ULONG toAdd = 0;
|
|
|
|
PSecPkgInfoA infoA = NULL;
|
|
|
|
PSecPkgInfoW infoW = NULL;
|
|
|
|
SECURITY_STATUS ret = SEC_E_OK;
|
|
|
|
|
|
|
|
if (pInitSecurityInterfaceA)
|
|
|
|
fnTableA = pInitSecurityInterfaceA();
|
|
|
|
if (pInitSecurityInterfaceW)
|
|
|
|
fnTableW = pInitSecurityInterfaceW();
|
|
|
|
if (fnTableW && fnTableW->EnumerateSecurityPackagesW)
|
2008-07-02 17:18:49 +02:00
|
|
|
{
|
|
|
|
if (fnTableW != &securityFunctionTableW)
|
|
|
|
ret = fnTableW->EnumerateSecurityPackagesW(&toAdd, &infoW);
|
|
|
|
else
|
|
|
|
TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName));
|
|
|
|
}
|
2004-03-02 05:57:35 +01:00
|
|
|
else if (fnTableA && fnTableA->EnumerateSecurityPackagesA)
|
2008-07-02 17:18:49 +02:00
|
|
|
{
|
|
|
|
if (fnTableA != &securityFunctionTableA)
|
|
|
|
ret = fnTableA->EnumerateSecurityPackagesA(&toAdd, &infoA);
|
|
|
|
else
|
|
|
|
TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName));
|
|
|
|
}
|
2004-03-02 05:57:35 +01:00
|
|
|
if (ret == SEC_E_OK && toAdd > 0 && (infoW || infoA))
|
|
|
|
{
|
2005-05-13 19:44:47 +02:00
|
|
|
SecureProvider *provider = SECUR32_addProvider(NULL, NULL,
|
|
|
|
moduleName);
|
|
|
|
|
|
|
|
if (provider)
|
|
|
|
SECUR32_addPackages(provider, toAdd, infoA, infoW);
|
2004-03-02 05:57:35 +01:00
|
|
|
if (infoW)
|
|
|
|
fnTableW->FreeContextBuffer(infoW);
|
|
|
|
else
|
|
|
|
fnTableA->FreeContextBuffer(infoA);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FreeLibrary(lib);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
WARN("failed to load %s\n", debugstr_w(moduleName));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SECUR32_initializeProviders(void)
|
|
|
|
{
|
|
|
|
HKEY key;
|
2010-05-11 21:28:42 +02:00
|
|
|
LSTATUS apiRet;
|
2004-03-02 05:57:35 +01:00
|
|
|
|
|
|
|
TRACE("\n");
|
2005-05-13 19:44:47 +02:00
|
|
|
/* First load built-in providers */
|
|
|
|
SECUR32_initSchannelSP();
|
2018-02-01 11:04:33 +01:00
|
|
|
/* Load SSP/AP packages (Kerberos and others) */
|
|
|
|
load_auth_packages();
|
2009-08-11 22:13:10 +02:00
|
|
|
/* Load the Negotiate provider last so apps stumble over the working NTLM
|
|
|
|
* provider first. Attempting to fix bug #16905 while keeping the
|
|
|
|
* application reported on wine-users on 2006-09-12 working. */
|
|
|
|
SECUR32_initNegotiateSP();
|
2005-05-13 19:44:47 +02:00
|
|
|
/* Now load providers from registry */
|
2021-05-07 11:54:43 +02:00
|
|
|
apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\SecurityProviders", 0,
|
|
|
|
KEY_READ, &key);
|
2004-03-02 05:57:35 +01:00
|
|
|
if (apiRet == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
WCHAR securityPkgNames[MAX_PATH]; /* arbitrary len */
|
2017-02-08 13:15:20 +01:00
|
|
|
DWORD size = sizeof(securityPkgNames), type;
|
2004-03-02 05:57:35 +01:00
|
|
|
|
2021-05-07 11:54:43 +02:00
|
|
|
apiRet = RegQueryValueExW(key, L"SecurityProviders", NULL, &type, (PBYTE)securityPkgNames, &size);
|
2004-03-02 05:57:35 +01:00
|
|
|
if (apiRet == ERROR_SUCCESS && type == REG_SZ)
|
|
|
|
{
|
|
|
|
WCHAR *ptr;
|
|
|
|
|
2007-12-20 16:29:23 +01:00
|
|
|
size = size / sizeof(WCHAR);
|
2004-03-02 05:57:35 +01:00
|
|
|
for (ptr = securityPkgNames;
|
2007-12-20 16:29:23 +01:00
|
|
|
ptr < securityPkgNames + size; )
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
|
|
|
WCHAR *comma;
|
|
|
|
|
|
|
|
for (comma = ptr; *comma && *comma != ','; comma++)
|
|
|
|
;
|
|
|
|
if (*comma == ',')
|
|
|
|
*comma = '\0';
|
2021-05-07 11:54:42 +02:00
|
|
|
for (; *ptr && iswspace(*ptr) && ptr < securityPkgNames + size;
|
2017-05-17 14:35:40 +02:00
|
|
|
ptr++)
|
2004-03-02 05:57:35 +01:00
|
|
|
;
|
|
|
|
if (*ptr)
|
|
|
|
_tryLoadProvider(ptr);
|
|
|
|
ptr += lstrlenW(ptr) + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RegCloseKey(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-25 23:21:07 +02:00
|
|
|
SecurePackage *SECUR32_findPackageW(PCWSTR packageName)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
2005-05-13 19:44:47 +02:00
|
|
|
SecurePackage *ret = NULL;
|
2005-11-07 17:39:00 +01:00
|
|
|
BOOL matched = FALSE;
|
2004-03-02 05:57:35 +01:00
|
|
|
|
|
|
|
if (packageTable && packageName)
|
|
|
|
{
|
2005-08-30 10:55:20 +02:00
|
|
|
LIST_FOR_EACH_ENTRY(ret, &packageTable->table, SecurePackage, entry)
|
|
|
|
{
|
2005-11-07 17:39:00 +01:00
|
|
|
matched = !lstrcmpiW(ret->infoW.Name, packageName);
|
2021-05-07 11:54:44 +02:00
|
|
|
if (matched) break;
|
2005-08-30 10:55:20 +02:00
|
|
|
}
|
2021-05-07 11:54:44 +02:00
|
|
|
if (!matched) return NULL;
|
2005-11-07 17:39:00 +01:00
|
|
|
|
2021-05-07 11:54:44 +02:00
|
|
|
if (ret->provider && !ret->provider->loaded)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
|
|
|
ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
|
|
|
|
if (ret->provider->lib)
|
|
|
|
{
|
|
|
|
INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
|
|
|
|
(INIT_SECURITY_INTERFACE_W)GetProcAddress(ret->provider->lib,
|
|
|
|
SECURITY_ENTRYPOINT_ANSIW);
|
|
|
|
INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
|
|
|
|
(INIT_SECURITY_INTERFACE_A)GetProcAddress(ret->provider->lib,
|
|
|
|
SECURITY_ENTRYPOINT_ANSIA);
|
|
|
|
PSecurityFunctionTableA fnTableA = NULL;
|
|
|
|
PSecurityFunctionTableW fnTableW = NULL;
|
|
|
|
|
|
|
|
if (pInitSecurityInterfaceA)
|
|
|
|
fnTableA = pInitSecurityInterfaceA();
|
|
|
|
if (pInitSecurityInterfaceW)
|
|
|
|
fnTableW = pInitSecurityInterfaceW();
|
2008-07-10 00:25:28 +02:00
|
|
|
/* don't update built-in SecurityFunctionTable */
|
2008-07-02 17:18:49 +02:00
|
|
|
if (fnTableA != &securityFunctionTableA)
|
|
|
|
_makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW);
|
|
|
|
if (fnTableW != &securityFunctionTableW)
|
|
|
|
_makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW);
|
2005-05-13 19:44:47 +02:00
|
|
|
ret->provider->loaded = TRUE;
|
2004-03-02 05:57:35 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2007-08-25 23:21:07 +02:00
|
|
|
SecurePackage *SECUR32_findPackageA(PCSTR packageName)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
|
|
|
SecurePackage *ret;
|
|
|
|
|
|
|
|
if (packageTable && packageName)
|
|
|
|
{
|
|
|
|
UNICODE_STRING package;
|
|
|
|
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&package, packageName);
|
|
|
|
ret = SECUR32_findPackageW(package.Buffer);
|
|
|
|
RtlFreeUnicodeString(&package);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = NULL;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SECUR32_freeProviders(void)
|
|
|
|
{
|
|
|
|
TRACE("\n");
|
|
|
|
EnterCriticalSection(&cs);
|
2005-08-30 10:55:20 +02:00
|
|
|
|
2008-09-22 22:14:04 +02:00
|
|
|
SECUR32_deinitSchannelSP();
|
|
|
|
|
2004-03-02 05:57:35 +01:00
|
|
|
if (packageTable)
|
|
|
|
{
|
2009-12-17 10:53:38 +01:00
|
|
|
SecurePackage *package, *package_next;
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(package, package_next, &packageTable->table,
|
|
|
|
SecurePackage, entry)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
2021-05-07 11:54:44 +02:00
|
|
|
free(package->infoW.Name);
|
|
|
|
free(package->infoW.Comment);
|
|
|
|
free(package);
|
2004-03-02 05:57:35 +01:00
|
|
|
}
|
2005-08-30 10:55:20 +02:00
|
|
|
|
2021-05-07 11:54:44 +02:00
|
|
|
free(packageTable);
|
2004-03-02 05:57:35 +01:00
|
|
|
packageTable = NULL;
|
|
|
|
}
|
2005-08-30 10:55:20 +02:00
|
|
|
|
2004-03-02 05:57:35 +01:00
|
|
|
if (providerTable)
|
|
|
|
{
|
2009-12-17 10:53:38 +01:00
|
|
|
SecureProvider *provider, *provider_next;
|
2021-05-07 11:54:44 +02:00
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(provider, provider_next, &providerTable->table, SecureProvider, entry)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
2021-05-07 11:54:44 +02:00
|
|
|
free(provider->moduleName);
|
|
|
|
if (provider->lib) FreeLibrary(provider->lib);
|
|
|
|
free(provider);
|
2004-03-02 05:57:35 +01:00
|
|
|
}
|
2005-08-30 10:55:20 +02:00
|
|
|
|
2021-05-07 11:54:44 +02:00
|
|
|
free(providerTable);
|
2004-03-02 05:57:35 +01:00
|
|
|
providerTable = NULL;
|
|
|
|
}
|
2005-08-30 10:55:20 +02:00
|
|
|
|
2004-03-02 05:57:35 +01:00
|
|
|
LeaveCriticalSection(&cs);
|
|
|
|
DeleteCriticalSection(&cs);
|
|
|
|
}
|
|
|
|
|
2004-05-17 23:08:31 +02:00
|
|
|
/***********************************************************************
|
|
|
|
* FreeContextBuffer (SECUR32.@)
|
|
|
|
*
|
|
|
|
* Doh--if pv was allocated by a crypto package, this may not be correct.
|
2004-03-02 05:57:35 +01:00
|
|
|
* The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
|
|
|
|
* be any guarantee, nor is there an alloc function in secur32.
|
|
|
|
*/
|
2021-05-07 11:54:44 +02:00
|
|
|
SECURITY_STATUS WINAPI FreeContextBuffer( void *pv )
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
2021-05-07 11:54:44 +02:00
|
|
|
RtlFreeHeap( GetProcessHeap(), 0, pv );
|
2006-04-27 13:52:58 +02:00
|
|
|
return SEC_E_OK;
|
2004-03-02 05:57:35 +01:00
|
|
|
}
|
|
|
|
|
2004-05-17 23:08:31 +02:00
|
|
|
/***********************************************************************
|
|
|
|
* EnumerateSecurityPackagesW (SECUR32.@)
|
|
|
|
*/
|
|
|
|
SECURITY_STATUS WINAPI EnumerateSecurityPackagesW(PULONG pcPackages,
|
2004-03-02 05:57:35 +01:00
|
|
|
PSecPkgInfoW *ppPackageInfo)
|
|
|
|
{
|
|
|
|
SECURITY_STATUS ret = SEC_E_OK;
|
|
|
|
|
2006-02-10 14:51:59 +01:00
|
|
|
TRACE("(%p, %p)\n", pcPackages, ppPackageInfo);
|
|
|
|
|
2004-03-02 05:57:35 +01:00
|
|
|
/* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
|
|
|
|
*pcPackages = 0;
|
|
|
|
EnterCriticalSection(&cs);
|
|
|
|
if (packageTable)
|
|
|
|
{
|
2005-08-30 10:55:20 +02:00
|
|
|
SecurePackage *package;
|
2004-03-02 05:57:35 +01:00
|
|
|
size_t bytesNeeded;
|
|
|
|
|
|
|
|
bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
|
2005-08-30 10:55:20 +02:00
|
|
|
LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
2005-08-30 10:55:20 +02:00
|
|
|
if (package->infoW.Name)
|
|
|
|
bytesNeeded += (lstrlenW(package->infoW.Name) + 1) * sizeof(WCHAR);
|
|
|
|
if (package->infoW.Comment)
|
|
|
|
bytesNeeded += (lstrlenW(package->infoW.Comment) + 1) * sizeof(WCHAR);
|
2004-03-02 05:57:35 +01:00
|
|
|
}
|
|
|
|
if (bytesNeeded)
|
|
|
|
{
|
2021-05-07 11:54:44 +02:00
|
|
|
/* freed with FeeContextBuffer */
|
|
|
|
if ((*ppPackageInfo = RtlAllocateHeap(GetProcessHeap(), 0, bytesNeeded)))
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
2005-08-30 10:55:20 +02:00
|
|
|
ULONG i = 0;
|
2004-03-02 05:57:35 +01:00
|
|
|
PWSTR nextString;
|
|
|
|
|
|
|
|
*pcPackages = packageTable->numPackages;
|
|
|
|
nextString = (PWSTR)((PBYTE)*ppPackageInfo +
|
|
|
|
packageTable->numPackages * sizeof(SecPkgInfoW));
|
2005-08-30 10:55:20 +02:00
|
|
|
LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
2005-08-30 10:55:20 +02:00
|
|
|
PSecPkgInfoW pkgInfo = *ppPackageInfo + i++;
|
2004-03-02 05:57:35 +01:00
|
|
|
|
2008-03-16 00:25:42 +01:00
|
|
|
*pkgInfo = package->infoW;
|
2005-08-30 10:55:20 +02:00
|
|
|
if (package->infoW.Name)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
2006-10-15 14:51:52 +02:00
|
|
|
TRACE("Name[%d] = %s\n", i - 1, debugstr_w(package->infoW.Name));
|
2004-03-02 05:57:35 +01:00
|
|
|
pkgInfo->Name = nextString;
|
2005-08-30 10:55:20 +02:00
|
|
|
lstrcpyW(nextString, package->infoW.Name);
|
2004-03-02 05:57:35 +01:00
|
|
|
nextString += lstrlenW(nextString) + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pkgInfo->Name = NULL;
|
2005-08-30 10:55:20 +02:00
|
|
|
if (package->infoW.Comment)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
2006-10-15 14:51:52 +02:00
|
|
|
TRACE("Comment[%d] = %s\n", i - 1, debugstr_w(package->infoW.Comment));
|
2004-03-02 05:57:35 +01:00
|
|
|
pkgInfo->Comment = nextString;
|
2005-08-30 10:55:20 +02:00
|
|
|
lstrcpyW(nextString, package->infoW.Comment);
|
2004-03-02 05:57:35 +01:00
|
|
|
nextString += lstrlenW(nextString) + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pkgInfo->Comment = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = SEC_E_INSUFFICIENT_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LeaveCriticalSection(&cs);
|
2006-10-15 14:51:52 +02:00
|
|
|
TRACE("<-- 0x%08x\n", ret);
|
2004-03-02 05:57:35 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
|
|
|
|
* structures) into an array of SecPkgInfoA structures, which it returns.
|
|
|
|
*/
|
|
|
|
static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
|
2007-08-25 23:21:07 +02:00
|
|
|
const SecPkgInfoW *info)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
|
|
|
PSecPkgInfoA ret;
|
|
|
|
|
|
|
|
if (info)
|
|
|
|
{
|
|
|
|
size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
|
|
|
|
ULONG i;
|
|
|
|
|
|
|
|
for (i = 0; i < cPackages; i++)
|
|
|
|
{
|
|
|
|
if (info[i].Name)
|
|
|
|
bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
|
|
|
|
-1, NULL, 0, NULL, NULL);
|
|
|
|
if (info[i].Comment)
|
|
|
|
bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
|
|
|
|
-1, NULL, 0, NULL, NULL);
|
|
|
|
}
|
2021-05-07 11:54:44 +02:00
|
|
|
/* freed with FreeContextBuffer */
|
|
|
|
if ((ret = RtlAllocateHeap(GetProcessHeap(), 0, bytesNeeded)))
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
|
|
|
PSTR nextString;
|
|
|
|
|
|
|
|
nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
|
|
|
|
for (i = 0; i < cPackages; i++)
|
|
|
|
{
|
|
|
|
PSecPkgInfoA pkgInfo = ret + i;
|
|
|
|
int bytes;
|
|
|
|
|
|
|
|
memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
|
|
|
|
if (info[i].Name)
|
|
|
|
{
|
|
|
|
pkgInfo->Name = nextString;
|
|
|
|
/* just repeat back to WideCharToMultiByte how many bytes
|
|
|
|
* it requires, since we asked it earlier
|
|
|
|
*/
|
|
|
|
bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
|
|
|
|
NULL, 0, NULL, NULL);
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
|
|
|
|
pkgInfo->Name, bytes, NULL, NULL);
|
|
|
|
nextString += lstrlenA(nextString) + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pkgInfo->Name = NULL;
|
|
|
|
if (info[i].Comment)
|
|
|
|
{
|
|
|
|
pkgInfo->Comment = nextString;
|
|
|
|
/* just repeat back to WideCharToMultiByte how many bytes
|
|
|
|
* it requires, since we asked it earlier
|
|
|
|
*/
|
|
|
|
bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
|
|
|
|
NULL, 0, NULL, NULL);
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
|
|
|
|
pkgInfo->Comment, bytes, NULL, NULL);
|
|
|
|
nextString += lstrlenA(nextString) + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pkgInfo->Comment = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = NULL;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2004-05-17 23:08:31 +02:00
|
|
|
/***********************************************************************
|
|
|
|
* EnumerateSecurityPackagesA (SECUR32.@)
|
|
|
|
*/
|
|
|
|
SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
|
2004-03-02 05:57:35 +01:00
|
|
|
PSecPkgInfoA *ppPackageInfo)
|
|
|
|
{
|
|
|
|
SECURITY_STATUS ret;
|
|
|
|
PSecPkgInfoW info;
|
|
|
|
|
|
|
|
ret = EnumerateSecurityPackagesW(pcPackages, &info);
|
|
|
|
if (ret == SEC_E_OK && *pcPackages && info)
|
|
|
|
{
|
|
|
|
*ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
|
|
|
|
if (*pcPackages && !*ppPackageInfo)
|
|
|
|
{
|
|
|
|
*pcPackages = 0;
|
|
|
|
ret = SEC_E_INSUFFICIENT_MEMORY;
|
|
|
|
}
|
|
|
|
FreeContextBuffer(info);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2004-07-12 21:52:47 +02:00
|
|
|
/***********************************************************************
|
|
|
|
* GetComputerObjectNameA (SECUR32.@)
|
2006-08-16 00:54:23 +02:00
|
|
|
*
|
|
|
|
* Get the local computer's name using the format specified.
|
|
|
|
*
|
|
|
|
* PARAMS
|
|
|
|
* NameFormat [I] The format for the name.
|
|
|
|
* lpNameBuffer [O] Pointer to buffer to receive the name.
|
|
|
|
* nSize [I/O] Size in characters of buffer.
|
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* TRUE If the name was written to lpNameBuffer.
|
|
|
|
* FALSE If the name couldn't be written.
|
|
|
|
*
|
|
|
|
* NOTES
|
|
|
|
* If lpNameBuffer is NULL, then the size of the buffer needed to hold the
|
|
|
|
* name will be returned in *nSize.
|
|
|
|
*
|
|
|
|
* nSize returns the number of characters written when lpNameBuffer is not
|
|
|
|
* NULL or the size of the buffer needed to hold the name when the buffer
|
|
|
|
* is too short or lpNameBuffer is NULL.
|
2021-05-07 11:54:44 +02:00
|
|
|
*
|
2006-08-16 00:54:23 +02:00
|
|
|
* It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
|
2004-07-12 21:52:47 +02:00
|
|
|
*/
|
|
|
|
BOOLEAN WINAPI GetComputerObjectNameA(
|
|
|
|
EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
|
|
|
|
{
|
2006-08-16 00:54:23 +02:00
|
|
|
BOOLEAN rc;
|
|
|
|
LPWSTR bufferW = NULL;
|
|
|
|
ULONG sizeW = *nSize;
|
2018-03-27 11:06:12 +02:00
|
|
|
|
2006-08-16 00:54:23 +02:00
|
|
|
TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
|
2018-03-27 11:06:12 +02:00
|
|
|
|
2006-08-16 00:54:23 +02:00
|
|
|
if (lpNameBuffer) {
|
2021-05-07 11:54:44 +02:00
|
|
|
if (!(bufferW = malloc(sizeW * sizeof(WCHAR)))) {
|
2006-08-16 00:54:23 +02:00
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rc = GetComputerObjectNameW(NameFormat, bufferW, &sizeW);
|
|
|
|
if (rc && bufferW) {
|
|
|
|
ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
|
|
|
|
*nSize = len;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*nSize = sizeW;
|
2021-05-07 11:54:44 +02:00
|
|
|
free(bufferW);
|
2006-08-16 00:54:23 +02:00
|
|
|
return rc;
|
2004-07-12 21:52:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetComputerObjectNameW (SECUR32.@)
|
|
|
|
*/
|
|
|
|
BOOLEAN WINAPI GetComputerObjectNameW(
|
|
|
|
EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
|
|
|
|
{
|
2006-08-16 00:54:23 +02:00
|
|
|
LSA_HANDLE policyHandle;
|
|
|
|
LSA_OBJECT_ATTRIBUTES objectAttributes;
|
|
|
|
PPOLICY_DNS_DOMAIN_INFO domainInfo;
|
|
|
|
NTSTATUS ntStatus;
|
|
|
|
BOOLEAN status;
|
2018-03-27 11:06:12 +02:00
|
|
|
|
2006-08-16 00:54:23 +02:00
|
|
|
TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
|
|
|
|
|
|
|
|
if (NameFormat == NameUnknown)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZeroMemory(&objectAttributes, sizeof(objectAttributes));
|
|
|
|
objectAttributes.Length = sizeof(objectAttributes);
|
|
|
|
|
|
|
|
ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
|
|
|
|
POLICY_VIEW_LOCAL_INFORMATION,
|
|
|
|
&policyHandle);
|
|
|
|
if (ntStatus != STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
SetLastError(LsaNtStatusToWinError(ntStatus));
|
2007-01-18 11:37:08 +01:00
|
|
|
WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
|
2006-08-16 00:54:23 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ntStatus = LsaQueryInformationPolicy(policyHandle,
|
|
|
|
PolicyDnsDomainInformation,
|
|
|
|
(PVOID *)&domainInfo);
|
|
|
|
if (ntStatus != STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
SetLastError(LsaNtStatusToWinError(ntStatus));
|
2007-01-18 11:37:08 +01:00
|
|
|
WARN("LsaQueryInformationPolicy failed with NT status %u\n",
|
2006-08-16 00:54:23 +02:00
|
|
|
GetLastError());
|
|
|
|
LsaClose(policyHandle);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (domainInfo->Sid)
|
|
|
|
{
|
|
|
|
switch (NameFormat)
|
|
|
|
{
|
|
|
|
case NameSamCompatible:
|
|
|
|
{
|
|
|
|
WCHAR name[MAX_COMPUTERNAME_LENGTH + 1];
|
2018-07-18 23:01:32 +02:00
|
|
|
DWORD size = ARRAY_SIZE(name);
|
2006-08-16 00:54:23 +02:00
|
|
|
if (GetComputerNameW(name, &size))
|
|
|
|
{
|
2008-11-08 16:16:26 +01:00
|
|
|
DWORD len = domainInfo->Name.Length + size + 3;
|
2018-03-01 09:25:44 +01:00
|
|
|
if (lpNameBuffer && *nSize >= len)
|
2006-08-16 00:54:23 +02:00
|
|
|
{
|
2018-03-27 11:06:12 +02:00
|
|
|
if (domainInfo->Name.Buffer)
|
|
|
|
{
|
|
|
|
lstrcpyW(lpNameBuffer, domainInfo->Name.Buffer);
|
2021-05-07 11:54:43 +02:00
|
|
|
lstrcatW(lpNameBuffer, L"\\");
|
2018-03-27 11:06:12 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
*lpNameBuffer = 0;
|
2018-03-01 09:25:44 +01:00
|
|
|
lstrcatW(lpNameBuffer, name);
|
2021-05-07 11:54:43 +02:00
|
|
|
lstrcatW(lpNameBuffer, L"$");
|
2018-03-01 09:25:44 +01:00
|
|
|
status = TRUE;
|
2006-08-16 00:54:23 +02:00
|
|
|
}
|
|
|
|
else /* just requesting length required */
|
|
|
|
{
|
|
|
|
*nSize = len;
|
2018-03-01 09:25:44 +01:00
|
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
status = FALSE;
|
2006-08-16 00:54:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INTERNAL_ERROR);
|
|
|
|
status = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NameFullyQualifiedDN:
|
2018-03-02 11:46:13 +01:00
|
|
|
{
|
|
|
|
WCHAR name[MAX_COMPUTERNAME_LENGTH + 1];
|
|
|
|
DWORD len, size;
|
|
|
|
WCHAR *suffix;
|
|
|
|
|
2018-07-18 23:01:32 +02:00
|
|
|
size = ARRAY_SIZE(name);
|
2018-03-02 11:46:13 +01:00
|
|
|
if (!GetComputerNameW(name, &size))
|
|
|
|
{
|
|
|
|
status = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-05-07 11:54:43 +02:00
|
|
|
len = wcslen(L"CN=") + size + 1 + wcslen(L"CN=Computers") + 1 + wcslen(L"DC=");
|
2018-03-27 11:06:12 +02:00
|
|
|
if (domainInfo->DnsDomainName.Buffer)
|
2018-03-02 11:46:13 +01:00
|
|
|
{
|
2021-05-07 11:54:42 +02:00
|
|
|
suffix = wcsrchr(domainInfo->DnsDomainName.Buffer, '.');
|
2018-03-27 11:06:12 +02:00
|
|
|
if (suffix)
|
|
|
|
{
|
|
|
|
*suffix++ = 0;
|
2021-05-07 11:54:43 +02:00
|
|
|
len += 1 + wcslen(L"DC=") + wcslen(suffix);
|
2018-03-27 11:06:12 +02:00
|
|
|
}
|
2021-05-07 11:54:42 +02:00
|
|
|
len += wcslen(domainInfo->DnsDomainName.Buffer);
|
2018-03-02 11:46:13 +01:00
|
|
|
}
|
2018-03-27 11:06:12 +02:00
|
|
|
else
|
|
|
|
suffix = NULL;
|
2018-03-02 11:46:13 +01:00
|
|
|
|
|
|
|
if (lpNameBuffer && *nSize > len)
|
|
|
|
{
|
2021-05-07 11:54:43 +02:00
|
|
|
lstrcpyW(lpNameBuffer, L"CN=");
|
2018-03-02 11:46:13 +01:00
|
|
|
lstrcatW(lpNameBuffer, name);
|
2021-05-07 11:54:43 +02:00
|
|
|
lstrcatW(lpNameBuffer, L",");
|
|
|
|
lstrcatW(lpNameBuffer, L"CN=Computers");
|
2018-03-27 11:06:12 +02:00
|
|
|
if (domainInfo->DnsDomainName.Buffer)
|
2018-03-02 11:46:13 +01:00
|
|
|
{
|
2021-05-07 11:54:43 +02:00
|
|
|
lstrcatW(lpNameBuffer, L",");
|
|
|
|
lstrcatW(lpNameBuffer, L"DC=");
|
2018-03-27 11:06:12 +02:00
|
|
|
lstrcatW(lpNameBuffer, domainInfo->DnsDomainName.Buffer);
|
|
|
|
if (suffix)
|
|
|
|
{
|
2021-05-07 11:54:43 +02:00
|
|
|
lstrcatW(lpNameBuffer, L",");
|
|
|
|
lstrcatW(lpNameBuffer, L"DC=");
|
2018-03-27 11:06:12 +02:00
|
|
|
lstrcatW(lpNameBuffer, suffix);
|
|
|
|
}
|
2018-03-02 11:46:13 +01:00
|
|
|
}
|
|
|
|
status = TRUE;
|
|
|
|
}
|
|
|
|
else /* just requesting length required */
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
status = FALSE;
|
|
|
|
}
|
|
|
|
*nSize = len + 1;
|
|
|
|
break;
|
|
|
|
}
|
2006-08-16 00:54:23 +02:00
|
|
|
case NameDisplay:
|
|
|
|
case NameUniqueId:
|
|
|
|
case NameCanonical:
|
|
|
|
case NameUserPrincipal:
|
|
|
|
case NameCanonicalEx:
|
|
|
|
case NameServicePrincipal:
|
|
|
|
case NameDnsDomain:
|
|
|
|
FIXME("NameFormat %d not implemented\n", NameFormat);
|
|
|
|
SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
|
|
|
|
status = FALSE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
status = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
|
|
|
|
status = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
LsaFreeMemory(domainInfo);
|
|
|
|
LsaClose(policyHandle);
|
|
|
|
|
|
|
|
return status;
|
2004-07-12 21:52:47 +02:00
|
|
|
}
|
|
|
|
|
2016-11-01 11:21:52 +01:00
|
|
|
SECURITY_STATUS WINAPI AddSecurityPackageA(LPSTR name, SECURITY_PACKAGE_OPTIONS *options)
|
|
|
|
{
|
|
|
|
FIXME("(%s %p)\n", debugstr_a(name), options);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
SECURITY_STATUS WINAPI AddSecurityPackageW(LPWSTR name, SECURITY_PACKAGE_OPTIONS *options)
|
|
|
|
{
|
|
|
|
FIXME("(%s %p)\n", debugstr_w(name), options);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
2006-11-12 20:23:28 +01:00
|
|
|
/***********************************************************************
|
|
|
|
* GetUserNameExA (SECUR32.@)
|
|
|
|
*/
|
2005-07-18 11:11:14 +02:00
|
|
|
BOOLEAN WINAPI GetUserNameExA(
|
|
|
|
EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
|
|
|
|
{
|
2009-04-07 10:53:57 +02:00
|
|
|
BOOLEAN rc;
|
|
|
|
LPWSTR bufferW = NULL;
|
|
|
|
ULONG sizeW = *nSize;
|
|
|
|
TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
|
|
|
|
if (lpNameBuffer) {
|
2021-05-07 11:54:44 +02:00
|
|
|
bufferW = malloc(sizeW * sizeof(WCHAR));
|
2009-04-07 10:53:57 +02:00
|
|
|
if (bufferW == NULL) {
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rc = GetUserNameExW(NameFormat, bufferW, &sizeW);
|
|
|
|
if (rc) {
|
|
|
|
ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
|
|
|
|
if (len <= *nSize)
|
|
|
|
{
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
|
|
|
|
*nSize = len - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*nSize = len;
|
|
|
|
rc = FALSE;
|
|
|
|
SetLastError(ERROR_MORE_DATA);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*nSize = sizeW;
|
2021-05-07 11:54:44 +02:00
|
|
|
free(bufferW);
|
2009-04-07 10:53:57 +02:00
|
|
|
return rc;
|
2005-07-18 11:11:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN WINAPI GetUserNameExW(
|
|
|
|
EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
|
|
|
|
{
|
2009-04-07 10:53:57 +02:00
|
|
|
TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
|
|
|
|
|
|
|
|
switch (NameFormat)
|
|
|
|
{
|
|
|
|
case NameSamCompatible:
|
|
|
|
{
|
2014-01-13 11:07:31 +01:00
|
|
|
WCHAR samname[UNLEN + 1 + MAX_COMPUTERNAME_LENGTH + 1];
|
|
|
|
LPWSTR out;
|
|
|
|
DWORD len;
|
|
|
|
|
2009-04-07 10:53:57 +02:00
|
|
|
/* This assumes the current user is always a local account */
|
|
|
|
len = MAX_COMPUTERNAME_LENGTH + 1;
|
|
|
|
if (GetComputerNameW(samname, &len))
|
|
|
|
{
|
|
|
|
out = samname + lstrlenW(samname);
|
|
|
|
*out++ = '\\';
|
|
|
|
len = UNLEN + 1;
|
|
|
|
if (GetUserNameW(out, &len))
|
|
|
|
{
|
2014-01-13 11:07:31 +01:00
|
|
|
if (lstrlenW(samname) < *nSize)
|
2009-04-07 10:53:57 +02:00
|
|
|
{
|
|
|
|
lstrcpyW(lpNameBuffer, samname);
|
|
|
|
*nSize = lstrlenW(samname);
|
2014-01-13 11:07:31 +01:00
|
|
|
return TRUE;
|
2009-04-07 10:53:57 +02:00
|
|
|
}
|
2014-01-13 11:07:31 +01:00
|
|
|
|
|
|
|
SetLastError(ERROR_MORE_DATA);
|
|
|
|
*nSize = lstrlenW(samname) + 1;
|
2009-04-07 10:53:57 +02:00
|
|
|
}
|
|
|
|
}
|
2014-01-13 11:07:31 +01:00
|
|
|
return FALSE;
|
2009-04-07 10:53:57 +02:00
|
|
|
}
|
2014-01-13 11:07:31 +01:00
|
|
|
|
2009-04-11 20:44:40 +02:00
|
|
|
case NameUnknown:
|
2009-04-07 10:53:57 +02:00
|
|
|
case NameFullyQualifiedDN:
|
|
|
|
case NameDisplay:
|
|
|
|
case NameUniqueId:
|
|
|
|
case NameCanonical:
|
|
|
|
case NameUserPrincipal:
|
|
|
|
case NameCanonicalEx:
|
|
|
|
case NameServicePrincipal:
|
|
|
|
case NameDnsDomain:
|
2009-04-11 20:44:40 +02:00
|
|
|
SetLastError(ERROR_NONE_MAPPED);
|
2014-01-13 11:07:31 +01:00
|
|
|
return FALSE;
|
|
|
|
|
2009-04-07 10:53:57 +02:00
|
|
|
default:
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
2014-01-13 11:07:31 +01:00
|
|
|
return FALSE;
|
2009-04-07 10:53:57 +02:00
|
|
|
}
|
2005-07-18 11:11:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN WINAPI TranslateNameA(
|
|
|
|
LPCSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
|
|
|
|
EXTENDED_NAME_FORMAT DesiredNameFormat, LPSTR lpTranslatedName,
|
|
|
|
PULONG nSize)
|
|
|
|
{
|
|
|
|
FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
|
|
|
|
DesiredNameFormat, lpTranslatedName, nSize);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN WINAPI TranslateNameW(
|
|
|
|
LPCWSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
|
|
|
|
EXTENDED_NAME_FORMAT DesiredNameFormat, LPWSTR lpTranslatedName,
|
|
|
|
PULONG nSize)
|
|
|
|
{
|
|
|
|
FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
|
|
|
|
DesiredNameFormat, lpTranslatedName, nSize);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2004-05-17 23:08:31 +02:00
|
|
|
/***********************************************************************
|
|
|
|
* DllMain (SECUR32.0)
|
|
|
|
*/
|
2013-05-15 10:26:18 +02:00
|
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
2013-05-15 10:26:18 +02:00
|
|
|
switch (reason)
|
2004-03-02 05:57:35 +01:00
|
|
|
{
|
2013-05-15 10:26:18 +02:00
|
|
|
case DLL_PROCESS_ATTACH:
|
2021-05-07 11:54:41 +02:00
|
|
|
hsecur32 = hinstDLL;
|
2004-03-02 05:57:35 +01:00
|
|
|
DisableThreadLibraryCalls(hinstDLL);
|
|
|
|
SECUR32_initializeProviders();
|
2013-05-15 10:26:18 +02:00
|
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
if (reserved) break;
|
2004-03-02 05:57:35 +01:00
|
|
|
SECUR32_freeProviders();
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|