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.

270 lines
7.4 KiB

  1. #include <windows.h>
  2. #include <ole2.h>
  3. #include <stdio.h>
  4. #include <malloc.h> // _alloca
  5. #include <obase.h> // def'n of OBJREF
  6. //-------------------------------------------------------------------------
  7. // convenient mappings
  8. #define ORCST(objref) objref.u_objref.u_custom
  9. #define ORSTD(objref) objref.u_objref.u_standard
  10. #define ORHDL(objref) objref.u_objref.u_handler
  11. // bits that must be zero in the flags fields
  12. #define OBJREF_RSRVD_MBZ ~(OBJREF_STANDARD | OBJREF_HANDLER | OBJREF_CUSTOM)
  13. #define SORF_RSRVD_MBZ ~(SORF_NOPING | SORF_OXRES1 | SORF_OXRES2 | \
  14. SORF_OXRES3 | SORF_OXRES4 | SORF_OXRES5 | \
  15. SORF_OXRES6 | SORF_OXRES7 | SORF_OXRES8)
  16. // Internal Uses of the reserved SORF_OXRES flags.
  17. // SORF_TBLWEAK is needed so that RMD works correctly on TABLEWEAK
  18. // marshaling, so it is ignored by unmarshalers. Therefore, we use one of
  19. // the bits reserved for the object exporter that must be ignored by
  20. // unmarshalers.
  21. //
  22. // SORF_WEAKREF is needed for container weak references, when handling
  23. // an IRemUnknown::RemQueryInterface on a weak interface. This is a strictly
  24. // local (windows) machine protocol, so we use a reserved bit.
  25. //
  26. // SORF_NONNDR is needed for interop of 16bit custom (non-NDR) marshalers
  27. // with 32bit, since the 32bit guys want to use MIDL (NDR) to talk to other
  28. // 32bit processes and remote processes, but the custom (non-NDR) format to
  29. // talk to local 16bit guys. In particular, this is to support OLE Automation.
  30. //
  31. // SORF_FREETHREADED is needed when we create a proxy to the SCM interface
  32. // in the apartment model. All apartments can use the same proxy so we avoid
  33. // the test for calling on the correct thread.
  34. #define SORF_TBLWEAK SORF_OXRES1 // (table) weak reference
  35. #define SORF_WEAKREF SORF_OXRES2 // (normal) weak reference
  36. #define SORF_NONNDR SORF_OXRES3 // stub does not use NDR marshaling
  37. #define SORF_FREETHREADED SORF_OXRES4 // proxy may be used on any thread
  38. // definition to simplify coding
  39. const DWORD MSHLFLAGS_TABLE = MSHLFLAGS_TABLESTRONG | MSHLFLAGS_TABLEWEAK;
  40. const DWORD MSHLFLAGS_USER_MASK = MSHLFLAGS_NORMAL | MSHLFLAGS_TABLE |
  41. MSHLFLAGS_NOPING;
  42. // return codes
  43. #define INVALID_SORFFLAG 90000001
  44. #define INVALID_REFCNT 90000002
  45. #define INVALID_MSHLFLAG 90000003
  46. //-------------------------------------------------------------------------
  47. //+-------------------------------------------------------------------------
  48. //
  49. // Function: StRead
  50. //
  51. // Synopsis: Stream read that only succeeds if all requested bytes read
  52. //
  53. // Arguments: [pStm] -- source stream
  54. // [pvBuffer] -- destination buffer
  55. // [ulcb] -- bytes to read
  56. //
  57. // Returns: S_OK if successful, else error code
  58. //
  59. //--------------------------------------------------------------------------
  60. HRESULT StRead(IStream *pStm, void *pvBuffer, ULONG ulcb)
  61. {
  62. ULONG cbRead;
  63. HRESULT hr = pStm->Read(pvBuffer, ulcb, &cbRead);
  64. if (SUCCEEDED(hr))
  65. {
  66. if (ulcb != cbRead)
  67. {
  68. hr = STG_E_READFAULT;
  69. }
  70. }
  71. return hr;
  72. }
  73. void DbgDumpSTD(STDOBJREF *pStd)
  74. {
  75. }
  76. //+-------------------------------------------------------------------------
  77. //
  78. // Function: ReadObjRef
  79. //
  80. // Synopsis: Reads an OBJREF from the stream
  81. //
  82. // Arguments: [pStm] -- source stream
  83. // [objref] -- destination buffer
  84. //
  85. // Returns: S_OK if successful, else error code
  86. //
  87. //--------------------------------------------------------------------------
  88. HRESULT ReadObjRef(IStream *pStm, OBJREF &objref, STDOBJREF **ppStd)
  89. {
  90. HRESULT hr = StRead(pStm, &objref, 2*sizeof(ULONG)+sizeof(IID));
  91. if (SUCCEEDED(hr))
  92. {
  93. if ((objref.signature != OBJREF_SIGNATURE) ||
  94. (objref.flags & OBJREF_RSRVD_MBZ) ||
  95. (objref.flags == 0))
  96. {
  97. // the objref signature is bad, or one of the reserved
  98. // bits in the flags is set, or none of the required bits
  99. // in the flags is set. the objref cant be interpreted so
  100. // fail the call.
  101. return E_UNEXPECTED; // BUGBUG:
  102. }
  103. // compute the size of the remainder of the objref and
  104. // include the size fields for the resolver string array
  105. STDOBJREF *pStd = &ORSTD(objref).std;
  106. DUALSTRINGARRAY *psa;
  107. ULONG cbToRead;
  108. if (objref.flags & OBJREF_STANDARD)
  109. {
  110. cbToRead = sizeof(STDOBJREF) + sizeof(ULONG);
  111. psa = &ORSTD(objref).saResAddr;
  112. }
  113. else if (objref.flags & OBJREF_HANDLER)
  114. {
  115. cbToRead = sizeof(STDOBJREF) + sizeof(CLSID) + sizeof(ULONG);
  116. psa = &ORHDL(objref).saResAddr;
  117. }
  118. else if (objref.flags & OBJREF_CUSTOM)
  119. {
  120. cbToRead = sizeof(CLSID) + sizeof(DWORD); // clsid + data size
  121. psa = NULL;
  122. }
  123. // return ptr to STDOBJREF
  124. *ppStd = pStd;
  125. // read the rest of the (fixed sized) objref from the stream
  126. hr = StRead(pStm, pStd, cbToRead);
  127. if (SUCCEEDED(hr) && psa)
  128. {
  129. // Non custom interface. Make sure the resolver string array
  130. // has some sensible values.
  131. if (psa->wSecurityOffset >= psa->wNumEntries)
  132. {
  133. hr = E_UNEXPECTED; // BUGBUG: correct return code
  134. }
  135. }
  136. if (SUCCEEDED(hr) && psa)
  137. {
  138. // Non custom interface. The data that follows is a variable
  139. // sized string array. Allocate memory for it and then read it.
  140. DbgDumpSTD(pStd);
  141. cbToRead = psa->wNumEntries * sizeof(WCHAR);
  142. DUALSTRINGARRAY *psaNew = (DUALSTRINGARRAY *) _alloca(cbToRead +
  143. sizeof(ULONG));
  144. if (psaNew != NULL)
  145. {
  146. // update the size fields and read in the rest of the data
  147. psaNew->wSecurityOffset = psa->wSecurityOffset;
  148. psaNew->wNumEntries = psa->wNumEntries;
  149. hr = StRead(pStm, psaNew->aStringArray, cbToRead);
  150. }
  151. else
  152. {
  153. psa->wNumEntries = 0;
  154. psa->wSecurityOffset = 0;
  155. hr = E_OUTOFMEMORY;
  156. // seek the stream past what we should have read, ignore
  157. // seek errors, since the OOM takes precedence.
  158. LARGE_INTEGER libMove;
  159. libMove.LowPart = cbToRead;
  160. libMove.HighPart = 0;
  161. pStm->Seek(libMove, STREAM_SEEK_CUR, 0);
  162. }
  163. }
  164. }
  165. return hr;
  166. }
  167. //+-------------------------------------------------------------------------
  168. //
  169. // Function: VerifyOBJREFFormat
  170. //
  171. // Synopsis: Checks the format of the marshal packet
  172. //
  173. // Arguments: [pStm] -- source stream
  174. // [mshlflags] -- destination buffer
  175. //
  176. // Returns: S_OK if successful, else error code
  177. //
  178. //--------------------------------------------------------------------------
  179. HRESULT VerifyOBJREFFormat(IStream *pStm, DWORD mshlflags)
  180. {
  181. OBJREF objref;
  182. STDOBJREF *pStd;
  183. HRESULT hr = ReadObjRef(pStm, objref, &pStd);
  184. // now verify the format
  185. if (SUCCEEDED(hr))
  186. {
  187. if (mshlflags & MSHLFLAGS_NOPING)
  188. {
  189. // SORF_NOPING should be set (unless previously marshaled PING)
  190. if (!(pStd->flags & SORF_NOPING))
  191. return INVALID_SORFFLAG;
  192. }
  193. if ((mshlflags & MSHLFLAGS_TABLE) == MSHLFLAGS_NORMAL)
  194. {
  195. // refcnt should be non-zero
  196. if (pStd->cPublicRefs == 0)
  197. return INVALID_REFCNT;
  198. // table flags should not be set
  199. if (pStd->flags & (SORF_WEAKREF | SORF_TBLWEAK))
  200. return INVALID_SORFFLAG;
  201. }
  202. else if ((mshlflags & MSHLFLAGS_TABLE) == MSHLFLAGS_TABLESTRONG)
  203. {
  204. // refcnt should be zero
  205. if (pStd->cPublicRefs != 0)
  206. return INVALID_REFCNT;
  207. }
  208. else if ((mshlflags & MSHLFLAGS_TABLE) == MSHLFLAGS_TABLEWEAK)
  209. {
  210. // refcnt should be zero
  211. if (pStd->cPublicRefs != 0)
  212. return INVALID_REFCNT;
  213. // SORF_TBLWEAK should be set
  214. if (!(pStd->flags & SORF_TBLWEAK))
  215. return INVALID_SORFFLAG;
  216. }
  217. else
  218. {
  219. // unknown flags
  220. return INVALID_MSHLFLAG;
  221. }
  222. }
  223. return hr;
  224. }