//+--------------------------------------------------------------------------- // // Microsoft Windows NT Security // Copyright (C) Microsoft Corporation, 1997 - 1999 // // File: filesp.cpp // // Contents: File Scheme Provider // // History: 08-Aug-97 kirtd Created // 01-Jan-02 philh Changed to internally use UNICODE Urls // //---------------------------------------------------------------------------- #include //+--------------------------------------------------------------------------- // // Function: FileRetrieveEncodedObject // // Synopsis: retrieve encoded object via Win32 File I/O // //---------------------------------------------------------------------------- BOOL WINAPI FileRetrieveEncodedObject ( IN LPCWSTR pwszUrl, IN LPCSTR pszObjectOid, IN DWORD dwRetrievalFlags, IN DWORD dwTimeout, OUT PCRYPT_BLOB_ARRAY pObject, OUT PFN_FREE_ENCODED_OBJECT_FUNC* ppfnFreeObject, OUT LPVOID* ppvFreeContext, IN HCRYPTASYNC hAsyncRetrieve, IN PCRYPT_CREDENTIALS pCredentials, IN PCRYPT_RETRIEVE_AUX_INFO pAuxInfo ) { BOOL fResult; IObjectRetriever* por = NULL; if ( !( dwRetrievalFlags & CRYPT_ASYNC_RETRIEVAL ) ) { por = new CFileSynchronousRetriever; } if ( por == NULL ) { SetLastError( (DWORD) E_OUTOFMEMORY ); return( FALSE ); } fResult = por->RetrieveObjectByUrl( pwszUrl, pszObjectOid, dwRetrievalFlags, dwTimeout, (LPVOID *)pObject, ppfnFreeObject, ppvFreeContext, hAsyncRetrieve, pCredentials, NULL, pAuxInfo ); por->Release(); return( fResult ); } //+--------------------------------------------------------------------------- // // Function: FileFreeEncodedObject // // Synopsis: free encoded object retrieved via FileRetrieveEncodedObject // //---------------------------------------------------------------------------- VOID WINAPI FileFreeEncodedObject ( IN LPCSTR pszObjectOid, IN PCRYPT_BLOB_ARRAY pObject, IN LPVOID pvFreeContext ) { BOOL fFreeBlobs = TRUE; PFILE_BINDINGS pfb = (PFILE_BINDINGS)pvFreeContext; // // If no file bindings were given in the context then this // must be a mapped file so we deal with it as such // if ( pfb != NULL ) { fFreeBlobs = FALSE; FileFreeBindings( pfb ); } FileFreeCryptBlobArray( pObject, fFreeBlobs ); } //+--------------------------------------------------------------------------- // // Function: FileCancelAsyncRetrieval // // Synopsis: cancel asynchronous object retrieval // //---------------------------------------------------------------------------- BOOL WINAPI FileCancelAsyncRetrieval ( IN HCRYPTASYNC hAsyncRetrieve ) { SetLastError( (DWORD) E_NOTIMPL ); return( FALSE ); } //+--------------------------------------------------------------------------- // // Member: CFileSynchronousRetriever::CFileSynchronousRetriever, public // // Synopsis: Constructor // //---------------------------------------------------------------------------- CFileSynchronousRetriever::CFileSynchronousRetriever () { m_cRefs = 1; } //+--------------------------------------------------------------------------- // // Member: CFileSynchronousRetriever::~CFileSynchronousRetriever, public // // Synopsis: Destructor // //---------------------------------------------------------------------------- CFileSynchronousRetriever::~CFileSynchronousRetriever () { } //+--------------------------------------------------------------------------- // // Member: CFileSynchronousRetriever::AddRef, public // // Synopsis: IRefCountedObject::AddRef // //---------------------------------------------------------------------------- VOID CFileSynchronousRetriever::AddRef () { InterlockedIncrement( (LONG *)&m_cRefs ); } //+--------------------------------------------------------------------------- // // Member: CFileSynchronousRetriever::Release, public // // Synopsis: IRefCountedObject::Release // //---------------------------------------------------------------------------- VOID CFileSynchronousRetriever::Release () { if ( InterlockedDecrement( (LONG *)&m_cRefs ) == 0 ) { delete this; } } //+--------------------------------------------------------------------------- // // Member: CFileSynchronousRetriever::RetrieveObjectByUrl, public // // Synopsis: IObjectRetriever::RetrieveObjectByUrl // //---------------------------------------------------------------------------- BOOL CFileSynchronousRetriever::RetrieveObjectByUrl ( LPCWSTR pwszUrl, LPCSTR pszObjectOid, DWORD dwRetrievalFlags, DWORD dwTimeout, LPVOID* ppvObject, PFN_FREE_ENCODED_OBJECT_FUNC* ppfnFreeObject, LPVOID* ppvFreeContext, HCRYPTASYNC hAsyncRetrieve, PCRYPT_CREDENTIALS pCredentials, LPVOID pvVerify, PCRYPT_RETRIEVE_AUX_INFO pAuxInfo ) { BOOL fResult = FALSE; DWORD LastError = 0; PFILE_BINDINGS pfb = NULL; LPVOID pvFreeContext = NULL; BOOL fIsUncUrl; assert( hAsyncRetrieve == NULL ); fIsUncUrl = FileIsUncUrl( pwszUrl ); if ( ( dwRetrievalFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) && ( fIsUncUrl == TRUE ) ) { return( SchemeRetrieveCachedCryptBlobArray( pwszUrl, dwRetrievalFlags, (PCRYPT_BLOB_ARRAY)ppvObject, ppfnFreeObject, ppvFreeContext, pAuxInfo ) ); } fResult = FileGetBindings( pwszUrl, dwRetrievalFlags, pCredentials, &pfb, pAuxInfo ); if ( fResult == TRUE ) { if ( pfb->fMapped == FALSE ) { fResult = FileSendReceiveUrlRequest( pfb, (PCRYPT_BLOB_ARRAY)ppvObject ); LastError = GetLastError(); FileFreeBindings( pfb ); } else { fResult = FileConvertMappedBindings( pfb, (PCRYPT_BLOB_ARRAY)ppvObject ); if ( fResult == TRUE ) { pvFreeContext = (LPVOID)pfb; } else { LastError = GetLastError(); FileFreeBindings( pfb ); } } } if ( fResult == TRUE ) { if ( !( dwRetrievalFlags & CRYPT_DONT_CACHE_RESULT ) && ( fIsUncUrl == TRUE ) ) { fResult = SchemeCacheCryptBlobArray( pwszUrl, dwRetrievalFlags, (PCRYPT_BLOB_ARRAY)ppvObject, pAuxInfo ); if ( fResult == FALSE ) { FileFreeEncodedObject( pszObjectOid, (PCRYPT_BLOB_ARRAY)ppvObject, pvFreeContext ); } } else { SchemeRetrieveUncachedAuxInfo( pAuxInfo ); } } if ( fResult == TRUE ) { *ppfnFreeObject = FileFreeEncodedObject; *ppvFreeContext = pvFreeContext; } if ( LastError != 0 ) { SetLastError( LastError ); } return( fResult ); } //+--------------------------------------------------------------------------- // // Member: CInetSynchronousRetriever::CancelAsyncRetrieval, public // // Synopsis: IObjectRetriever::CancelAsyncRetrieval // //---------------------------------------------------------------------------- BOOL CFileSynchronousRetriever::CancelAsyncRetrieval () { SetLastError( (DWORD) E_NOTIMPL ); return( FALSE ); } //+--------------------------------------------------------------------------- // // Function: FileGetBindings // // Synopsis: get the file bindings // //---------------------------------------------------------------------------- BOOL FileGetBindings ( LPCWSTR pwszUrl, DWORD dwRetrievalFlags, PCRYPT_CREDENTIALS pCredentials, PFILE_BINDINGS* ppfb, PCRYPT_RETRIEVE_AUX_INFO pAuxInfo ) { DWORD LastError; LPWSTR pwszFile = (LPWSTR)pwszUrl; HANDLE hFile; HANDLE hFileMap; LPVOID pvMap = NULL; DWORD dwSize; PFILE_BINDINGS pfb; BOOL fResult; WIN32_FILE_ATTRIBUTE_DATA FileAttr; DWORD dwMaxUrlRetrievalByteCount = 0; // 0 => no max if (pAuxInfo && offsetof(CRYPT_RETRIEVE_AUX_INFO, dwMaxUrlRetrievalByteCount) < pAuxInfo->cbSize) dwMaxUrlRetrievalByteCount = pAuxInfo->dwMaxUrlRetrievalByteCount; if ( pCredentials != NULL ) { SetLastError( (DWORD) E_NOTIMPL ); return( FALSE ); } if ( wcsstr( pwszUrl, FILE_SCHEME_PLUSPLUS ) != NULL ) { pwszFile += wcslen( FILE_SCHEME_PLUSPLUS ); } fResult = GetFileAttributesExW( pwszFile, GetFileExInfoStandard, &FileAttr ); if (!fResult) { return(FALSE); } dwSize = FileAttr.nFileSizeLow; if ((FileAttr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || (0 != FileAttr.nFileSizeHigh) || (0 == dwSize) || ((0 != dwMaxUrlRetrievalByteCount) && (dwSize > dwMaxUrlRetrievalByteCount))) { I_CryptNetDebugErrorPrintfA( "CRYPTNET.DLL --> Invalid File(%S):: Attributes: 0x%x Size: %d\n", pwszFile, FileAttr.dwFileAttributes, FileAttr.nFileSizeLow); SetLastError(ERROR_INVALID_DATA); return FALSE; } pfb = new FILE_BINDINGS; if ( pfb == NULL ) { SetLastError( (DWORD) E_OUTOFMEMORY ); return( FALSE ); } hFile = CreateFileW( pwszFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); if ( hFile == INVALID_HANDLE_VALUE ) { delete pfb; return( FALSE ); } if ( dwSize <= FILE_MAPPING_THRESHOLD ) { pfb->hFile = hFile; pfb->dwSize = dwSize; pfb->fMapped = FALSE; pfb->hFileMap = NULL; pfb->pvMap = NULL; *ppfb = pfb; return( TRUE ); } hFileMap = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL ); if ( hFileMap != NULL ) { pvMap = MapViewOfFile( hFileMap, FILE_MAP_READ, 0, 0, 0 ); } if ( pvMap != NULL ) { pfb->hFile = hFile; pfb->dwSize = dwSize; pfb->fMapped = TRUE; pfb->hFileMap = hFileMap; pfb->pvMap = pvMap; *ppfb = pfb; return( TRUE ); } LastError = GetLastError(); if ( hFileMap != NULL ) { CloseHandle( hFileMap ); } if ( hFile != INVALID_HANDLE_VALUE ) { CloseHandle( hFile ); } delete pfb; SetLastError( LastError ); return( FALSE ); } //+--------------------------------------------------------------------------- // // Function: FileFreeBindings // // Synopsis: free the file bindings // //---------------------------------------------------------------------------- VOID FileFreeBindings ( PFILE_BINDINGS pfb ) { if ( pfb->fMapped == TRUE ) { UnmapViewOfFile( pfb->pvMap ); CloseHandle( pfb->hFileMap ); } CloseHandle( pfb->hFile ); delete pfb; } //+--------------------------------------------------------------------------- // // Function: FileSendReceiveUrlRequest // // Synopsis: synchronously process the request for the file bits using // Win32 File API. Note that this only works for non-mapped // file bindings, for mapped file bindings use // FileConvertMappedBindings // //---------------------------------------------------------------------------- BOOL FileSendReceiveUrlRequest ( PFILE_BINDINGS pfb, PCRYPT_BLOB_ARRAY pcba ) { BOOL fResult; LPBYTE pb; DWORD dwRead; assert( pfb->fMapped == FALSE ); pb = CCryptBlobArray::AllocBlob( pfb->dwSize ); if ( pb == NULL ) { SetLastError( (DWORD) E_OUTOFMEMORY ); return( FALSE ); } fResult = ReadFile( pfb->hFile, pb, pfb->dwSize, &dwRead, NULL ); if ( fResult == TRUE ) { CCryptBlobArray cba( 1, 1, fResult ); if ( dwRead == pfb->dwSize ) { fResult = cba.AddBlob( pfb->dwSize, pb, FALSE ); } else { SetLastError( (DWORD) E_FAIL ); fResult = FALSE; } if ( fResult == TRUE ) { cba.GetArrayInNativeForm( pcba ); } else { cba.FreeArray( FALSE ); } } if ( fResult == FALSE ) { CCryptBlobArray::FreeBlob( pb ); } return( fResult ); } //+--------------------------------------------------------------------------- // // Function: FileConvertMappedBindings // // Synopsis: convert mapped bindings to a CRYPT_BLOB_ARRAY // //---------------------------------------------------------------------------- BOOL FileConvertMappedBindings ( PFILE_BINDINGS pfb, PCRYPT_BLOB_ARRAY pcba ) { BOOL fResult; assert( pfb->fMapped == TRUE ); CCryptBlobArray cba( 1, 1, fResult ); if ( fResult == TRUE ) { fResult = cba.AddBlob( pfb->dwSize, (LPBYTE)pfb->pvMap, FALSE ); } if ( fResult == TRUE ) { cba.GetArrayInNativeForm( pcba ); } else { cba.FreeArray( FALSE ); } return( fResult ); } //+--------------------------------------------------------------------------- // // Function: FileFreeCryptBlobArray // // Synopsis: free the CRYPT_BLOB_ARRAY // //---------------------------------------------------------------------------- VOID FileFreeCryptBlobArray ( PCRYPT_BLOB_ARRAY pcba, BOOL fFreeBlobs ) { CCryptBlobArray cba( pcba, 0 ); cba.FreeArray( fFreeBlobs ); } //+--------------------------------------------------------------------------- // // Function: FileIsUncUrl // // Synopsis: is this a UNC path URL? // //---------------------------------------------------------------------------- BOOL FileIsUncUrl ( LPCWSTR pwszUrl ) { DWORD cch = 0; if ( wcsstr( pwszUrl, FILE_SCHEME_PLUSPLUS ) != NULL ) { cch += wcslen( FILE_SCHEME_PLUSPLUS ); } if ( ( pwszUrl[ cch ] == L'\\' ) && ( pwszUrl[ cch + 1 ] == L'\\' ) ) { return( TRUE ); } return( FALSE ); }