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

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1998,1999 Microsoft Corporation
  4. //
  5. // File: ntfs.h
  6. //
  7. // Contents: Header file for NTFS-base message class
  8. //
  9. //-----------------------------------------------------------------------------
  10. #ifndef __NTFS_H_
  11. #define __NTFS_H_
  12. #include "resource.h" // main symbols
  13. #include "listmacr.h"
  14. #include "evntwrap.h"
  15. #include "perf.h"
  16. //
  17. // Class IDs
  18. //
  19. EXTERN_C const CLSID CLSID_NtfsStoreDriver;
  20. EXTERN_C const CLSID CLSID_NtfsEnumMessages;
  21. EXTERN_C const CLSID CLSID_NtfsPropertyStream;
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CDriverUtils
  24. class CDriverUtils
  25. {
  26. public:
  27. CDriverUtils();
  28. ~CDriverUtils();
  29. static HRESULT LoadStoreDirectory(
  30. DWORD dwInstanceId,
  31. LPTSTR szStoreDirectory,
  32. DWORD *pdwLength
  33. );
  34. static HRESULT GetStoreFileName(
  35. LPTSTR szStoreDirectory,
  36. LPTSTR szStoreFilename,
  37. DWORD *pdwLength
  38. );
  39. static HRESULT GetStoreFileFromPath(
  40. LPTSTR szStoreFilename,
  41. IMailMsgPropertyStream **ppStream,
  42. PFIO_CONTEXT *phContentFile,
  43. BOOL fCreate,
  44. BOOL fIsFAT,
  45. IMailMsgProperties *pMsg,
  46. GUID guidInstance = GUID_NULL
  47. );
  48. static HRESULT SetMessageContext(
  49. IMailMsgProperties *pMsg,
  50. LPBYTE pbContext,
  51. DWORD dwLength
  52. );
  53. static HRESULT GetMessageContext(
  54. IMailMsgProperties *pMsg,
  55. LPBYTE pbContext,
  56. DWORD *pdwLength
  57. );
  58. static HRESULT IsStoreDirectoryFat(
  59. LPTSTR szStoreDirectory,
  60. BOOL *pfIsFAT
  61. );
  62. #if 0
  63. static HANDLE CreateFileCallback(
  64. LPSTR szFilename,
  65. LPVOID lpvData,
  66. DWORD *pdwSize,
  67. DWORD *pdwSizeHigh
  68. );
  69. #endif
  70. private:
  71. static DWORD s_dwCounter;
  72. };
  73. typedef struct {
  74. DWORD dwSignature;
  75. DWORD dwVersion;
  76. GUID guidInstance;
  77. } NTFS_STREAM_HEADER;
  78. #define STREAM_OFFSET sizeof(NTFS_STREAM_HEADER)
  79. #define STREAM_SIGNATURE 'rvDN'
  80. #define STREAM_SIGNATURE_INVALID 'rvD!'
  81. #define STREAM_SIGNATURE_PRECOMMIT 'rvDp'
  82. #define STREAM_SIGNATURE_NOOFFSET 'MMCv'
  83. //
  84. // These are internal status codes used by CNtfsStoreDriver::SetHandle
  85. // to report on the status of the current stream
  86. //
  87. // They aren't errors because SetHandle does actually load the stream.
  88. // they are hints to the caller telling them that mailmsg won't be
  89. // able to parse the stream.
  90. //
  91. #define FACILITY_NTFSDRV 0x6b1
  92. #define NTFSDRV_S_HRESULT(_x_) \
  93. MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NTFSDRV, (_x_))
  94. #define S_NO_FIRST_COMMIT NTFSDRV_S_HRESULT(1)
  95. #define S_INVALIDSTREAM NTFSDRV_S_HRESULT(2)
  96. /////////////////////////////////////////////////////////////////////////////
  97. // CNtfsStoreDriver
  98. class ATL_NO_VTABLE CNtfsStoreDriver :
  99. public IMailMsgStoreDriver,
  100. public ISMTPStoreDriver,
  101. public IEventIsCacheable,
  102. public CComObjectRootEx<CComMultiThreadModelNoCS>,
  103. public CComCoClass<CNtfsStoreDriver, &CLSID_NtfsStoreDriver>,
  104. public IMailMsgStoreDriverValidateContext
  105. {
  106. public:
  107. CNtfsStoreDriver();
  108. ~CNtfsStoreDriver();
  109. LONG AddUsage()
  110. { return(InterlockedIncrement(&m_lRefCount)); }
  111. LONG ReleaseUsage()
  112. { return(InterlockedDecrement(&m_lRefCount)); }
  113. DWORD GetInstance()
  114. { return(m_dwInstance); }
  115. BOOL IsShuttingDown()
  116. { return(m_fIsShuttingDown); }
  117. /***************************************************************************/
  118. //
  119. // Implementation of IUnknown
  120. //
  121. HRESULT STDMETHODCALLTYPE QueryInterface(
  122. REFIID iid,
  123. void **ppvObject
  124. );
  125. ULONG STDMETHODCALLTYPE AddRef();
  126. ULONG STDMETHODCALLTYPE Release();
  127. /***************************************************************************/
  128. //
  129. // IMailMsgStoreDriver
  130. //
  131. HRESULT STDMETHODCALLTYPE AllocMessage(
  132. IMailMsgProperties *pMsg,
  133. DWORD dwFlags,
  134. IMailMsgPropertyStream **ppStream,
  135. PFIO_CONTEXT *phContentFile,
  136. IMailMsgNotify *pNotify
  137. );
  138. HRESULT STDMETHODCALLTYPE EnumMessages(
  139. IMailMsgEnumMessages **ppEnum
  140. );
  141. HRESULT STDMETHODCALLTYPE ReOpen(
  142. IMailMsgProperties *pMsg,
  143. IMailMsgPropertyStream **ppStream,
  144. PFIO_CONTEXT *phContentFile,
  145. IMailMsgNotify *pNotify
  146. );
  147. HRESULT STDMETHODCALLTYPE Delete(
  148. IMailMsgProperties *pMsg,
  149. IMailMsgNotify *pNotify
  150. );
  151. HRESULT STDMETHODCALLTYPE CloseContentFile(
  152. IMailMsgProperties *pMsg,
  153. PFIO_CONTEXT hContentFile
  154. );
  155. HRESULT STDMETHODCALLTYPE ReAllocMessage(
  156. IMailMsgProperties *pOriginalMsg,
  157. IMailMsgProperties *pNewMsg,
  158. IMailMsgPropertyStream **ppStream,
  159. PFIO_CONTEXT *phContentFile,
  160. IMailMsgNotify *pNotify
  161. );
  162. HRESULT STDMETHODCALLTYPE SupportWriteContent() { return S_OK; }
  163. /***************************************************************************/
  164. //
  165. // ISMTPStoreDriver
  166. //
  167. HRESULT STDMETHODCALLTYPE Init(
  168. DWORD dwInstance,
  169. IUnknown *pBinding,
  170. IUnknown *pServer,
  171. DWORD dwReason,
  172. IUnknown **ppStoreDriver
  173. );
  174. HRESULT STDMETHODCALLTYPE PrepareForShutdown(
  175. DWORD dwReason
  176. );
  177. HRESULT STDMETHODCALLTYPE Shutdown(
  178. DWORD dwReason
  179. );
  180. HRESULT STDMETHODCALLTYPE LocalDelivery(
  181. IMailMsgProperties *pMsg,
  182. DWORD dwRecipCount,
  183. DWORD *pdwRecipIndexes,
  184. IMailMsgNotify *pNotify
  185. );
  186. HRESULT STDMETHODCALLTYPE EnumerateAndSubmitMessages(
  187. IMailMsgNotify *pNotify
  188. );
  189. //
  190. // IEventIsCahceable
  191. //
  192. HRESULT STDMETHODCALLTYPE IsCacheable();
  193. //
  194. // IMailMsgStoreDriverValidateContext
  195. //
  196. HRESULT STDMETHODCALLTYPE ValidateMessageContext(
  197. BYTE *pbContext,
  198. DWORD cbContext);
  199. DECLARE_REGISTRY_RESOURCEID(IDR_NTFSDRV)
  200. BEGIN_COM_MAP(CNtfsStoreDriver)
  201. COM_INTERFACE_ENTRY(IMailMsgStoreDriver)
  202. COM_INTERFACE_ENTRY(ISMTPStoreDriver)
  203. COM_INTERFACE_ENTRY(IEventIsCacheable)
  204. COM_INTERFACE_ENTRY(IMailMsgStoreDriverValidateContext)
  205. END_COM_MAP()
  206. GUID GetInstanceGuid() { return m_guidInstance; }
  207. BOOL IsFAT() { return m_fIsFAT; }
  208. private:
  209. LONG m_lRefCount;
  210. DWORD m_dwInstance;
  211. TCHAR m_szQueueDirectory[MAX_PATH * 2];
  212. BOOL m_fInitialized;
  213. BOOL m_fIsShuttingDown;
  214. ISMTPServer *m_pSMTPServer;
  215. // Reference count
  216. LONG m_ulRefCount;
  217. BOOL m_fIsFAT;
  218. // our instance guid
  219. GUID m_guidInstance;
  220. public:
  221. //Use list entry to maintain the list to keep track of current
  222. //instances of sink of this type
  223. LIST_ENTRY m_InstLEntry;
  224. public:
  225. //Global array of instances
  226. static DWORD sm_cCurrentInstances;
  227. static CRITICAL_SECTION sm_csLockInstList;
  228. static LIST_ENTRY sm_ListHead;
  229. //for controlling the retry queue
  230. static void LockList () {EnterCriticalSection (&CNtfsStoreDriver::sm_csLockInstList);}
  231. static void UnLockList() {LeaveCriticalSection (&CNtfsStoreDriver::sm_csLockInstList);}
  232. //Lookup and insert into array
  233. static IUnknown * LookupSinkInstance(DWORD dwVirtualServerId, REFIID iidBinding)
  234. {
  235. PLIST_ENTRY pCurrentListEntry;
  236. CNtfsStoreDriver * pStoreInstance = NULL;
  237. //Initialize
  238. pCurrentListEntry = &sm_ListHead;
  239. //Look at the next entry to see if we are not at the end of the queue
  240. while(pCurrentListEntry->Flink != &sm_ListHead)
  241. {
  242. //Get the object pointed by the next entry
  243. pStoreInstance = CONTAINING_RECORD( pCurrentListEntry->Flink, CNtfsStoreDriver, m_InstLEntry);
  244. //If the entry has same virtual server id we are done
  245. //NK** : check binding too in MM3 timeframe
  246. if(dwVirtualServerId == pStoreInstance->m_dwInstance)
  247. {
  248. return (IUnknown *)(ISMTPStoreDriver *)pStoreInstance;
  249. }
  250. pCurrentListEntry = pCurrentListEntry->Flink;
  251. }
  252. return NULL;
  253. }
  254. static HRESULT InsertSinkInstance(PLIST_ENTRY pListEntry)
  255. {
  256. CNtfsStoreDriver::sm_cCurrentInstances++;
  257. //insert at the start of the list
  258. InsertHeadList(&sm_ListHead, pListEntry);
  259. return S_OK;
  260. }
  261. static HRESULT RemoveSinkInstance(IUnknown * pISinkInstance)
  262. {
  263. PLIST_ENTRY pCurrentListEntry;
  264. CNtfsStoreDriver * pStoreInstance = NULL;
  265. //Initialize
  266. pCurrentListEntry = &sm_ListHead;
  267. //Look at the next entry to see if we are not at the end of the queue
  268. while(pCurrentListEntry->Flink != &sm_ListHead)
  269. {
  270. //Get the object pointed by the next entry
  271. pStoreInstance = CONTAINING_RECORD( pCurrentListEntry->Flink, CNtfsStoreDriver, m_InstLEntry);
  272. //If the entry has same instance pointer we are done
  273. //check binding too in MM3 timeframe
  274. if(pISinkInstance == (IUnknown *)(ISMTPStoreDriver *)pStoreInstance)
  275. {
  276. RemoveEntryList(pCurrentListEntry->Flink);
  277. CNtfsStoreDriver::sm_cCurrentInstances--;
  278. pStoreInstance->m_InstLEntry.Flink = NULL;
  279. pStoreInstance->m_InstLEntry.Blink = NULL;
  280. return S_OK;
  281. }
  282. pCurrentListEntry = pCurrentListEntry->Flink;
  283. }
  284. return(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  285. }
  286. public:
  287. PerfObjectInstance *m_ppoi;
  288. static CEventLogWrapper *g_pEventLog;
  289. };
  290. /////////////////////////////////////////////////////////////////////////////
  291. // CNtfsStoreDriver
  292. class ATL_NO_VTABLE CNtfsEnumMessages :
  293. public IMailMsgEnumMessages,
  294. public CComObjectRootEx<CComMultiThreadModelNoCS>,
  295. public CComCoClass<CNtfsEnumMessages, &CLSID_NtfsEnumMessages>
  296. {
  297. public:
  298. CNtfsEnumMessages();
  299. ~CNtfsEnumMessages();
  300. HRESULT SetStoreDirectory(
  301. LPTSTR szStoreDirectory,
  302. BOOL fIsFAT
  303. );
  304. HRESULT SetInfo(
  305. CNtfsStoreDriver *pDriver
  306. )
  307. {
  308. _ASSERT(pDriver);
  309. m_pDriver = pDriver;
  310. pDriver->AddUsage();
  311. return(S_OK);
  312. }
  313. /***************************************************************************/
  314. //
  315. // Implementation of IUnknown
  316. //
  317. HRESULT STDMETHODCALLTYPE QueryInterface(
  318. REFIID iid,
  319. void **ppvObject
  320. );
  321. ULONG STDMETHODCALLTYPE AddRef();
  322. ULONG STDMETHODCALLTYPE Release();
  323. //
  324. // IMailMsgEnumMessages
  325. //
  326. HRESULT STDMETHODCALLTYPE Next(
  327. IMailMsgProperties *pMsg,
  328. IMailMsgPropertyStream **ppStream,
  329. PFIO_CONTEXT *phContentFile,
  330. IMailMsgNotify *pNotify
  331. );
  332. DECLARE_REGISTRY_RESOURCEID(IDR_NTFSENUM)
  333. BEGIN_COM_MAP(CNtfsEnumMessages)
  334. COM_INTERFACE_ENTRY(IMailMsgEnumMessages)
  335. END_COM_MAP()
  336. private:
  337. CNtfsStoreDriver *m_pDriver;
  338. BOOL m_fIsFAT;
  339. TCHAR m_szEnumPath[MAX_PATH * 2];
  340. TCHAR m_szStorePath[MAX_PATH * 2];
  341. HANDLE m_hEnum;
  342. WIN32_FIND_DATA m_Data;
  343. // Reference count
  344. LONG m_ulRefCount;
  345. };
  346. /////////////////////////////////////////////////////////////////////////////
  347. // CNtfsPropertyStream
  348. class ATL_NO_VTABLE CNtfsPropertyStream :
  349. public IMailMsgPropertyStream,
  350. public CComObjectRootEx<CComMultiThreadModelNoCS>,
  351. public CComCoClass<CNtfsPropertyStream, &CLSID_NtfsPropertyStream>
  352. {
  353. public:
  354. CNtfsPropertyStream();
  355. ~CNtfsPropertyStream();
  356. //
  357. // guidInstance should be GUID_NULL when we are loading an existing
  358. // stream from disk, or an instance guid for the driver when we are
  359. // creating a new stream;
  360. //
  361. HRESULT SetHandle(
  362. HANDLE hStream,
  363. GUID guidInstance,
  364. BOOL fLiveStream,
  365. IMailMsgProperties *pMsg);
  366. HRESULT SetInfo(
  367. CNtfsStoreDriver *pDriver
  368. )
  369. {
  370. _ASSERT(pDriver);
  371. m_pDriver = pDriver;
  372. pDriver->AddUsage();
  373. IncCtr((pDriver->m_ppoi), NTFSDRV_MSG_STREAMS_OPEN);
  374. return(S_OK);
  375. }
  376. /***************************************************************************/
  377. //
  378. // Implementation of IUnknown
  379. //
  380. HRESULT STDMETHODCALLTYPE QueryInterface(
  381. REFIID iid,
  382. void **ppvObject
  383. );
  384. ULONG STDMETHODCALLTYPE AddRef();
  385. ULONG STDMETHODCALLTYPE Release();
  386. //
  387. // IMailMsgPropertyStream
  388. //
  389. HRESULT STDMETHODCALLTYPE GetSize(
  390. IMailMsgProperties *pMsg,
  391. DWORD *pdwSize,
  392. IMailMsgNotify *pNotify
  393. );
  394. HRESULT STDMETHODCALLTYPE ReadBlocks(
  395. IMailMsgProperties *pMsg,
  396. DWORD dwCount,
  397. DWORD *pdwOffset,
  398. DWORD *pdwLength,
  399. BYTE **ppbBlock,
  400. IMailMsgNotify *pNotify
  401. );
  402. HRESULT STDMETHODCALLTYPE StartWriteBlocks(
  403. IMailMsgProperties *pMsg,
  404. DWORD cBlocks,
  405. DWORD cBytes);
  406. HRESULT STDMETHODCALLTYPE EndWriteBlocks(
  407. IMailMsgProperties *pMsg);
  408. HRESULT STDMETHODCALLTYPE CancelWriteBlocks(
  409. IMailMsgProperties *pMsg);
  410. HRESULT STDMETHODCALLTYPE WriteBlocks(
  411. IMailMsgProperties *pMsg,
  412. DWORD dwCount,
  413. DWORD *pdwOffset,
  414. DWORD *pdwLength,
  415. BYTE **ppbBlock,
  416. IMailMsgNotify *pNotify
  417. );
  418. DECLARE_REGISTRY_RESOURCEID(IDR_NTFSSTM)
  419. BEGIN_COM_MAP(CNtfsPropertyStream)
  420. COM_INTERFACE_ENTRY(IMailMsgPropertyStream)
  421. END_COM_MAP()
  422. GUID GetInstanceGuid() { return m_guidInstance; }
  423. private:
  424. HANDLE m_hStream;
  425. CNtfsStoreDriver *m_pDriver;
  426. // how many times have we seen EndWriteBlocks? (and thus a full commit)
  427. BOOL m_cCommits;
  428. // Reference count
  429. LONG m_ulRefCount;
  430. // do we have header information?
  431. BOOL m_fStreamHasHeader;
  432. // is the stream being used for validation?
  433. BOOL m_fValidation;
  434. // the instance GUID under which this was created
  435. GUID m_guidInstance;
  436. // the hresult that we returned from StartWriteBlocks. if we failed
  437. // then we also fail writeblocks
  438. HRESULT m_hrStartWriteBlocks;
  439. };
  440. #define DECLARE_STD_IUNKNOWN_METHODS(ClassRoot, Interface) \
  441. HRESULT STDMETHODCALLTYPE C##ClassRoot::QueryInterface( \
  442. REFIID iid, \
  443. void **ppvObject \
  444. ) \
  445. { \
  446. if (iid == IID_IUnknown) \
  447. *ppvObject = (IUnknown *)(##Interface *)this; \
  448. else if (iid == IID_##Interface) \
  449. *ppvObject = (##Interface *)this; \
  450. else \
  451. return(E_NOINTERFACE); \
  452. AddRef(); \
  453. return(S_OK); \
  454. } \
  455. ULONG STDMETHODCALLTYPE C##ClassRoot::AddRef() \
  456. { \
  457. return(InterlockedIncrement(&m_ulRefCount)); \
  458. } \
  459. ULONG STDMETHODCALLTYPE C##ClassRoot::Release() \
  460. { \
  461. LONG lRefCount = InterlockedDecrement(&m_ulRefCount);\
  462. if (lRefCount == 0) \
  463. delete this; \
  464. return(lRefCount); \
  465. }
  466. #endif //__NTFS_H_