//+--------------------------------------------------------------------------- // // Microsoft Windows NT Security // Copyright (C) Microsoft Corporation, 1997 - 1999 // // File: cba.cpp // // Contents: Implementation of CCryptBlobArray // // History: 23-Jul-97 kirtd Created // //---------------------------------------------------------------------------- #include //+--------------------------------------------------------------------------- // // Member: CCryptBlobArray::CCryptBlobArray, public // // Synopsis: Initialize the internal CRYPT_BLOB_ARRAY // //---------------------------------------------------------------------------- CCryptBlobArray::CCryptBlobArray ( ULONG cMinBlobs, ULONG cGrowBlobs, BOOL& rfResult ) { rfResult = TRUE; m_cGrowBlobs = cGrowBlobs; m_cba.cBlob = 0; m_cba.rgBlob = new CRYPT_DATA_BLOB [cMinBlobs]; if ( m_cba.rgBlob != NULL ) { memset( m_cba.rgBlob, 0, sizeof(CRYPT_DATA_BLOB)*cMinBlobs ); m_cArray = cMinBlobs; } else { SetLastError( (DWORD) E_OUTOFMEMORY ); rfResult = FALSE; } } //+--------------------------------------------------------------------------- // // Member: CCryptBlobArray::CCryptBlobArray, public // // Synopsis: Initialize the internal CRYPT_BLOB_ARRAY with a native form // blob array created via ::GetArrayInNativeForm // //---------------------------------------------------------------------------- CCryptBlobArray::CCryptBlobArray ( PCRYPT_BLOB_ARRAY pcba, ULONG cGrowBlobs ) { m_cGrowBlobs = cGrowBlobs; m_cba.cBlob = pcba->cBlob; m_cba.rgBlob = pcba->rgBlob; m_cArray = pcba->cBlob; } //+--------------------------------------------------------------------------- // // Member: CCryptBlobArray::AllocBlob, public, static // // Synopsis: allocate a blob using the same allocator used for ::AddBlob // copies. This means that the resulting blob can be added // without copying. // //---------------------------------------------------------------------------- LPBYTE CCryptBlobArray::AllocBlob (ULONG cb) { return( (LPBYTE)CryptMemAlloc( cb ) ); } //+--------------------------------------------------------------------------- // // Member: CCryptBlobArray::ReallocBlob, public, static // // Synopsis: see ::AllocBlob // //---------------------------------------------------------------------------- LPBYTE CCryptBlobArray::ReallocBlob (LPBYTE pb, ULONG cb) { return( (LPBYTE)CryptMemRealloc( pb, cb ) ); } //+--------------------------------------------------------------------------- // // Member: CCryptBlobArray::FreeBlob, public // // Synopsis: free blob allocated using ::AllocBlob or ::ReallocBlob // //---------------------------------------------------------------------------- VOID CCryptBlobArray::FreeBlob (LPBYTE pb) { CryptMemFree( pb ); } //+--------------------------------------------------------------------------- // // Member: CCryptBlobArray::AddBlob, public // // Synopsis: add a blob // //---------------------------------------------------------------------------- BOOL CCryptBlobArray::AddBlob ( ULONG cb, LPBYTE pb, BOOL fCopyBlob ) { BOOL fResult = TRUE; LPBYTE pbToUse; // // If we need to copy the blob, do so // if ( fCopyBlob == TRUE ) { pbToUse = AllocBlob( cb ); if ( pbToUse != NULL ) { memcpy( pbToUse, pb, cb ); } else { SetLastError( (DWORD) E_OUTOFMEMORY ); return( FALSE ); } } else { pbToUse = pb; } // // If we need to grow the array, do so // if ( m_cArray == m_cba.cBlob ) { fResult = GrowArray(); } // // Add the blob to the array // if ( fResult == TRUE ) { m_cba.rgBlob[m_cba.cBlob].cbData = cb; m_cba.rgBlob[m_cba.cBlob].pbData = pbToUse; m_cba.cBlob += 1; } else if ( fCopyBlob == TRUE ) { FreeBlob( pbToUse ); } return( fResult ); } //+--------------------------------------------------------------------------- // // Member: CCryptBlobArray::GetBlob, public // // Synopsis: gets blob given an index // //---------------------------------------------------------------------------- PCRYPT_DATA_BLOB CCryptBlobArray::GetBlob (ULONG index) { assert( m_cba.cBlob > index ); return( &m_cba.rgBlob[index] ); } //+--------------------------------------------------------------------------- // // Member: CCryptBlobArray::GetBlobCount, public // // Synopsis: get the count of blobs // //---------------------------------------------------------------------------- ULONG CCryptBlobArray::GetBlobCount () { return( m_cba.cBlob ); } //+--------------------------------------------------------------------------- // // Member: CCryptBlobArray::GetArrayInNativeForm, public // // Synopsis: get the array in native form // //---------------------------------------------------------------------------- VOID CCryptBlobArray::GetArrayInNativeForm (PCRYPT_BLOB_ARRAY pcba) { pcba->cBlob = m_cba.cBlob; pcba->rgBlob = m_cba.rgBlob; } //+--------------------------------------------------------------------------- // // Member: CCryptBlobArray::GetArrayInSingleBufferEncodedForm, public // // Synopsis: gets the array in a single buffer encoded form // //---------------------------------------------------------------------------- BOOL CCryptBlobArray::GetArrayInSingleBufferEncodedForm ( PCRYPT_BLOB_ARRAY* ppcba, ULONG* pcb ) { ULONG cbStruct; ULONG cbPointers; ULONG cbData; ULONG cb; ULONG cbSize; ULONG cCount; PCRYPT_BLOB_ARRAY pcba = NULL; // // Calculate the buffer size we will need and allocate it // cbStruct = sizeof( CRYPT_BLOB_ARRAY ); cbPointers = m_cba.cBlob * sizeof( CRYPT_DATA_BLOB ); for ( cCount = 0, cbData = 0; cCount < m_cba.cBlob; cCount++ ) { cbData += m_cba.rgBlob[cCount].cbData; } cbSize = cbStruct + cbPointers + cbData; pcba = (PCRYPT_BLOB_ARRAY)CryptMemAlloc( cbSize ); if ( pcba == NULL ) { SetLastError( (DWORD) E_OUTOFMEMORY ); return( FALSE ); } // // Fill in the data // pcba->cBlob = m_cba.cBlob; pcba->rgBlob = (PCRYPT_DATA_BLOB)((LPBYTE)pcba+cbStruct); __try { for ( cCount = 0, cb = 0; cCount < m_cba.cBlob; cCount++ ) { pcba->rgBlob[cCount].cbData = m_cba.rgBlob[cCount].cbData; pcba->rgBlob[cCount].pbData = (LPBYTE)pcba+cbStruct+cbPointers+cb; memcpy( pcba->rgBlob[cCount].pbData, m_cba.rgBlob[cCount].pbData, m_cba.rgBlob[cCount].cbData ); cb += m_cba.rgBlob[cCount].cbData; } } __except( EXCEPTION_EXECUTE_HANDLER ) { CryptMemFree( pcba ); SetLastError( GetExceptionCode() ); return( FALSE ); } *ppcba = pcba; if ( pcb != NULL ) { *pcb = cbSize; } return( TRUE ); } //+--------------------------------------------------------------------------- // // Member: CCryptBlobArray::FreeArray, public // // Synopsis: frees the array and optionally frees the blobs // //---------------------------------------------------------------------------- VOID CCryptBlobArray::FreeArray (BOOL fFreeBlobs) { if ( fFreeBlobs == TRUE ) { ULONG cCount; for ( cCount = 0; cCount < m_cba.cBlob; cCount++ ) { FreeBlob( m_cba.rgBlob[cCount].pbData ); } } delete m_cba.rgBlob; } //+--------------------------------------------------------------------------- // // Member: CCryptBlobArray::GrowArray, private // // Synopsis: grows the array // //---------------------------------------------------------------------------- BOOL CCryptBlobArray::GrowArray () { ULONG cNewArray; PCRYPT_DATA_BLOB pcba; // // Check if we are allowed to grow // // if ( m_cGrowBlobs == 0 ) { SetLastError( (DWORD) E_INVALIDARG ); return( FALSE ); } // // Allocate and initialize the new array // cNewArray = m_cArray + m_cGrowBlobs; pcba = new CRYPT_DATA_BLOB [cNewArray]; if ( pcba == NULL ) { SetLastError( (DWORD) E_OUTOFMEMORY ); return( FALSE ); } memset(pcba, 0, cNewArray*sizeof( CRYPT_DATA_BLOB )); // // Copy the old to the new // memcpy(pcba, m_cba.rgBlob, m_cba.cBlob*sizeof( CRYPT_DATA_BLOB ) ); // // Free the old and use the new // delete m_cba.rgBlob; m_cba.rgBlob = pcba; m_cArray = cNewArray; return( TRUE ); }