Leaked source code of windows server 2003
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

//+----------------------------------------------------------------------------
//
// 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_