848 lines
19 KiB
C
848 lines
19 KiB
C
/*++
|
||
|
||
Copyright (c) 1997 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
contain.c
|
||
|
||
Abstract:
|
||
|
||
Container manipulators for the IIS cryptographic package.
|
||
|
||
The following routines are exported by this module:
|
||
|
||
IISCryptoGetStandardContainer
|
||
IISCryptoGetStandardContainer2
|
||
IISCryptoGetContainerByName
|
||
IISCryptoDeleteContainer
|
||
IISCryptoCloseContainer
|
||
|
||
Author:
|
||
|
||
Keith Moore (keithmo) 02-Dec-1996
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
|
||
//
|
||
// Private constants.
|
||
//
|
||
|
||
|
||
//
|
||
// Private types.
|
||
//
|
||
|
||
|
||
//
|
||
// Private globals.
|
||
//
|
||
|
||
|
||
//
|
||
// Private prototypes.
|
||
//
|
||
|
||
HRESULT
|
||
IcpGetContainerHelper(
|
||
OUT HCRYPTPROV * phProv,
|
||
IN LPCTSTR pszContainer,
|
||
IN LPCTSTR pszProvider,
|
||
IN DWORD dwProvType,
|
||
IN DWORD dwAdditionalFlags,
|
||
IN BOOL fApplyAcl
|
||
);
|
||
|
||
|
||
//
|
||
// Public functions.
|
||
//
|
||
|
||
|
||
HRESULT
|
||
WINAPI
|
||
IISCryptoGetStandardContainer(
|
||
OUT HCRYPTPROV * phProv,
|
||
IN DWORD dwAdditionalFlags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine attempts to open the crypto key container. If the
|
||
container does not yet exist, this routine will attempt to create
|
||
it.
|
||
|
||
Arguments:
|
||
|
||
phProv - Receives the provider handle if successful.
|
||
|
||
dwAdditionalFlags - Any additional flags that should be passed to
|
||
the CryptAcquireContext() API. This is typically used by server
|
||
processes that pass in the CRYPT_MACHINE_KEYSET flag.
|
||
|
||
Return Value:
|
||
|
||
HRESULT - Completion status, 0 if successful, !0 otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
HRESULT result;
|
||
|
||
//
|
||
// Sanity check.
|
||
//
|
||
|
||
DBG_ASSERT( IcpGlobals.Initialized );
|
||
DBG_ASSERT( phProv != NULL );
|
||
DBG_ASSERT( ( dwAdditionalFlags & CRYPT_NEWKEYSET ) == 0 );
|
||
DBG_ASSERT( ( dwAdditionalFlags & CRYPT_DELETEKEYSET ) == 0 );
|
||
|
||
//
|
||
// Let IcpGetContainerHelper() do the dirty work.
|
||
//
|
||
|
||
result = IcpGetContainerHelper(
|
||
phProv,
|
||
IC_CONTAINER,
|
||
IC_PROVIDER,
|
||
IC_PROVTYPE,
|
||
dwAdditionalFlags,
|
||
( dwAdditionalFlags & CRYPT_MACHINE_KEYSET ) != 0
|
||
);
|
||
|
||
return result;
|
||
|
||
} // IISCryptoGetStandardContainer
|
||
|
||
HRESULT
|
||
WINAPI
|
||
IISCryptoGetStandardContainer2(
|
||
OUT HCRYPTPROV * phProv
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine attempts to open the crypto key container. If the
|
||
container does not yet exist, this routine will attempt to create
|
||
it.
|
||
|
||
Arguments:
|
||
|
||
phProv - Receives the provider handle if successful.
|
||
|
||
Return Value:
|
||
|
||
HRESULT - Completion status, 0 if successful, !0 otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
HRESULT result;
|
||
|
||
//
|
||
// Sanity check.
|
||
//
|
||
|
||
DBG_ASSERT( IcpGlobals.Initialized );
|
||
DBG_ASSERT( phProv != NULL );
|
||
|
||
//
|
||
// Let IcpGetContainerHelper() do the dirty work.
|
||
//
|
||
|
||
result = IcpGetContainerHelper(
|
||
phProv,
|
||
NULL,
|
||
NULL,
|
||
IC_PROVTYPE,
|
||
CRYPT_VERIFYCONTEXT,
|
||
FALSE
|
||
);
|
||
|
||
return result;
|
||
|
||
} // IISCryptoGetStandardContainer2
|
||
|
||
HRESULT
|
||
WINAPI
|
||
IISCryptoGetContainerByName(
|
||
OUT HCRYPTPROV * phProv,
|
||
IN LPTSTR pszContainerName,
|
||
IN DWORD dwAdditionalFlags,
|
||
IN BOOL fApplyAcl
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine attempts to open a specific named crypto key container.
|
||
If the container does not yet exist, this routine will attempt to
|
||
create it and (optionally) apply an ACL to the container.
|
||
|
||
Arguments:
|
||
|
||
phProv - Receives the provider handle if successful.
|
||
|
||
pszContainerName - The name of the container to open/create.
|
||
NULL means temporary container
|
||
|
||
dwAdditionalFlags - Any additional flags that should be passed to
|
||
the CryptAcquireContext() API. This is typically used by server
|
||
processes that pass in the CRYPT_MACHINE_KEYSET flag.
|
||
|
||
fApplyAcl - If TRUE, then an ACL is applied to the container.
|
||
|
||
Return Value:
|
||
|
||
HRESULT - Completion status, 0 if successful, !0 otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
HRESULT result;
|
||
|
||
//
|
||
// Sanity check.
|
||
//
|
||
|
||
DBG_ASSERT( IcpGlobals.Initialized );
|
||
DBG_ASSERT( phProv != NULL );
|
||
DBG_ASSERT( ( dwAdditionalFlags & CRYPT_NEWKEYSET ) == 0 );
|
||
DBG_ASSERT( ( dwAdditionalFlags & CRYPT_DELETEKEYSET ) == 0 );
|
||
|
||
//
|
||
// Let IcpGetContainerHelper() do the dirty work.
|
||
//
|
||
|
||
result = IcpGetContainerHelper(
|
||
phProv,
|
||
pszContainerName,
|
||
IC_PROVIDER,
|
||
IC_PROVTYPE,
|
||
dwAdditionalFlags,
|
||
fApplyAcl
|
||
);
|
||
|
||
return result;
|
||
|
||
} // IISCryptoGetContainerByName
|
||
|
||
|
||
HRESULT
|
||
WINAPI
|
||
IISCryptoDeleteStandardContainer(
|
||
IN DWORD dwAdditionalFlags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine deletes the standard crypto key container.
|
||
|
||
Arguments:
|
||
|
||
dwAdditionalFlags - Any additional flags that should be passed to
|
||
the CryptAcquireContext() API. This is typically used by server
|
||
processes that pass in the CRYPT_MACHINE_KEYSET flag.
|
||
|
||
Return Value:
|
||
|
||
HRESULT - Completion status, 0 if successful, !0 otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
HRESULT result = NO_ERROR;
|
||
BOOL status;
|
||
HCRYPTPROV cryptProv;
|
||
|
||
//
|
||
// Sanity check.
|
||
//
|
||
|
||
DBG_ASSERT( IcpGlobals.Initialized );
|
||
DBG_ASSERT( ( dwAdditionalFlags & CRYPT_NEWKEYSET ) == 0 );
|
||
DBG_ASSERT( ( dwAdditionalFlags & CRYPT_DELETEKEYSET ) == 0 );
|
||
|
||
//
|
||
// Short-circuit if cryptography is disabled.
|
||
//
|
||
|
||
if( !IcpGlobals.EnableCryptography ) {
|
||
return NO_ERROR;
|
||
}
|
||
|
||
//
|
||
// Delete the container.
|
||
//
|
||
|
||
status = CryptAcquireContext(
|
||
&cryptProv,
|
||
IC_CONTAINER,
|
||
IC_PROVIDER,
|
||
IC_PROVTYPE,
|
||
CRYPT_DELETEKEYSET | dwAdditionalFlags
|
||
);
|
||
|
||
if( !status ) {
|
||
result = IcpGetLastError();
|
||
}
|
||
|
||
return result;
|
||
|
||
} // IISCryptoDeleteStandardContainer
|
||
|
||
|
||
HRESULT
|
||
WINAPI
|
||
IISCryptoDeleteContainerByName(
|
||
IN LPTSTR pszContainerName,
|
||
IN DWORD dwAdditionalFlags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine deletes the specified crypto key container.
|
||
|
||
Arguments:
|
||
|
||
pszContainerName - The name of the container to delete.
|
||
|
||
dwAdditionalFlags - Any additional flags that should be passed to
|
||
the CryptAcquireContext() API. This is typically used by server
|
||
processes that pass in the CRYPT_MACHINE_KEYSET flag.
|
||
|
||
Return Value:
|
||
|
||
HRESULT - Completion status, 0 if successful, !0 otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
HRESULT result = NO_ERROR;
|
||
BOOL status;
|
||
HCRYPTPROV cryptProv;
|
||
|
||
//
|
||
// Sanity check.
|
||
//
|
||
|
||
DBG_ASSERT( IcpGlobals.Initialized );
|
||
DBG_ASSERT( ( dwAdditionalFlags & CRYPT_NEWKEYSET ) == 0 );
|
||
DBG_ASSERT( ( dwAdditionalFlags & CRYPT_DELETEKEYSET ) == 0 );
|
||
|
||
//
|
||
// Short-circuit if cryptography is disabled.
|
||
//
|
||
|
||
if( !IcpGlobals.EnableCryptography ) {
|
||
return NO_ERROR;
|
||
}
|
||
|
||
//
|
||
// Delete the container.
|
||
//
|
||
|
||
status = CryptAcquireContext(
|
||
&cryptProv,
|
||
pszContainerName,
|
||
IC_PROVIDER,
|
||
IC_PROVTYPE,
|
||
CRYPT_DELETEKEYSET | dwAdditionalFlags
|
||
);
|
||
|
||
if( !status ) {
|
||
result = IcpGetLastError();
|
||
}
|
||
|
||
return result;
|
||
|
||
} // IISCryptoDeleteContainerByName
|
||
|
||
|
||
HRESULT
|
||
WINAPI
|
||
IISCryptoCloseContainer(
|
||
IN HCRYPTPROV hProv
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine closes the container associated with the specified
|
||
provider handle.
|
||
|
||
Arguments:
|
||
|
||
hProv - A handle to a crypto service provider.
|
||
|
||
Return Value:
|
||
|
||
HRESULT - Completion status, 0 if successful, !0 otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
BOOL status;
|
||
|
||
//
|
||
// Sanity check.
|
||
//
|
||
|
||
DBG_ASSERT( IcpGlobals.Initialized );
|
||
DBG_ASSERT( hProv != CRYPT_NULL );
|
||
|
||
//
|
||
// Short-circuit if cryptography is disabled.
|
||
//
|
||
|
||
if( !IcpGlobals.EnableCryptography ) {
|
||
if( hProv == DUMMY_HPROV ) {
|
||
return NO_ERROR;
|
||
} else {
|
||
return RETURNCODETOHRESULT( ERROR_INVALID_PARAMETER );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Close the provider.
|
||
//
|
||
|
||
status = CryptReleaseContext(
|
||
hProv,
|
||
0
|
||
);
|
||
|
||
if( status ) {
|
||
|
||
UpdateContainersClosed();
|
||
return NO_ERROR;
|
||
|
||
}
|
||
|
||
return IcpGetLastError();
|
||
|
||
} // IISCryptoCloseContainer
|
||
|
||
|
||
//
|
||
// Private functions.
|
||
//
|
||
|
||
|
||
HRESULT
|
||
IcpGetContainerHelper(
|
||
OUT HCRYPTPROV * phProv,
|
||
IN LPCTSTR pszContainer,
|
||
IN LPCTSTR pszProvider,
|
||
IN DWORD dwProvType,
|
||
IN DWORD dwAdditionalFlags,
|
||
IN BOOL fApplyAcl
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is a helper routine for IISCryptoGetContainer. It tries
|
||
to open/create the specified container in the specified provider.
|
||
|
||
Arguments:
|
||
|
||
phProv - Receives the provider handle if successful.
|
||
|
||
pszContainer - The key container name.
|
||
|
||
pszProvider - The provider name.
|
||
|
||
dwProvType - The type of provider to acquire.
|
||
|
||
dwAdditionalFlags - Any additional flags that should be passed to
|
||
the CryptAcquireContext() API. This is typically used by server
|
||
processes that pass in the CRYPT_MACHINE_KEYSET flag.
|
||
|
||
fApplyAcl - If TRUE, then an ACL is applied to the container.
|
||
|
||
Return Value:
|
||
|
||
HRESULT - Completion status, 0 if successful, !0 otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
HRESULT result = NO_ERROR;
|
||
HCRYPTPROV hProv;
|
||
BOOL status;
|
||
PSID systemSid;
|
||
PSID adminSid;
|
||
PACL dacl;
|
||
DWORD daclSize;
|
||
SECURITY_DESCRIPTOR securityDescriptor;
|
||
SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
|
||
BOOL isNt = FALSE;
|
||
OSVERSIONINFO osInfo;
|
||
|
||
// Sanity check.
|
||
//
|
||
|
||
DBG_ASSERT( IcpGlobals.Initialized );
|
||
DBG_ASSERT( phProv != NULL );
|
||
DBG_ASSERT( ( dwAdditionalFlags & CRYPT_NEWKEYSET ) == 0 );
|
||
DBG_ASSERT( ( dwAdditionalFlags & CRYPT_DELETEKEYSET ) == 0 );
|
||
|
||
//
|
||
// Short-circuit if cryptography is disabled.
|
||
//
|
||
|
||
if( !IcpGlobals.EnableCryptography ) {
|
||
*phProv = DUMMY_HPROV;
|
||
return NO_ERROR;
|
||
}
|
||
|
||
//
|
||
// Setup our locals so we know how to cleanup on exit.
|
||
//
|
||
|
||
hProv = CRYPT_NULL;
|
||
systemSid = NULL;
|
||
adminSid = NULL;
|
||
dacl = NULL;
|
||
|
||
//
|
||
// Grab the lock protecting the container code. This is always
|
||
// necessary to prevent race conditions between this code and
|
||
// the code below that creates the container & adds a security
|
||
// descriptor.
|
||
//
|
||
|
||
IcpAcquireGlobalLock();
|
||
|
||
//
|
||
// Try to open an existing container.
|
||
//
|
||
|
||
if ( pszContainer == NULL )
|
||
{
|
||
//
|
||
// if container is NULL it means that temporary (ephemeral)
|
||
// keys will be used
|
||
// CRYPT_VERIFYCONTEXT must be used in this case
|
||
// keys used for DCOM traffic encryption will be using
|
||
// NULL containers
|
||
//
|
||
|
||
status = CryptAcquireContext(
|
||
&hProv,
|
||
pszContainer,
|
||
pszProvider,
|
||
dwProvType,
|
||
CRYPT_VERIFYCONTEXT
|
||
);
|
||
if( !status )
|
||
{
|
||
result = IcpGetLastError();
|
||
DBGPRINTF(( DBG_CONTEXT,"IcpGetContainerHelper. CryptAcquireContext(advapi32.dll) with CRYPT_VERIFYCONTEXT failed err=0x%x\n",result));
|
||
DBGPRINTF(( DBG_CONTEXT,"args for CryptAcquireContext(%p,%p,%p,%d,%d)\n",&hProv,pszContainer,pszProvider,dwProvType, CRYPT_VERIFYCONTEXT));
|
||
|
||
goto fatal;
|
||
}
|
||
else
|
||
{
|
||
goto success;
|
||
}
|
||
|
||
}
|
||
|
||
status = CryptAcquireContext(
|
||
&hProv,
|
||
pszContainer,
|
||
pszProvider,
|
||
dwProvType,
|
||
0 | dwAdditionalFlags
|
||
);
|
||
|
||
if( !status ) {
|
||
result = IcpGetLastError();
|
||
}
|
||
|
||
if( SUCCEEDED(result) ) {
|
||
|
||
DBG_ASSERT( hProv != CRYPT_NULL );
|
||
*phProv = hProv;
|
||
|
||
IcpReleaseGlobalLock();
|
||
|
||
UpdateContainersOpened();
|
||
return NO_ERROR;
|
||
|
||
}
|
||
|
||
//
|
||
// Could not open the container. If the failure was anything
|
||
// other than NTE_BAD_KEYSET, then we're toast.
|
||
//
|
||
|
||
if( result != NTE_BAD_KEYSET ) {
|
||
DBGPRINTF(( DBG_CONTEXT,"IcpGetContainerHelper. CryptAcquireContext(advapi32.dll) failed err=0x%x.toast.\n",result));
|
||
DBGPRINTF(( DBG_CONTEXT,"args for CryptAcquireContext(%p,%p,%p,%d,%d)\n",&hProv,pszContainer,pszProvider,dwProvType,CRYPT_NEWKEYSET | dwAdditionalFlags));
|
||
hProv = CRYPT_NULL;
|
||
goto fatal;
|
||
}
|
||
|
||
if(result == NTE_BAD_KEYSET)
|
||
{
|
||
DBGPRINTF(( DBG_CONTEXT,"CryptAcquireContext(%p,%p,%p,%d,%d) returned NTE_BAD_KEYSET, so lets create a keyset now...\n",&hProv,pszContainer,pszProvider,dwProvType,0 | dwAdditionalFlags));
|
||
}
|
||
|
||
//
|
||
// OK, CryptAcquireContext() failed with NTE_BAD_KEYSET, meaning
|
||
// that the container does not yet exist, so create it now.
|
||
//
|
||
|
||
status = CryptAcquireContext(
|
||
&hProv,
|
||
pszContainer,
|
||
pszProvider,
|
||
dwProvType,
|
||
CRYPT_NEWKEYSET | dwAdditionalFlags
|
||
);
|
||
|
||
if( status ) {
|
||
result = NO_ERROR;
|
||
} else {
|
||
result = IcpGetLastError();
|
||
}
|
||
|
||
if( FAILED(result) ) {
|
||
DBGPRINTF(( DBG_CONTEXT,"IcpGetContainerHelper. CryptAcquireContext(advapi32.dll) failed err=0x%x.\n",result));
|
||
DBGPRINTF(( DBG_CONTEXT,"args for CryptAcquireContext(%p,%p,%p,%d,%d)\n",&hProv,pszContainer,pszProvider,dwProvType,CRYPT_NEWKEYSET | dwAdditionalFlags));
|
||
hProv = CRYPT_NULL;
|
||
goto fatal;
|
||
}
|
||
|
||
//
|
||
// We've created the container. If requested, then we must create
|
||
// a security descriptor for the container. This security descriptor
|
||
// allows full access to the the container by the local system and
|
||
// the local administrators group. Other login contexts may not
|
||
// access the container.
|
||
//
|
||
// Of course, we only need to do this under NT...
|
||
//
|
||
|
||
|
||
osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
|
||
if ( GetVersionEx( &osInfo ) ) {
|
||
isNt = (osInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
|
||
}
|
||
|
||
if( fApplyAcl && isNt ) {
|
||
|
||
//
|
||
// Initialize the security descriptor.
|
||
//
|
||
|
||
status = InitializeSecurityDescriptor(
|
||
&securityDescriptor,
|
||
SECURITY_DESCRIPTOR_REVISION
|
||
);
|
||
|
||
if( !status ) {
|
||
result = IcpGetLastError();
|
||
goto fatal;
|
||
}
|
||
|
||
//
|
||
// Create the SIDs for the local system and admin group.
|
||
//
|
||
|
||
status = AllocateAndInitializeSid(
|
||
&ntAuthority,
|
||
1,
|
||
SECURITY_LOCAL_SYSTEM_RID,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
&systemSid
|
||
);
|
||
|
||
if( !status ) {
|
||
result = IcpGetLastError();
|
||
goto fatal;
|
||
}
|
||
|
||
status= AllocateAndInitializeSid(
|
||
&ntAuthority,
|
||
2,
|
||
SECURITY_BUILTIN_DOMAIN_RID,
|
||
DOMAIN_ALIAS_RID_ADMINS,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
&adminSid
|
||
);
|
||
|
||
if( !status ) {
|
||
result = IcpGetLastError();
|
||
goto fatal;
|
||
}
|
||
|
||
//
|
||
// Create the DACL containing an access-allowed ACE
|
||
// for the local system and admin SIDs.
|
||
//
|
||
|
||
daclSize = sizeof(ACL)
|
||
+ sizeof(ACCESS_ALLOWED_ACE)
|
||
+ GetLengthSid(adminSid)
|
||
+ sizeof(ACCESS_ALLOWED_ACE)
|
||
+ GetLengthSid(systemSid)
|
||
- sizeof(DWORD);
|
||
|
||
dacl = (PACL)IcpAllocMemory( daclSize );
|
||
|
||
if( dacl == NULL ) {
|
||
result = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
|
||
goto fatal;
|
||
}
|
||
|
||
status = InitializeAcl(
|
||
dacl,
|
||
daclSize,
|
||
ACL_REVISION
|
||
);
|
||
|
||
if( !status ) {
|
||
result = IcpGetLastError();
|
||
goto fatal;
|
||
}
|
||
|
||
status = AddAccessAllowedAce(
|
||
dacl,
|
||
ACL_REVISION,
|
||
KEY_ALL_ACCESS,
|
||
systemSid
|
||
);
|
||
|
||
if( !status ) {
|
||
result = IcpGetLastError();
|
||
goto fatal;
|
||
}
|
||
|
||
status = AddAccessAllowedAce(
|
||
dacl,
|
||
ACL_REVISION,
|
||
KEY_ALL_ACCESS,
|
||
adminSid
|
||
);
|
||
|
||
if( !status ) {
|
||
result = IcpGetLastError();
|
||
goto fatal;
|
||
}
|
||
|
||
//
|
||
// Set the DACL into the security descriptor.
|
||
//
|
||
|
||
status = SetSecurityDescriptorDacl(
|
||
&securityDescriptor,
|
||
TRUE,
|
||
dacl,
|
||
FALSE
|
||
);
|
||
|
||
if( !status ) {
|
||
result = IcpGetLastError();
|
||
goto fatal;
|
||
}
|
||
|
||
//
|
||
// And (finally!) set the security descriptor on the
|
||
// container.
|
||
//
|
||
|
||
status = CryptSetProvParam(
|
||
hProv,
|
||
PP_KEYSET_SEC_DESCR,
|
||
(BYTE *)&securityDescriptor,
|
||
DACL_SECURITY_INFORMATION
|
||
);
|
||
|
||
if( !status ) {
|
||
result = IcpGetLastError();
|
||
goto fatal;
|
||
}
|
||
|
||
}
|
||
|
||
success:
|
||
//
|
||
// Success!
|
||
//
|
||
|
||
DBG_ASSERT( hProv != CRYPT_NULL );
|
||
*phProv = hProv;
|
||
|
||
UpdateContainersOpened();
|
||
result = NO_ERROR;
|
||
|
||
fatal:
|
||
|
||
if( dacl != NULL ) {
|
||
IcpFreeMemory( dacl );
|
||
}
|
||
|
||
if( adminSid != NULL ) {
|
||
FreeSid( adminSid );
|
||
}
|
||
|
||
if( systemSid != NULL ) {
|
||
FreeSid( systemSid );
|
||
}
|
||
|
||
if( hProv != CRYPT_NULL && FAILED(result) ) {
|
||
DBG_REQUIRE( CryptReleaseContext(
|
||
hProv,
|
||
0
|
||
) );
|
||
}
|
||
|
||
IcpReleaseGlobalLock();
|
||
return result;
|
||
|
||
} // IcpGetContainerHelper
|
||
|