You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
11 KiB
324 lines
11 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// 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 <dfheader.hxx>
|
|
#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+
|