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.
578 lines
15 KiB
578 lines
15 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1998,1999 Microsoft Corporation
|
|
//
|
|
// File: ntfs.h
|
|
//
|
|
// Contents: Header file for NTFS-base message class
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#ifndef __NTFS_H_
|
|
#define __NTFS_H_
|
|
|
|
#include "resource.h" // main symbols
|
|
#include "listmacr.h"
|
|
#include "evntwrap.h"
|
|
#include "perf.h"
|
|
|
|
|
|
//
|
|
// Class IDs
|
|
//
|
|
EXTERN_C const CLSID CLSID_NtfsStoreDriver;
|
|
EXTERN_C const CLSID CLSID_NtfsEnumMessages;
|
|
EXTERN_C const CLSID CLSID_NtfsPropertyStream;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDriverUtils
|
|
|
|
class CDriverUtils
|
|
{
|
|
public:
|
|
CDriverUtils();
|
|
~CDriverUtils();
|
|
|
|
static HRESULT LoadStoreDirectory(
|
|
DWORD dwInstanceId,
|
|
LPTSTR szStoreDirectory,
|
|
DWORD *pdwLength
|
|
);
|
|
|
|
static HRESULT GetStoreFileName(
|
|
LPTSTR szStoreDirectory,
|
|
LPTSTR szStoreFilename,
|
|
DWORD *pdwLength
|
|
);
|
|
|
|
static HRESULT GetStoreFileFromPath(
|
|
LPTSTR szStoreFilename,
|
|
IMailMsgPropertyStream **ppStream,
|
|
PFIO_CONTEXT *phContentFile,
|
|
BOOL fCreate,
|
|
BOOL fIsFAT,
|
|
IMailMsgProperties *pMsg,
|
|
GUID guidInstance = GUID_NULL
|
|
);
|
|
|
|
static HRESULT SetMessageContext(
|
|
IMailMsgProperties *pMsg,
|
|
LPBYTE pbContext,
|
|
DWORD dwLength
|
|
);
|
|
|
|
static HRESULT GetMessageContext(
|
|
IMailMsgProperties *pMsg,
|
|
LPBYTE pbContext,
|
|
DWORD *pdwLength
|
|
);
|
|
|
|
static HRESULT IsStoreDirectoryFat(
|
|
LPTSTR szStoreDirectory,
|
|
BOOL *pfIsFAT
|
|
);
|
|
|
|
#if 0
|
|
static HANDLE CreateFileCallback(
|
|
LPSTR szFilename,
|
|
LPVOID lpvData,
|
|
DWORD *pdwSize,
|
|
DWORD *pdwSizeHigh
|
|
);
|
|
#endif
|
|
|
|
private:
|
|
static DWORD s_dwCounter;
|
|
};
|
|
|
|
typedef struct {
|
|
DWORD dwSignature;
|
|
DWORD dwVersion;
|
|
GUID guidInstance;
|
|
} NTFS_STREAM_HEADER;
|
|
|
|
#define STREAM_OFFSET sizeof(NTFS_STREAM_HEADER)
|
|
#define STREAM_SIGNATURE 'rvDN'
|
|
#define STREAM_SIGNATURE_INVALID 'rvD!'
|
|
#define STREAM_SIGNATURE_PRECOMMIT 'rvDp'
|
|
#define STREAM_SIGNATURE_NOOFFSET 'MMCv'
|
|
|
|
//
|
|
// These are internal status codes used by CNtfsStoreDriver::SetHandle
|
|
// to report on the status of the current stream
|
|
//
|
|
// They aren't errors because SetHandle does actually load the stream.
|
|
// they are hints to the caller telling them that mailmsg won't be
|
|
// able to parse the stream.
|
|
//
|
|
#define FACILITY_NTFSDRV 0x6b1
|
|
#define NTFSDRV_S_HRESULT(_x_) \
|
|
MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NTFSDRV, (_x_))
|
|
#define S_NO_FIRST_COMMIT NTFSDRV_S_HRESULT(1)
|
|
#define S_INVALIDSTREAM NTFSDRV_S_HRESULT(2)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CNtfsStoreDriver
|
|
|
|
class ATL_NO_VTABLE CNtfsStoreDriver :
|
|
public IMailMsgStoreDriver,
|
|
public ISMTPStoreDriver,
|
|
public IEventIsCacheable,
|
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
|
public CComCoClass<CNtfsStoreDriver, &CLSID_NtfsStoreDriver>,
|
|
public IMailMsgStoreDriverValidateContext
|
|
{
|
|
public:
|
|
CNtfsStoreDriver();
|
|
~CNtfsStoreDriver();
|
|
|
|
LONG AddUsage()
|
|
{ return(InterlockedIncrement(&m_lRefCount)); }
|
|
|
|
LONG ReleaseUsage()
|
|
{ return(InterlockedDecrement(&m_lRefCount)); }
|
|
|
|
DWORD GetInstance()
|
|
{ return(m_dwInstance); }
|
|
|
|
BOOL IsShuttingDown()
|
|
{ return(m_fIsShuttingDown); }
|
|
|
|
/***************************************************************************/
|
|
//
|
|
// Implementation of IUnknown
|
|
//
|
|
|
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
|
REFIID iid,
|
|
void **ppvObject
|
|
);
|
|
|
|
ULONG STDMETHODCALLTYPE AddRef();
|
|
|
|
ULONG STDMETHODCALLTYPE Release();
|
|
|
|
/***************************************************************************/
|
|
//
|
|
// IMailMsgStoreDriver
|
|
//
|
|
HRESULT STDMETHODCALLTYPE AllocMessage(
|
|
IMailMsgProperties *pMsg,
|
|
DWORD dwFlags,
|
|
IMailMsgPropertyStream **ppStream,
|
|
PFIO_CONTEXT *phContentFile,
|
|
IMailMsgNotify *pNotify
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE EnumMessages(
|
|
IMailMsgEnumMessages **ppEnum
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE ReOpen(
|
|
IMailMsgProperties *pMsg,
|
|
IMailMsgPropertyStream **ppStream,
|
|
PFIO_CONTEXT *phContentFile,
|
|
IMailMsgNotify *pNotify
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE Delete(
|
|
IMailMsgProperties *pMsg,
|
|
IMailMsgNotify *pNotify
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE CloseContentFile(
|
|
IMailMsgProperties *pMsg,
|
|
PFIO_CONTEXT hContentFile
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE ReAllocMessage(
|
|
IMailMsgProperties *pOriginalMsg,
|
|
IMailMsgProperties *pNewMsg,
|
|
IMailMsgPropertyStream **ppStream,
|
|
PFIO_CONTEXT *phContentFile,
|
|
IMailMsgNotify *pNotify
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE SupportWriteContent() { return S_OK; }
|
|
|
|
/***************************************************************************/
|
|
//
|
|
// ISMTPStoreDriver
|
|
//
|
|
HRESULT STDMETHODCALLTYPE Init(
|
|
DWORD dwInstance,
|
|
IUnknown *pBinding,
|
|
IUnknown *pServer,
|
|
DWORD dwReason,
|
|
IUnknown **ppStoreDriver
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE PrepareForShutdown(
|
|
DWORD dwReason
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE Shutdown(
|
|
DWORD dwReason
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE LocalDelivery(
|
|
IMailMsgProperties *pMsg,
|
|
DWORD dwRecipCount,
|
|
DWORD *pdwRecipIndexes,
|
|
IMailMsgNotify *pNotify
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE EnumerateAndSubmitMessages(
|
|
IMailMsgNotify *pNotify
|
|
);
|
|
|
|
//
|
|
// IEventIsCahceable
|
|
//
|
|
HRESULT STDMETHODCALLTYPE IsCacheable();
|
|
|
|
//
|
|
// IMailMsgStoreDriverValidateContext
|
|
//
|
|
HRESULT STDMETHODCALLTYPE ValidateMessageContext(
|
|
BYTE *pbContext,
|
|
DWORD cbContext);
|
|
|
|
DECLARE_REGISTRY_RESOURCEID(IDR_NTFSDRV)
|
|
|
|
BEGIN_COM_MAP(CNtfsStoreDriver)
|
|
COM_INTERFACE_ENTRY(IMailMsgStoreDriver)
|
|
COM_INTERFACE_ENTRY(ISMTPStoreDriver)
|
|
COM_INTERFACE_ENTRY(IEventIsCacheable)
|
|
COM_INTERFACE_ENTRY(IMailMsgStoreDriverValidateContext)
|
|
END_COM_MAP()
|
|
|
|
GUID GetInstanceGuid() { return m_guidInstance; }
|
|
|
|
BOOL IsFAT() { return m_fIsFAT; }
|
|
|
|
private:
|
|
|
|
LONG m_lRefCount;
|
|
|
|
DWORD m_dwInstance;
|
|
|
|
TCHAR m_szQueueDirectory[MAX_PATH * 2];
|
|
BOOL m_fInitialized;
|
|
BOOL m_fIsShuttingDown;
|
|
ISMTPServer *m_pSMTPServer;
|
|
|
|
// Reference count
|
|
LONG m_ulRefCount;
|
|
|
|
BOOL m_fIsFAT;
|
|
|
|
// our instance guid
|
|
GUID m_guidInstance;
|
|
|
|
public:
|
|
|
|
//Use list entry to maintain the list to keep track of current
|
|
//instances of sink of this type
|
|
LIST_ENTRY m_InstLEntry;
|
|
|
|
public:
|
|
//Global array of instances
|
|
static DWORD sm_cCurrentInstances;
|
|
static CRITICAL_SECTION sm_csLockInstList;
|
|
static LIST_ENTRY sm_ListHead;
|
|
|
|
//for controlling the retry queue
|
|
static void LockList () {EnterCriticalSection (&CNtfsStoreDriver::sm_csLockInstList);}
|
|
static void UnLockList() {LeaveCriticalSection (&CNtfsStoreDriver::sm_csLockInstList);}
|
|
|
|
//Lookup and insert into array
|
|
static IUnknown * LookupSinkInstance(DWORD dwVirtualServerId, REFIID iidBinding)
|
|
{
|
|
PLIST_ENTRY pCurrentListEntry;
|
|
CNtfsStoreDriver * pStoreInstance = NULL;
|
|
|
|
//Initialize
|
|
pCurrentListEntry = &sm_ListHead;
|
|
|
|
//Look at the next entry to see if we are not at the end of the queue
|
|
while(pCurrentListEntry->Flink != &sm_ListHead)
|
|
{
|
|
//Get the object pointed by the next entry
|
|
pStoreInstance = CONTAINING_RECORD( pCurrentListEntry->Flink, CNtfsStoreDriver, m_InstLEntry);
|
|
|
|
//If the entry has same virtual server id we are done
|
|
//NK** : check binding too in MM3 timeframe
|
|
if(dwVirtualServerId == pStoreInstance->m_dwInstance)
|
|
{
|
|
return (IUnknown *)(ISMTPStoreDriver *)pStoreInstance;
|
|
}
|
|
|
|
pCurrentListEntry = pCurrentListEntry->Flink;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static HRESULT InsertSinkInstance(PLIST_ENTRY pListEntry)
|
|
{
|
|
CNtfsStoreDriver::sm_cCurrentInstances++;
|
|
//insert at the start of the list
|
|
InsertHeadList(&sm_ListHead, pListEntry);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT RemoveSinkInstance(IUnknown * pISinkInstance)
|
|
{
|
|
PLIST_ENTRY pCurrentListEntry;
|
|
CNtfsStoreDriver * pStoreInstance = NULL;
|
|
|
|
//Initialize
|
|
pCurrentListEntry = &sm_ListHead;
|
|
|
|
//Look at the next entry to see if we are not at the end of the queue
|
|
while(pCurrentListEntry->Flink != &sm_ListHead)
|
|
{
|
|
//Get the object pointed by the next entry
|
|
pStoreInstance = CONTAINING_RECORD( pCurrentListEntry->Flink, CNtfsStoreDriver, m_InstLEntry);
|
|
|
|
//If the entry has same instance pointer we are done
|
|
//check binding too in MM3 timeframe
|
|
if(pISinkInstance == (IUnknown *)(ISMTPStoreDriver *)pStoreInstance)
|
|
{
|
|
RemoveEntryList(pCurrentListEntry->Flink);
|
|
CNtfsStoreDriver::sm_cCurrentInstances--;
|
|
pStoreInstance->m_InstLEntry.Flink = NULL;
|
|
pStoreInstance->m_InstLEntry.Blink = NULL;
|
|
return S_OK;
|
|
}
|
|
|
|
pCurrentListEntry = pCurrentListEntry->Flink;
|
|
}
|
|
|
|
return(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
}
|
|
|
|
public:
|
|
PerfObjectInstance *m_ppoi;
|
|
static CEventLogWrapper *g_pEventLog;
|
|
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CNtfsStoreDriver
|
|
|
|
class ATL_NO_VTABLE CNtfsEnumMessages :
|
|
public IMailMsgEnumMessages,
|
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
|
public CComCoClass<CNtfsEnumMessages, &CLSID_NtfsEnumMessages>
|
|
{
|
|
public:
|
|
CNtfsEnumMessages();
|
|
~CNtfsEnumMessages();
|
|
|
|
HRESULT SetStoreDirectory(
|
|
LPTSTR szStoreDirectory,
|
|
BOOL fIsFAT
|
|
);
|
|
|
|
HRESULT SetInfo(
|
|
CNtfsStoreDriver *pDriver
|
|
)
|
|
{
|
|
_ASSERT(pDriver);
|
|
m_pDriver = pDriver;
|
|
pDriver->AddUsage();
|
|
return(S_OK);
|
|
}
|
|
|
|
/***************************************************************************/
|
|
//
|
|
// Implementation of IUnknown
|
|
//
|
|
|
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
|
REFIID iid,
|
|
void **ppvObject
|
|
);
|
|
|
|
ULONG STDMETHODCALLTYPE AddRef();
|
|
|
|
ULONG STDMETHODCALLTYPE Release();
|
|
|
|
//
|
|
// IMailMsgEnumMessages
|
|
//
|
|
HRESULT STDMETHODCALLTYPE Next(
|
|
IMailMsgProperties *pMsg,
|
|
IMailMsgPropertyStream **ppStream,
|
|
PFIO_CONTEXT *phContentFile,
|
|
IMailMsgNotify *pNotify
|
|
);
|
|
|
|
DECLARE_REGISTRY_RESOURCEID(IDR_NTFSENUM)
|
|
|
|
BEGIN_COM_MAP(CNtfsEnumMessages)
|
|
COM_INTERFACE_ENTRY(IMailMsgEnumMessages)
|
|
END_COM_MAP()
|
|
|
|
private:
|
|
CNtfsStoreDriver *m_pDriver;
|
|
BOOL m_fIsFAT;
|
|
|
|
TCHAR m_szEnumPath[MAX_PATH * 2];
|
|
TCHAR m_szStorePath[MAX_PATH * 2];
|
|
HANDLE m_hEnum;
|
|
WIN32_FIND_DATA m_Data;
|
|
|
|
// Reference count
|
|
LONG m_ulRefCount;
|
|
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CNtfsPropertyStream
|
|
|
|
class ATL_NO_VTABLE CNtfsPropertyStream :
|
|
public IMailMsgPropertyStream,
|
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
|
public CComCoClass<CNtfsPropertyStream, &CLSID_NtfsPropertyStream>
|
|
{
|
|
public:
|
|
|
|
CNtfsPropertyStream();
|
|
~CNtfsPropertyStream();
|
|
|
|
//
|
|
// guidInstance should be GUID_NULL when we are loading an existing
|
|
// stream from disk, or an instance guid for the driver when we are
|
|
// creating a new stream;
|
|
//
|
|
HRESULT SetHandle(
|
|
HANDLE hStream,
|
|
GUID guidInstance,
|
|
BOOL fLiveStream,
|
|
IMailMsgProperties *pMsg);
|
|
|
|
HRESULT SetInfo(
|
|
CNtfsStoreDriver *pDriver
|
|
)
|
|
{
|
|
_ASSERT(pDriver);
|
|
m_pDriver = pDriver;
|
|
pDriver->AddUsage();
|
|
IncCtr((pDriver->m_ppoi), NTFSDRV_MSG_STREAMS_OPEN);
|
|
return(S_OK);
|
|
}
|
|
|
|
/***************************************************************************/
|
|
//
|
|
// Implementation of IUnknown
|
|
//
|
|
|
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
|
REFIID iid,
|
|
void **ppvObject
|
|
);
|
|
|
|
ULONG STDMETHODCALLTYPE AddRef();
|
|
|
|
ULONG STDMETHODCALLTYPE Release();
|
|
|
|
//
|
|
// IMailMsgPropertyStream
|
|
//
|
|
HRESULT STDMETHODCALLTYPE GetSize(
|
|
IMailMsgProperties *pMsg,
|
|
DWORD *pdwSize,
|
|
IMailMsgNotify *pNotify
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE ReadBlocks(
|
|
IMailMsgProperties *pMsg,
|
|
DWORD dwCount,
|
|
DWORD *pdwOffset,
|
|
DWORD *pdwLength,
|
|
BYTE **ppbBlock,
|
|
IMailMsgNotify *pNotify
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE StartWriteBlocks(
|
|
IMailMsgProperties *pMsg,
|
|
DWORD cBlocks,
|
|
DWORD cBytes);
|
|
|
|
HRESULT STDMETHODCALLTYPE EndWriteBlocks(
|
|
IMailMsgProperties *pMsg);
|
|
|
|
HRESULT STDMETHODCALLTYPE CancelWriteBlocks(
|
|
IMailMsgProperties *pMsg);
|
|
|
|
HRESULT STDMETHODCALLTYPE WriteBlocks(
|
|
IMailMsgProperties *pMsg,
|
|
DWORD dwCount,
|
|
DWORD *pdwOffset,
|
|
DWORD *pdwLength,
|
|
BYTE **ppbBlock,
|
|
IMailMsgNotify *pNotify
|
|
);
|
|
|
|
DECLARE_REGISTRY_RESOURCEID(IDR_NTFSSTM)
|
|
|
|
BEGIN_COM_MAP(CNtfsPropertyStream)
|
|
COM_INTERFACE_ENTRY(IMailMsgPropertyStream)
|
|
END_COM_MAP()
|
|
|
|
GUID GetInstanceGuid() { return m_guidInstance; }
|
|
|
|
private:
|
|
HANDLE m_hStream;
|
|
CNtfsStoreDriver *m_pDriver;
|
|
|
|
// how many times have we seen EndWriteBlocks? (and thus a full commit)
|
|
BOOL m_cCommits;
|
|
|
|
// Reference count
|
|
LONG m_ulRefCount;
|
|
|
|
// do we have header information?
|
|
BOOL m_fStreamHasHeader;
|
|
|
|
// is the stream being used for validation?
|
|
BOOL m_fValidation;
|
|
|
|
// the instance GUID under which this was created
|
|
GUID m_guidInstance;
|
|
|
|
// the hresult that we returned from StartWriteBlocks. if we failed
|
|
// then we also fail writeblocks
|
|
HRESULT m_hrStartWriteBlocks;
|
|
};
|
|
|
|
|
|
#define DECLARE_STD_IUNKNOWN_METHODS(ClassRoot, Interface) \
|
|
HRESULT STDMETHODCALLTYPE C##ClassRoot::QueryInterface( \
|
|
REFIID iid, \
|
|
void **ppvObject \
|
|
) \
|
|
{ \
|
|
if (iid == IID_IUnknown) \
|
|
*ppvObject = (IUnknown *)(##Interface *)this; \
|
|
else if (iid == IID_##Interface) \
|
|
*ppvObject = (##Interface *)this; \
|
|
else \
|
|
return(E_NOINTERFACE); \
|
|
AddRef(); \
|
|
return(S_OK); \
|
|
} \
|
|
ULONG STDMETHODCALLTYPE C##ClassRoot::AddRef() \
|
|
{ \
|
|
return(InterlockedIncrement(&m_ulRefCount)); \
|
|
} \
|
|
ULONG STDMETHODCALLTYPE C##ClassRoot::Release() \
|
|
{ \
|
|
LONG lRefCount = InterlockedDecrement(&m_ulRefCount);\
|
|
if (lRefCount == 0) \
|
|
delete this; \
|
|
return(lRefCount); \
|
|
}
|
|
|
|
#endif //__NTFS_H_
|