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.

198 lines
5.5 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1999 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * Object.hpp
  8. *
  9. * Abstract:
  10. *
  11. * GpObject interface class
  12. *
  13. * Created:
  14. *
  15. * 4/22/1999 DCurtis
  16. *
  17. \**************************************************************************/
  18. #ifndef _OBJECT_HPP
  19. #define _OBJECT_HPP
  20. // The version must be changed when any EMF+ record is changed, including
  21. // when an object record is changed.
  22. // Changes that invalidate previous files require a major version number change.
  23. // Other changes just require a minor version number change.
  24. #define EMFPLUS_VERSION 0xdbc01001
  25. #define EMFPLUS_MAJORVERSION_BITS 0xFFFFF000
  26. #define EMFPLUS_MINORVERSION_BITS 0x00000FFF
  27. // The GetData methods for all objects must all return a data buffer that
  28. // has a version number as the first INT32 field.
  29. class ObjectData
  30. {
  31. public:
  32. INT32 Version;
  33. ObjectData()
  34. {
  35. Version = EMFPLUS_VERSION;
  36. }
  37. // We should be able to understand the data format as long as the
  38. // major version numbers match. The code must be able to handle
  39. // minor version number changes.
  40. BOOL MajorVersionMatches() const
  41. {
  42. return MajorVersionMatches(Version);
  43. }
  44. static BOOL MajorVersionMatches(INT version)
  45. {
  46. return ((version & EMFPLUS_MAJORVERSION_BITS) ==
  47. (EMFPLUS_VERSION & EMFPLUS_MAJORVERSION_BITS));
  48. }
  49. };
  50. class ObjectTypeData : public ObjectData
  51. {
  52. public:
  53. INT32 Type;
  54. };
  55. VOID InitVersionInfo();
  56. enum EmfPlusRecordType;
  57. enum ColorAdjustType;
  58. class GpRecolor;
  59. class GpObject
  60. {
  61. public:
  62. GpObject()
  63. {
  64. Uid = 0;
  65. Tag = ObjectTagInvalid; // Invalid state
  66. }
  67. virtual ~GpObject()
  68. {
  69. // Force the object to be invalid so we can't reuse this
  70. // deleted object accidentally.
  71. Tag = ObjectTagInvalid; // Invalid state
  72. }
  73. virtual BOOL IsValid() const = 0;
  74. BOOL IsValid(ObjectTag objectTag) const
  75. {
  76. #ifdef _X86_
  77. // We have to guarantee that the Tag field doesn't move for
  78. // versioning to work between releases of GDI+.
  79. ASSERT(offsetof(GpObject, Tag) == 4);
  80. #endif
  81. ASSERT((objectTag & 0xff) == '1');
  82. #if DBG
  83. if (Tag == ObjectTagInvalid)
  84. {
  85. WARNING1("Invalid Object");
  86. }
  87. else if ((Tag & 0xff) != '1')
  88. {
  89. WARNING1("Object created by different version of GDI+")
  90. }
  91. else
  92. {
  93. ASSERT(objectTag == Tag);
  94. }
  95. #endif
  96. return (objectTag == Tag);
  97. }
  98. VOID SetValid(ObjectTag objectTag)
  99. {
  100. ASSERT((objectTag == ObjectTagInvalid) || ((objectTag & 0xff) == '1'))
  101. Tag = objectTag;
  102. }
  103. virtual ObjectType GetObjectType() const = 0;
  104. virtual UINT GetDataSize() const = 0;
  105. virtual GpStatus GetData(BYTE * dataBuffer, UINT & size) const;
  106. virtual GpStatus GetData(IStream * stream) const = 0;
  107. virtual GpStatus SetData(const BYTE * dataBuffer, UINT size) = 0;
  108. virtual GpStatus ColorAdjust(
  109. GpRecolor * recolor,
  110. ColorAdjustType type
  111. )
  112. {
  113. return Ok;
  114. }
  115. virtual VOID Dispose() { delete this; }
  116. UINT GetExternalDataSize() const;
  117. GpStatus GetExternalData(BYTE * dataBuffer, UINT & size);
  118. GpStatus SetExternalData(const BYTE * data, UINT size);
  119. UINT GetUid() const
  120. { if(Uid == 0)
  121. {
  122. Uid = GpObject::GenerateUniqueness();
  123. }
  124. return (UINT)Uid;
  125. }
  126. VOID UpdateUid() { Uid = 0; }
  127. // SetUid is useful in cloning operations.
  128. VOID SetUid(UINT newUid) { Uid = (LONG_PTR)newUid; }
  129. // Object factory for creating an object from metafile memory
  130. static GpObject *
  131. Factory(
  132. ObjectType type,
  133. const ObjectData * objectData,
  134. UINT size
  135. );
  136. static LONG_PTR
  137. GenerateUniqueness(
  138. )
  139. {
  140. LONG_PTR Uid;
  141. // !!! Until we get a way to make sure GDI+ has been initialized when
  142. // !!! using it as a static lib, we need this check because if there
  143. // !!! is a global object, this could get called before
  144. // !!! InitializeGdiplus() is called (for static lib case).
  145. if (!Globals::VersionInfoInitialized)
  146. {
  147. InitVersionInfo();
  148. }
  149. // Use InterlockedCompareExchangeFunction instead of
  150. // InterlockedIncrement, because InterlockedIncrement doesn't work
  151. // the way we need it to on Win9x.
  152. do
  153. {
  154. Uid = Uniqueness;
  155. } while (CompareExchangeLong_Ptr(&Uniqueness, (Uid + 1), Uid) != Uid);
  156. return (Uid + 1);
  157. }
  158. private:
  159. // These members are declared as LONG_PTR because they have to be aligned
  160. // to, and sized according to the minimum atomically exchangable object.
  161. // On x86 this is 32bits and on IA64 this is 64bits.
  162. static LONG_PTR Uniqueness;
  163. // We now use an ObjectTag to determine if the object is valid
  164. // instead of using a BOOL. This is much more robust and helps
  165. // with debugging. It also enables us to version our objects
  166. // more easily with a version number in the ObjectTag.
  167. ObjectTag Tag; // Keep this as the 1st value in the object!
  168. mutable LONG_PTR Uid;
  169. };
  170. #endif // !_OBJECT_HPP