Source code of Windows XP (NT5)
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.

644 lines
18 KiB

  1. //+--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992
  5. //
  6. // File: dfmsp.hxx
  7. //
  8. // Contents: DocFile and MultiStream shared private definitions
  9. //
  10. // History: 01-Apr-92 DrewB Created
  11. // 06-Sep-95 MikeHill Added P_NOSCRATCH
  12. //
  13. //---------------------------------------------------------------
  14. #ifndef __DFMSP_HXX__
  15. #define __DFMSP_HXX__
  16. #include <debnot.h>
  17. #include <wchar.h>
  18. #include <valid.h>
  19. #include <string.h>
  20. #if !defined(MULTIHEAP) && !defined(_CHICAGO_)
  21. #define MULTIHEAP
  22. #include <tls.h>
  23. #endif
  24. #ifdef ASYNC
  25. #include <async.hxx>
  26. #endif
  27. //Enable large docfiles (>4GB files and larger sector sizes)
  28. #define LARGE_DOCFILE
  29. #define LARGE_STREAMS
  30. // Target-dependent things
  31. //
  32. // x86 16-bit build optimizations
  33. //
  34. // Some function parameters are always stack based pointers,
  35. // so we can let the compiler use near addressing via ss by
  36. // declaring the parameter stack based.
  37. //
  38. #if defined(_M_I286)
  39. #define STACKBASED __based(__segname("_STACK"))
  40. #else
  41. #define STACKBASED
  42. #endif
  43. //
  44. // x86 16-bit retail build optimizations
  45. //
  46. // For the retail build, we group the code segments,
  47. // allowing us to make many calls near.
  48. //
  49. #if defined(_M_I286) && DBG == 0 && defined(USE_NEAR)
  50. #define DFBASED
  51. #define DIR_CLASS __near
  52. #define FAT_CLASS __near
  53. #define MSTREAM_CLASS __near
  54. #define VECT_CLASS __near
  55. #else
  56. #define DFBASED
  57. #define DIR_CLASS
  58. #define FAT_CLASS
  59. #define MSTREAM_CLASS
  60. #define VECT_CLASS
  61. #endif
  62. // Compiler pragma define
  63. // Currently defined for C7 and C8
  64. // Unused as of 1/18/93
  65. #if ((_MSC_VER == 700) || (_MSC_VER == 800))
  66. #define MS_COMPILER
  67. #endif
  68. // Segmented memory model definitions
  69. #if !defined(HUGEP)
  70. #if defined(_M_I286)
  71. #define HUGEP __huge
  72. #else
  73. #define HUGEP
  74. #endif
  75. #endif
  76. #ifndef LISet32
  77. #define LISet32(li, v) ((li).QuadPart = (LONGLONG) (v))
  78. #endif
  79. #ifndef ULISet32
  80. #define ULISet32(li, v) ((li).QuadPart = (ULONGLONG) (v))
  81. #endif
  82. #define LISetLow(li, v) ((li).LowPart = (v))
  83. #define LISetHigh(li, v) ((li).HighPart = (v))
  84. #define ULISetLow(li, v) ((li).LowPart = (v))
  85. #define ULISetHigh(li, v) ((li).HighPart = (v))
  86. #define LIGetLow(li) ((li).LowPart)
  87. #define LIGetHigh(li) ((li).HighPart)
  88. #define ULIGetLow(li) ((li).LowPart)
  89. #define ULIGetHigh(li) ((li).HighPart)
  90. // Fast safe increment/decrement
  91. #if !defined(REF) && defined(USEATOMICINC)
  92. // Win32 specific functions
  93. // Should use #ifdef WIN32 instead of FLAT, but there isn't a WIN32
  94. #define AtomicInc(lp) InterlockedIncrement(lp)
  95. #define AtomicDec(lp) InterlockedDecrement(lp)
  96. #else
  97. #define AtomicInc(lp) (++*(lp))
  98. #define AtomicDec(lp) (--*(lp))
  99. #endif //!REF
  100. // Switchable ANSI/Unicode support for TCHAR
  101. // Conversion routines assume null termination before max characters
  102. #ifdef UNICODE
  103. #define ATOT(a, t, max) mbstowcs(t, a, max)
  104. #define TTOA(t, a, max) wcstombs(a, t, max)
  105. #define WTOT(w, t, max) wcscpy(t, w)
  106. #define TTOW(t, w, max) wcscpy(w, t)
  107. #define tcscpy(t, f) lstrcpyW(t, f)
  108. #define tcslen(t) lstrlenW(t)
  109. #define TSTR(s) L##s
  110. // printf format string
  111. #define TFMT "%ws"
  112. #else
  113. #define ATOT(a, t, max) strcpy(t, a)
  114. #define TTOA(t, a, max) strcpy(a, t)
  115. #define WTOT(w, t, max) wcstombs(t, w, max)
  116. #define TTOW(t, w, max) mbstowcs(w, t, max)
  117. #define tcscpy(t, f) strcpy(t, f)
  118. #define tcslen(t) strlen(t)
  119. #define TSTR(s) s
  120. // printf format string
  121. #define TFMT "%s"
  122. #endif
  123. // Switchable ANSI/Unicode support for OLECHAR
  124. // Conversion routines assume null termination before max characters
  125. #define OLEWIDECHAR
  126. #ifndef OLECHAR
  127. #define LPOLESTR LPWSTR
  128. #define LPCOLESTR LPCWSTR
  129. #define OLECHAR WCHAR
  130. #define OLESTR(str) L##str
  131. #endif //OLECHAR
  132. #define _OLESTDMETHODIMP STDMETHODIMP
  133. #define _OLEAPIDECL STDAPI
  134. #define _OLERETURN(sc) ResultFromScode(sc)
  135. #define _OLEAPI(name) name
  136. #define ATOOLE(a, t, max) mbstowcs(t, a, max)
  137. #define OLETOA(t, a, max) wcstombs(a, t, max)
  138. #define WTOOLE(w, t, max) wcscpy(t, w)
  139. #define OLETOW(t, w, max) wcscpy(w, t)
  140. #define olecscpy(t, f) lstrcpyW(t, f)
  141. #define olecslen(t) lstrlenW(t)
  142. #define OLESTR(s) L##s
  143. // printf format string
  144. #define OLEFMT "%ws"
  145. #ifdef _CAIRO_
  146. typedef LPSECURITY_ATTRIBUTES LPSTGSECURITY;
  147. #else
  148. typedef DWORD LPSTGSECURITY;
  149. #endif
  150. #ifdef _CAIRO_
  151. #define STATSTG_dwStgFmt dwStgFmt
  152. #else
  153. #define STATSTG_dwStgFmt reserved
  154. #endif
  155. // For NT 1.0a OLE we need to use based pointers for shared memory objects
  156. // since they might not be mapped at the same address in every process
  157. #if WIN32 == 100 || WIN32 > 200
  158. #define USEBASED
  159. #endif
  160. //We need DfInitSharedMemBase even if we aren't using based pointers,
  161. // since it sets up the shared mem allocator if one hasn't already
  162. // been set up.
  163. void DfInitSharedMemBase(void);
  164. #ifdef USEBASED
  165. #ifdef MULTIHEAP
  166. #define DFBASEPTR pvDfSharedMemBase()
  167. // The previous declaration of DFBASEPTR was:
  168. // extern __declspec(thread) void *DFBASEPTR;
  169. // Now, it is an inline function that returns the threadlocal base pointer
  170. // Reference to pointer syntax is needed for assignments to DFBASEPTR
  171. __forceinline void *& DFBASEPTR
  172. {
  173. COleTls otls;
  174. return otls->pvThreadBase;
  175. }
  176. #else
  177. #define DFBASEPTR pvDfSharedMemBase
  178. extern void *DFBASEPTR;
  179. #endif // MULTIHEAP
  180. #pragma warning(error: 4795 4796)
  181. #undef DFBASED
  182. #ifdef MULTIHEAP
  183. // based pointers are replaced by CSafeBased... smart pointer macros
  184. // macros invoke conversion constructor and conversion operators
  185. //#define DFBASED __based(DFBASEDPTR)
  186. #define P_TO_BP(t, p) ((t)(p))
  187. #define BP_TO_P(t, bp) ((t)(bp))
  188. #else // MULTIHEAP
  189. #define DFBASED __based(DFBASEPTR)
  190. #define P_TO_BP(t, p) ((t)((p) ? (int)(t)(char *)(p) : 0))
  191. #define BP_TO_P(t, bp) (t)((bp) != 0 ? (bp) : 0)
  192. #endif // MULTIHEAP
  193. #else
  194. #define P_TO_BP(t, p) p
  195. #define BP_TO_P(t, bp) bp
  196. #endif //USEBASED
  197. //----------------------------------------------------------------------------
  198. // The name of this function might change, so encapsulate it
  199. #define DfGetScode(hr) GetScode(hr)
  200. // Buffer/pointer validation macros
  201. BOOL IsValidStgInterface (void * pv);
  202. #define AssertMsg(s) _Win4Assert(__FILE__, __LINE__, s)
  203. // MAC - We use Windows functions if available
  204. #if (WIN32 == 100 || WIN32 >= 300)
  205. #define IsValidHugePtrIn(pv, n) (((pv) == NULL) || !IsBadHugeReadPtr(pv, n))
  206. #define IsValidHugePtrOut(pv, n) (!IsBadHugeWritePtr(pv, n))
  207. #else
  208. #define IsValidHugePtrIn(pv, n) 1
  209. #define IsValidHugePtrOut(pv, n) ((pv) != NULL)
  210. #endif
  211. #define ValidateBuffer(pv, n) \
  212. (((pv) == NULL || !IsValidPtrIn(pv, n)) ? STG_E_INVALIDPOINTER : S_OK)
  213. #define ValidatePtrBuffer(pv) \
  214. ValidateBuffer(pv, sizeof(void *))
  215. #define ValidateHugeBuffer(pv, n) \
  216. (((pv) == NULL || !IsValidHugePtrIn(pv, n)) ? STG_E_INVALIDPOINTER : S_OK)
  217. #define ValidateOutBuffer(pv, n) \
  218. (!IsValidPtrOut(pv, n) ? STG_E_INVALIDPOINTER : S_OK)
  219. #define ValidateOutPtrBuffer(pv) \
  220. ValidateOutBuffer(pv, sizeof(void *))
  221. #define ValidateHugeOutBuffer(pv, n) \
  222. (!IsValidHugePtrOut(pv, n) ? STG_E_INVALIDPOINTER : S_OK)
  223. #if DBG==1
  224. #define ValidateIid(riid) \
  225. (!IsValidIid(riid) ? STG_E_INVALIDPOINTER : S_OK)
  226. #else
  227. // killed this macro in retail build since it used to do no useful work
  228. // now we are faster. see comment for ValidateIid.
  229. #define ValidateIid(riid) S_OK
  230. #endif
  231. #define ValidateInterface(punk, riid) \
  232. (!IsValidStgInterface(punk) ? STG_E_INVALIDPOINTER : S_OK)
  233. #if (WIN32 == 100 || WIN32 >= 300)
  234. #define ValidateWcs(pwcs, cwcMax) \
  235. (IsBadStringPtrW(pwcs, cwcMax) ? STG_E_INVALIDPOINTER : S_OK)
  236. #else
  237. // OLE should provide a helper function for this
  238. #define ValidateWcs(pwcs, cwcMax) \
  239. ((pwcs == NULL) || !IsValidPtrIn(pwcs, sizeof(WCHAR)) ? STG_E_INVALIDPOINTER : S_OK)
  240. #endif
  241. #if defined(_WINDOWS_)
  242. # define ValidateSz(psz, cchMax) \
  243. (IsBadStringPtrA(psz, cchMax) ? STG_E_INVALIDPOINTER : S_OK)
  244. #elif defined(_INC_WINDOWS)
  245. # define ValidateSz(psz, cchMax) \
  246. (IsBadStringPtr(psz, cchMax) ? STG_E_INVALIDPOINTER : S_OK)
  247. #else
  248. // MAC - OLE doesn't provide sufficient helper functions
  249. # define ValidateSz(psz, cchMax) \
  250. (!IsValidPtrIn(psz, 1) ? STG_E_INVALIDPOINTER : S_OK)
  251. #endif
  252. #if defined(OLEWIDECHAR)
  253. SCODE ValidateNameW(LPCWSTR pwcsName, UINT cchMax);
  254. #else
  255. // For non-Unicode builds, we verify all names before converting them
  256. // to wide character names, so there's no need to recheck.
  257. # define ValidateNameW(pwcs, cchMax) \
  258. S_OK
  259. #endif
  260. #if defined(_WINDOWS_)
  261. # define ValidateNameA(psz, cchMax) \
  262. (IsBadStringPtrA(psz, cchMax) ? STG_E_INVALIDNAME : S_OK)
  263. #elif defined(_INC_WINDOWS)
  264. # define ValidateNameA(psz, cchMax) \
  265. (IsBadStringPtr(psz, cchMax) ? STG_E_INVALIDNAME : S_OK)
  266. #else
  267. # define ValidateNameA(psz, cchMax) \
  268. (!IsValidPtrIn(psz, 1) ? STG_E_INVALIDNAME : S_OK)
  269. #endif
  270. // Enumeration for Get/SetTime
  271. enum WHICHTIME
  272. {
  273. WT_CREATION,
  274. WT_MODIFICATION,
  275. WT_ACCESS
  276. };
  277. // Time type
  278. typedef FILETIME TIME_T;
  279. // Signature for transactioning
  280. typedef DWORD DFSIGNATURE;
  281. #define DF_INVALIDSIGNATURE ((DFSIGNATURE)-1)
  282. // Convenience macros for signature creation
  283. #define LONGSIG(c1, c2, c3, c4) \
  284. (((ULONG) (BYTE) (c1)) | \
  285. (((ULONG) (BYTE) (c2)) << 8) | \
  286. (((ULONG) (BYTE) (c3)) << 16) | \
  287. (((ULONG) (BYTE) (c4)) << 24))
  288. #ifndef min
  289. #define min(a, b) ((a)<(b) ? (a) : (b))
  290. #endif
  291. #ifndef max
  292. #define max(a, b) ((a)>(b) ? (a) : (b))
  293. #endif
  294. SCODE DfGetTOD(TIME_T *ptm);
  295. // Shared signature validation routine
  296. SCODE CheckSignature(BYTE *pb);
  297. // Docfile locally unique identity
  298. // Every entry in a multistream has a LUID generated and stored for it
  299. typedef DWORD DFLUID;
  300. #define DF_NOLUID 0
  301. typedef SNB SNBW;
  302. typedef STATSTG STATSTGW;
  303. #define CBSTORAGENAME (CWCSTORAGENAME*sizeof(WCHAR))
  304. int dfwcsnicmp(const WCHAR *wcsa, const WCHAR *wcsb, size_t len);
  305. #include <dfname.hxx>
  306. // Fast, fixed space iterator structure
  307. struct SIterBuffer
  308. {
  309. CDfName dfnName;
  310. DWORD type;
  311. };
  312. //SID is a Stream Identifier
  313. #define SID DFSID
  314. typedef ULONG SID;
  315. // IsEntry entry information
  316. struct SEntryBuffer
  317. {
  318. DFLUID luid;
  319. DWORD dwType;
  320. SID sid;
  321. };
  322. // Destroy flags
  323. #define DESTROY_FROM_HANDLE 0
  324. #define DESTROY_FROM_ENTRY 1
  325. #define DESTROY_FROM 0x01
  326. #define DESTROY_SELF 0x40
  327. #define DESTROY_RECURSIVE 0x80
  328. #define DESTROY_HANDLE (DESTROY_FROM_HANDLE | DESTROY_SELF)
  329. #define DESTROY_ENTRY (DESTROY_FROM_ENTRY | DESTROY_SELF)
  330. // Root startup flags
  331. #define RSF_OPEN 0x00
  332. #define RSF_CONVERT 0x01
  333. #define RSF_TRUNCATE 0x02
  334. #define RSF_CREATE 0x04
  335. #define RSF_DELAY 0x08
  336. #define RSF_DELETEONRELEASE 0x10
  337. #define RSF_OPENCREATE 0x20
  338. #define RSF_SCRATCH 0x40
  339. #define RSF_SNAPSHOT 0x80
  340. #define RSF_NO_BUFFERING 0x200
  341. #define RSF_ENCRYPTED 0x400
  342. #define RSF_SECTORSIZE4K 0xC000
  343. #define RSF_SECTORSIZE8K 0xD000
  344. #define RSF_SECTORSIZE16K 0xE000
  345. #define RSF_SECTORSIZE32K 0xF000
  346. #define RSF_SECTORSIZE_MASK 0xF000
  347. // The sector size flags can be converted to sector shifts by >> 12 bits
  348. #define RSF_CREATEFLAGS (RSF_CREATE | RSF_TRUNCATE | RSF_OPENCREATE)
  349. #define RSF_TEMPFILE (RSF_SCRATCH | RSF_SNAPSHOT)
  350. // Stream copy buffer size
  351. ULONG const STREAMBUFFERSIZE = 8192;
  352. ULONG const LARGESTREAMBUFFERSIZE = 256*1024;
  353. // Docfile flags for permissions and other information kept
  354. // on streams and docfiles
  355. typedef DWORD DFLAGS;
  356. #define DF_TRANSACTEDSELF 0x0001
  357. #define DF_TRANSACTED 0x0002
  358. #define DF_DIRECT 0x0000
  359. #define DF_INDEPENDENT 0x0004
  360. #define DF_DEPENDENT 0x0000
  361. #define DF_COMMIT 0x0008
  362. #define DF_ABORT 0x0000
  363. #define DF_INVALID 0x0010
  364. #define DF_REVERTED 0x0020
  365. #define DF_NOTREVERTED 0x0000
  366. #define DF_READ 0x0040
  367. #define DF_WRITE 0x0080
  368. #define DF_READWRITE (DF_READ | DF_WRITE)
  369. #define DF_DENYREAD 0x0100
  370. #define DF_DENYWRITE 0x0200
  371. #define DF_DENYALL (DF_DENYREAD | DF_DENYWRITE)
  372. #define DF_PRIORITY 0x0400
  373. #define DF_CREATE 0x0800
  374. #define DF_CACHE 0x1000
  375. #define DF_NOUPDATE 0x2000
  376. #define DF_NOSCRATCH 0x4000
  377. #if WIN32 >= 300
  378. #define DF_ACCESSCONTROL 0x8000
  379. #endif
  380. #define DF_COORD 0x10000
  381. #define DF_COMMITTING 0x20000
  382. #define DF_NOSNAPSHOT 0x40000
  383. // docfile can be bigger than 4G
  384. #define DF_LARGE 0x80000
  385. // Shift required to translate from DF_READWRITE to DF_DENYALL
  386. #define DF_DENIALSHIFT 2
  387. // Permission abstraction macros
  388. // These only work with DF_* flags
  389. #define P_READ(f) ((f) & DF_READ)
  390. #define P_WRITE(f) ((f) & DF_WRITE)
  391. #define P_READWRITE(f) (((f) & (DF_READ | DF_WRITE)) == (DF_READ | DF_WRITE))
  392. #define P_DENYREAD(f) ((f) & DF_DENYREAD)
  393. #define P_DENYWRITE(f) ((f) & DF_DENYWRITE)
  394. #define P_DENYALL(f) (((f) & (DF_DENYREAD | DF_DENYWRITE)) == \
  395. (DF_DENYREAD | DF_DENYWRITE))
  396. #define P_PRIORITY(f) ((f) & DF_PRIORITY)
  397. #define P_TRANSACTED(f) ((f) & DF_TRANSACTED)
  398. #define P_DIRECT(f) (!P_TRANSACTED(f))
  399. #define P_INDEPENDENT(f) (((DFLAGS)f) & DF_INDEPENDENT)
  400. #define P_DEPENDENT(f) (!P_INDEPENDENT(f))
  401. #define P_TSELF(f) ((f) & DF_TRANSACTEDSELF)
  402. #define P_INVALID(f) ((f) & DF_INVALID)
  403. #define P_REVERTED(f) ((f) & DF_REVERTED)
  404. #define P_COMMIT(f) ((f) & DF_COMMIT)
  405. #define P_ABORT(f) (!P_COMMIT(f))
  406. #define P_CREATE(f) ((f) & DF_CREATE)
  407. #define P_CACHE(f) ((f) & DF_CACHE)
  408. #define P_NOUPDATE(f) ((f) & DF_NOUPDATE)
  409. #define P_COORD(f) ((f) & DF_COORD)
  410. #define P_COMMITTING(f) ((f) & DF_COMMITTING)
  411. #define P_NOSCRATCH(f) ((f) & DF_NOSCRATCH)
  412. #define P_NOSNAPSHOT(f) ((f) & DF_NOSNAPSHOT)
  413. // Translation functions
  414. DFLAGS ModeToDFlags(DWORD const dwModeFlags);
  415. DWORD DFlagsToMode(DFLAGS const df);
  416. // Flags for what state has been dirtied
  417. #define DIRTY_CREATETIME 0x0001
  418. #define DIRTY_MODIFYTIME 0x0002
  419. #define DIRTY_ACCESSTIME 0x0004
  420. #define DIRTY_CLASS 0x0008
  421. #define DIRTY_STATEBITS 0x0010
  422. // Allow text in asserts
  423. #define aMsg(s) ((char *)(s) != NULL)
  424. // Indicate that something is a property value
  425. // This must not conflict with official STGTY_* flags
  426. #define STGTY_REAL (STGTY_STORAGE | STGTY_STREAM | STGTY_LOCKBYTES)
  427. #define REAL_STGTY(f) (f)
  428. // Buffer management
  429. #ifdef LARGE_DOCFILE
  430. #define CB_LARGEBUFFER 65536
  431. #else
  432. #define CB_LARGEBUFFER 32768
  433. #endif
  434. #define CB_PAGEBUFFER 4096
  435. #define CB_SMALLBUFFER 512
  436. extern SCODE GetBuffer(ULONG cbMin, ULONG cbMax, BYTE **ppb,
  437. ULONG *pcbActual);
  438. extern void GetSafeBuffer(ULONG cbMin, ULONG cbMax, BYTE **ppb,
  439. ULONG *pcbActual);
  440. extern void FreeBuffer(BYTE *pb);
  441. #include <dfmem.hxx>
  442. #define DfAllocWC(cwc, ppwcs) (*ppwcs = (WCHAR *)\
  443. TaskMemAlloc((cwc)*sizeof(WCHAR)),\
  444. (*ppwcs != NULL) ? S_OK: STG_E_INSUFFICIENTMEMORY)
  445. #define DfAllocWCS(pwcs, ppwcs) DfAllocWC(lstrlenW(pwcs)+1, ppwcs)
  446. SCODE Win32ErrorToScode(DWORD dwErr);
  447. #define STG_SCODE(err) Win32ErrorToScode(err)
  448. #ifdef MULTIHEAP
  449. //+------------------------------------------------------------------------
  450. //
  451. // Macro: SAFE_DFBASED_PTR
  452. //
  453. // Purpose: Pointer to memory created by shared memory allocator.
  454. // This macro replaces the __based() compiler keyword
  455. // Only the offset is stored in _p, and conversion operators
  456. // return the absolute address (by adding the base address).
  457. // The smart pointer can only change through:
  458. // construction, assignment operator=
  459. // The smart pointer can be read through:
  460. // operator->, operator*, (casting to unbased type)
  461. // Destroying the smart pointer does not invoke _p's destructor
  462. //
  463. // Notes: There is special logic to translate a NULL based pointer
  464. // into a NULL absolute pointer, and vice versa.
  465. // We can do this without ambiguity since DFBASEPTR can
  466. // never be returned from CSmAlllocator::Alloc
  467. // (DFBASEPTR is really a CHeapHeader pointer, part of the heap)
  468. //
  469. // Arguments: [SpName] - class name of the smart based pointer
  470. // [SpType] - class name of the original unbased type
  471. //
  472. // History: 22-Feb-96 HenryLee Created
  473. //
  474. //-------------------------------------------------------------------------
  475. #define SAFE_DFBASED_PTR(SpName,SpType) \
  476. class SpName \
  477. { \
  478. public: \
  479. inline SpName () : _p(NULL) \
  480. { \
  481. } \
  482. inline SpName (SpType *p) \
  483. { \
  484. _p = (p) ? (ULONG_PTR)((BYTE*)p - (ULONG_PTR)DFBASEPTR) : NULL; \
  485. } \
  486. inline ~##SpName () \
  487. { \
  488. } \
  489. __forceinline SpType* operator-> () const \
  490. { \
  491. return (SpType *)(_p ? (BYTE *)_p + (ULONG_PTR)DFBASEPTR : NULL); \
  492. } \
  493. __forceinline SpType& operator * () const \
  494. { \
  495. return * (SpType *)(_p ? (BYTE *)_p + (ULONG_PTR)DFBASEPTR : NULL); \
  496. } \
  497. __forceinline operator SpType* () const \
  498. { \
  499. return (SpType *)(_p ? (BYTE *)_p + (ULONG_PTR)DFBASEPTR : NULL); \
  500. } \
  501. __forceinline SpType* operator= (SpType* p) \
  502. { \
  503. _p = (p) ? (ULONG_PTR)((BYTE*)p - (ULONG_PTR)DFBASEPTR) : NULL; \
  504. return p; \
  505. } \
  506. private: \
  507. ULONG_PTR _p; \
  508. }; \
  509. #else
  510. #define SAFE_DFBASED_PTR(SpName,SpType) \
  511. typedef SpType DFBASED * SpName;
  512. #endif // MULTIHEAP
  513. #include <widewrap.h>
  514. #ifndef STG_E_PENDINGCONTROL
  515. #define STG_E_PENDINGCONTROL _HRESULT_TYPEDEF_(0x80030204L)
  516. #endif
  517. #endif // #ifndef __DFMSP_HXX__