//+------------------------------------------------------------------------- // // Microsoft OLE // Copyright (C) Microsoft Corporation, 1996 - 1997. // // File: ntutil.cpp // // Contents: Utility functions for NTFS drives. // These functions will probably not be // available for Mac, Win9x, so should be // stubbed out in the header file as such. // // Functions: // ConversionVerification // VerifyNssfile // // History: 01/19/98 SCousens Created // //-------------------------------------------------------------------------- #include #pragma hdrstop // Debug Object declaration DH_DECLARE; // Must be at least NT5 (not mac, not win9x, not nt4 etc) #if defined(_WIN32_WINNT) && (_WIN32_WINNT>=0x0500) /*******************************************************************/ /* */ /* WARNING: */ /* ConversionVerification, VerifyNssfile */ /* must be the LAST functions in this file. */ /* We redefine stuff that must not affect the rest */ /* of the functions. */ /* of the functions. */ /* */ /*******************************************************************/ #ifdef _HOOK_STGAPI_ #undef StgCreateDocfile #undef StgOpenStorage #endif /* _HOOK_STGAPI_ */ //+------------------------------------------------------------------------- // Function: ConversionVerification // // Synopsis: Opens a nssfile as docfile and then as nssfile // and calculates CRC each time. If CRC is different // then there is a problem with the conversion driver // // Arguments: [pFileName] - Name of Docfile // [dwCRCexp] - Expected CRC (default=0) // // Returns: S_OK if all went well and CRCs match // or E_FAIL if something else went wrong // (CRCs dont match, ulRef not 0 after Release) // // History: 28-Jan-97 SCousens Created. // // Notes: - NSSFile must previously be closed, or access violations // may occur calculating CRC. //-------------------------------------------------------------------------- HRESULT ConversionVerification (LPTSTR pFileName, DWORD dwCRCexp) { DWORD dwCRCdf = 0, dwCRCnss = 0; IStorage *pIStorage; HRESULT hr = S_OK; ULONG ul; LPOLESTR pOleStrTemp = NULL; DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ConversionVerification")); DH_VDATESTRINGPTR (pFileName); // Convert TCHAR to OLECHAR hr = TStringToOleString(pFileName, &pOleStrTemp); DH_HRCHECK(hr, TEXT("TStringToOleString")) ; // Open as docfile, calc CRC for file and close it. if(S_OK == hr) { hr = StgOpenStorageEx (pOleStrTemp, STGM_READ | STGM_SHARE_EXCLUSIVE, STGFMT_DOCFILE, 0, NULL, NULL, IID_IStorage, (void**)&pIStorage); DH_HRCHECK (hr, TEXT("Cnv:StgOpenStorageEx")); if (S_OK == hr) { hr = CalculateCRCForDocFile(pIStorage, VERIFY_INC_TOPSTG_NAME, &dwCRCdf); DH_HRCHECK (hr, TEXT("CalculateCRCForDocFile")); } if (S_OK != hr || 0 == dwCRCdf) { DH_LOG((LOG_INFO, TEXT("Cnv:CalculateCRCForDocFile on docfile failed, hr=0x%lx.\n"), hr)); } if (NULL != pIStorage) { ul = pIStorage->Release (); DH_ASSERT (0 == ul); pIStorage = NULL; } } // Open normally (as nssfile), calc CRC for the file close it. if (S_OK == hr) { hr = StgOpenStorage (pOleStrTemp, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pIStorage); DH_HRCHECK (hr, TEXT("Cnv:StgOpenStorage")); if (S_OK == hr) { hr = CalculateCRCForDocFile(pIStorage, VERIFY_INC_TOPSTG_NAME, &dwCRCnss); DH_HRCHECK (hr, TEXT("CalculateCRCForDocFile")); } if (S_OK != hr || 0 == dwCRCnss) { DH_LOG((LOG_INFO, TEXT("Cnv:CalculateCRCForDocFile on nssfile failed, hr=0x%lx.\n"), hr)); } if (NULL != pIStorage) { ul = pIStorage->Release (); DH_ASSERT (0 == ul); pIStorage = NULL; } } // spew if (S_OK == hr && dwCRCnss == dwCRCdf && 0 != dwCRCdf && (0 == dwCRCexp || dwCRCexp == dwCRCdf)) { DH_LOG((LOG_INFO, TEXT("Conversion verification passed.\n")) ); } else { hr = (S_OK != hr) ? hr : E_FAIL; //set it only if not already set. DH_LOG((LOG_INFO, TEXT("Conversion verification failed, hr=0x%lx.\n"), hr) ); } if (NULL != pOleStrTemp) { delete pOleStrTemp; pOleStrTemp = NULL; } return hr; } //+------------------------------------------------------------------------- // Function: VerifyNssfile // // Synopsis: Verify an nssfile is indeed an nssfile by checking: // 1. reparse point is set (spew if not) // 2. header is valid (spew if df or unknown, and set hr) // Verify the reparse point is set. // Open the file directly with REPARSE flag (to prevent cnss from // converting it). Read the header and make sure it looks like a // real nssfile by checking the file signatures. // // Arguments: [pszPathname] - full path to the file to be checked // // Returns: S_OK, else some sort of error. // We set the following if file is df or unknown // ERROR_INVALID_DATA - if file is a DOCFILE // 13L - The data is invalid // ERROR_FILE_INVALID - if file is UNKNOWN (not df or nss) // 1006L - The volume for a file has been externally // altered so that the opened file is no longer valid // ERROR_INVALID_EA_NAME - no reparse point (if others valid) // 254L - The specified extended attribute name was invalid. // // History: 24-Jul-97 SCousens Created. // // Notes: - NSSFile must previously be closed, or file share // access violations may occur reading the header. //-------------------------------------------------------------------------- #define NSSFILE_SIGNATURE 0x444D4F30 #define DOCFILE_SIGNATURE1 0xE011CFD0 //0xD0CF11E0 little endian #define DOCFILE_SIGNATURE2 0xE11AB1A1 //0xA1B11AE1 little endian HRESULT VerifyNssfile (LPTSTR pszPathname) { HRESULT hr = S_OK; HANDLE hnd; ULONG culRead; ULONG ulAttr; struct _structFileHeader { ULONG ulSig1; ULONG ulSig2; } sFileHeader; DH_FUNCENTRY (&hr, DH_LVL_DFLIB, TEXT("VerifyNssfile")); /* check the file attributes and look for reparse attribute */ ulAttr = GetFileAttributes (pszPathname); DH_TRACE ((DH_LVL_DFLIB, TEXT("VerifyNssfile; Attributes retrieved:%#lx"), ulAttr)); if ((ULONG)-1 == ulAttr) { DH_TRACE ((DH_LVL_ERROR, TEXT("VerifyNssfile; Unable to get attributes for %s"), pszPathname)); hr = HRESULT_FROM_WIN32(GetLastError()); DH_HRCHECK (hr, TEXT("GetFileAttributes")); return hr; } /* attempt to open the file */ hnd = CreateFile(pszPathname, GENERIC_READ, FILE_SHARE_READ, NULL, // security descriptor OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT, NULL); //hTemplateFile if (INVALID_HANDLE_VALUE == hnd) { hr = HRESULT_FROM_WIN32(GetLastError()); } DH_HRCHECK (hr, TEXT("CreateFile")); /* if we succeeded, read the header */ if (S_OK == hr) { BOOL fErr; fErr = ReadFile (hnd, &sFileHeader, sizeof (sFileHeader), &culRead, NULL); if (FALSE == fErr) { hr = HRESULT_FROM_WIN32(GetLastError()); } DH_HRCHECK (hr, TEXT("ReadFile")); DH_TRACE ((DH_LVL_DFLIB, TEXT("Read %ld bytes from file"), culRead)); } /* check the header looks like an nss header */ if (S_OK == hr) { if (sFileHeader.ulSig1 != NSSFILE_SIGNATURE) { if (sFileHeader.ulSig1 == DOCFILE_SIGNATURE1 && sFileHeader.ulSig2 == DOCFILE_SIGNATURE2) { hr = ERROR_INVALID_DATA; DH_TRACE ((DH_LVL_TRACE1, TEXT("WARNING!!! VerifyNssfile; File appears to be a DOCFILE"))); } else { hr = ERROR_FILE_INVALID; DH_TRACE ((DH_LVL_TRACE1, TEXT("WARNING!!! VerifyNssfile; File is INVALID nssfile or docfile!"))); } } else { DH_TRACE ((DH_LVL_DFLIB, TEXT("VerifyNssfile; File appears to be valid nssfile"))); } } // If nssfile, but no reparse point, its still not valid! // It is impossible to have an nssfile with a reparse // point on an NTFS4 volume. // It is impossible to have an nssfile on a FAT volume. if (0 == (FILE_ATTRIBUTE_REPARSE_POINT & ulAttr)) { DH_TRACE ((DH_LVL_TRACE1, TEXT("WARNING!!! VerifyNssfile; File *NOT* have reparse point set!"))); if (S_OK == hr) { hr = ERROR_INVALID_EA_NAME; } } // close the file if (INVALID_HANDLE_VALUE != hnd) { HRESULT hr2 = S_OK; if (FALSE == CloseHandle(hnd)) { hr2 = HRESULT_FROM_WIN32(GetLastError()); } DH_HRCHECK (hr2, TEXT("CloseHandle")); } // if there is a problem, say what file caused it. if (S_OK != hr) { DH_TRACE ((DH_LVL_TRACE1, TEXT("WARNING!!! File causing problem: %s"), pszPathname)); } return hr; } /*******************************************************************/ /* */ /* WARNING: */ /* ConversionVerification, VerifyNssfile */ /* must be the LAST function in this file. */ /* We redefine stuff that must not affect the rest */ /* of the functions. */ /* */ /*******************************************************************/ #endif // WINNT5+