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.

1793 lines
52 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. frscomm.c
  5. Abstract:
  6. Routines for the comm layer to convert to and from communication packets.
  7. Author:
  8. Billy J. Fuller 29-May-1997
  9. David Orbits 21-Mar-2000
  10. Restructured to use table and provide extensible elements.
  11. Environment
  12. User mode winnt
  13. --*/
  14. #include <ntreppch.h>
  15. #pragma hdrstop
  16. #include <frs.h>
  17. #include <tablefcn.h>
  18. PCO_RECORD_EXTENSION_WIN2K
  19. DbsDataConvertCocExtensionToWin2K(
  20. IN PCHANGE_ORDER_RECORD_EXTENSION CocExt
  21. );
  22. extern PGEN_TABLE CompressionTable;
  23. //
  24. // Types for the common comm subsystem
  25. //
  26. // WARNING: The order of these entries can never change. This ensures that
  27. // packets can be exchanged between uplevel and downlevel members.
  28. //
  29. typedef enum _COMMTYPE {
  30. COMM_NONE = 0,
  31. COMM_BOP, // beginning of packet
  32. COMM_COMMAND, // command packet stuff
  33. COMM_TO,
  34. COMM_FROM,
  35. COMM_REPLICA,
  36. COMM_JOIN_GUID,
  37. COMM_VVECTOR,
  38. COMM_CXTION,
  39. COMM_BLOCK, // file data
  40. COMM_BLOCK_SIZE,
  41. COMM_FILE_SIZE,
  42. COMM_FILE_OFFSET,
  43. COMM_REMOTE_CO, // remote change order command
  44. COMM_GVSN, // version (guid, vsn)
  45. COMM_CO_GUID, // change order guid
  46. COMM_CO_SEQUENCE_NUMBER,// CO Seq number for ack.
  47. COMM_JOIN_TIME, // machine's can't join if there times or badly out of sync
  48. COMM_LAST_JOIN_TIME, // The Last time this connection was joined.
  49. // Used to detect Database mismatch.
  50. COMM_EOP, // end of packet
  51. COMM_REPLICA_VERSION_GUID, // replica version guid (originator guid)
  52. COMM_MD5_DIGEST, // md5 digest
  53. //
  54. // Change Order Record Extension. If not supplied the the ptr for
  55. // what was Spare1Bin (now Extension) is left as Null. So comm packets
  56. // sent from down level members still work.
  57. //
  58. COMM_CO_EXT_WIN2K, // in down level code this was called COMM_CO_EXTENSION.
  59. //
  60. // See comment in schema.h for why we need to seperate the var len
  61. // COMM_CO_EXTENSION_2 from COMM_CO_EXT_WIN2K above.
  62. //
  63. COMM_CO_EXTENSION_2,
  64. COMM_COMPRESSION_GUID, // Guid for a supported compression algorithm.
  65. //
  66. // WARNING: To ensure that down level members can read Comm packets
  67. // from uplevel clients always add net data type codes here.
  68. //
  69. COMM_MAX
  70. } COMM_TYPE, *PCOMM_TYPE;
  71. #define COMM_NULL_DATA (-1)
  72. //
  73. // The decode data types are defined below. They are used in the CommPacketTable
  74. // to aid in decode dispatching and comm packet construction
  75. // They DO NOT get sent in the actual packet.
  76. //
  77. typedef enum _COMM_PACKET_DECODE_TYPE {
  78. COMM_DECODE_NONE = 0,
  79. COMM_DECODE_ULONG,
  80. COMM_DECODE_ULONG_TO_USHORT,
  81. COMM_DECODE_GNAME,
  82. COMM_DECODE_BLOB,
  83. COMM_DECODE_ULONGLONG,
  84. COMM_DECODE_VVECTOR,
  85. COMM_DECODE_VAR_LEN_BLOB,
  86. COMM_DECODE_REMOTE_CO,
  87. COMM_DECODE_GUID,
  88. COMM_DECODE_MAX
  89. } COMM_PACKET_DECODE_TYPE, *PCOMM_PACKET_DECODE_TYPE;
  90. //
  91. // The COMM_PACKET_ELEMENT struct is used in a table to describe the data
  92. // elements in a Comm packet.
  93. //
  94. typedef struct _COMM_PACKET_ELEMENT_ {
  95. COMM_TYPE CommType;
  96. PCHAR CommTag;
  97. ULONG DataSize;
  98. ULONG DecodeType;
  99. ULONG NativeOffset;
  100. } COMM_PACKET_ELEMENT, *PCOMM_PACKET_ELEMENT;
  101. #define COMM_MEM_SIZE (128)
  102. //
  103. // Size of the required Beginning-of-packet and End-of-Packet fields
  104. //
  105. #define MIN_COMM_PACKET_SIZE (2 * (sizeof(USHORT) + sizeof(ULONG) + sizeof(ULONG)))
  106. #define COMM_SZ_UL sizeof(ULONG)
  107. #define COMM_SZ_ULL sizeof(ULONGLONG)
  108. #define COMM_SZ_GUID sizeof(GUID)
  109. #define COMM_SZ_GUL sizeof(GUID) + sizeof(ULONG)
  110. #define COMM_SZ_GVSN sizeof(GVSN) + sizeof(ULONG)
  111. #define COMM_SZ_NULL 0
  112. #define COMM_SZ_COC sizeof(CHANGE_ORDER_COMMAND) + sizeof(ULONG)
  113. //#define COMM_SZ_COC CO_PART1_SIZE + CO_PART2_SIZE + CO_PART3_SIZE + sizeof(ULONG)
  114. #define COMM_SZ_COEXT_W2K sizeof(CO_RECORD_EXTENSION_WIN2K) + sizeof(ULONG)
  115. #define COMM_SZ_MD5 MD5DIGESTLEN + sizeof(ULONG)
  116. #define COMM_SZ_JTIME sizeof(ULONGLONG) + sizeof(ULONG)
  117. //
  118. // Note: When using COMM_DECODE_VAR_LEN_BLOB you must also use COMM_SZ_NULL
  119. // in the table below so that no length check is made when the field is decoded.
  120. // This allows the field size to grow. Down level members must be able to
  121. // handle this by ignoring var len field components they do not understand.
  122. //
  123. //
  124. // The Communication packet element table below is used to construct and
  125. // decode comm packet data sent between members.
  126. // *** WARNING *** - the order of the rows in the table must match the
  127. // the order of the elements in the COMM_TYPE enum. See comments for COMM_TYPE
  128. // enum for restrictions on adding new elements to the table.
  129. //
  130. // Data Element Type DisplayText Size Decode Type Offset to Native Cmd Packet
  131. //
  132. COMM_PACKET_ELEMENT CommPacketTable[COMM_MAX] = {
  133. {COMM_NONE, "NONE" , COMM_SZ_NULL, COMM_DECODE_NONE, 0 },
  134. {COMM_BOP, "BOP" , COMM_SZ_UL, COMM_DECODE_ULONG, RsOffsetSkip },
  135. {COMM_COMMAND, "COMMAND" , COMM_SZ_UL, COMM_DECODE_ULONG_TO_USHORT, OFFSET(COMMAND_PACKET, Command)},
  136. {COMM_TO, "TO" , COMM_SZ_NULL, COMM_DECODE_GNAME, RsOffset(To) },
  137. {COMM_FROM, "FROM" , COMM_SZ_NULL, COMM_DECODE_GNAME, RsOffset(From) },
  138. {COMM_REPLICA, "REPLICA" , COMM_SZ_NULL, COMM_DECODE_GNAME, RsOffset(ReplicaName) },
  139. {COMM_JOIN_GUID, "JOIN_GUID" , COMM_SZ_GUL, COMM_DECODE_BLOB, RsOffset(JoinGuid) },
  140. {COMM_VVECTOR, "VVECTOR" , COMM_SZ_GVSN, COMM_DECODE_VVECTOR, RsOffset(VVector) },
  141. {COMM_CXTION, "CXTION" , COMM_SZ_NULL, COMM_DECODE_GNAME, RsOffset(Cxtion) },
  142. {COMM_BLOCK, "BLOCK" , COMM_SZ_NULL, COMM_DECODE_BLOB, RsOffset(Block) },
  143. {COMM_BLOCK_SIZE, "BLOCK_SIZE" , COMM_SZ_ULL, COMM_DECODE_ULONGLONG, RsOffset(BlockSize) },
  144. {COMM_FILE_SIZE, "FILE_SIZE" , COMM_SZ_ULL, COMM_DECODE_ULONGLONG, RsOffset(FileSize) },
  145. {COMM_FILE_OFFSET, "FILE_OFFSET" , COMM_SZ_ULL, COMM_DECODE_ULONGLONG, RsOffset(FileOffset) },
  146. {COMM_REMOTE_CO, "REMOTE_CO" , COMM_SZ_COC, COMM_DECODE_REMOTE_CO, RsOffset(PartnerChangeOrderCommand)},
  147. {COMM_GVSN, "GVSN" , COMM_SZ_GVSN, COMM_DECODE_BLOB, RsOffset(GVsn) },
  148. {COMM_CO_GUID, "CO_GUID" , COMM_SZ_GUL, COMM_DECODE_BLOB, RsOffset(ChangeOrderGuid) },
  149. {COMM_CO_SEQUENCE_NUMBER, "CO_SEQUENCE_NUMBER" , COMM_SZ_UL, COMM_DECODE_ULONG, RsOffset(ChangeOrderSequenceNumber)},
  150. {COMM_JOIN_TIME, "JOIN_TIME" , COMM_SZ_JTIME, COMM_DECODE_BLOB, RsOffset(JoinTime) },
  151. {COMM_LAST_JOIN_TIME, "LAST_JOIN_TIME" , COMM_SZ_ULL, COMM_DECODE_ULONGLONG, RsOffset(LastJoinTime) },
  152. {COMM_EOP, "EOP" , COMM_SZ_UL, COMM_DECODE_ULONG, RsOffsetSkip },
  153. {COMM_REPLICA_VERSION_GUID, "REPLICA_VERSION_GUID", COMM_SZ_GUL, COMM_DECODE_BLOB, RsOffset(ReplicaVersionGuid)},
  154. {COMM_MD5_DIGEST, "MD5_DIGEST" , COMM_SZ_MD5, COMM_DECODE_BLOB, RsOffset(Md5Digest) },
  155. {COMM_CO_EXT_WIN2K, "CO_EXT_WIN2K" , COMM_SZ_COEXT_W2K,COMM_DECODE_BLOB, RsOffset(PartnerChangeOrderCommandExt)},
  156. {COMM_CO_EXTENSION_2, "CO_EXTENSION_2" , COMM_SZ_NULL, COMM_DECODE_VAR_LEN_BLOB, RsOffset(PartnerChangeOrderCommandExt)},
  157. {COMM_COMPRESSION_GUID, "COMPRESSION_GUID" , COMM_SZ_GUID, COMM_DECODE_GUID, RsOffset(CompressionTable)}
  158. };
  159. BOOL
  160. CommGetNextElement(
  161. IN PCOMM_PACKET CommPkt,
  162. OUT COMM_TYPE *CommType,
  163. OUT ULONG *CommTypeSize
  164. );
  165. VOID
  166. CommInitializeCommSubsystem(
  167. VOID
  168. )
  169. /*++
  170. Routine Description:
  171. Initialize the generic comm subsystem
  172. Arguments:
  173. None.
  174. Return Value:
  175. None.
  176. --*/
  177. {
  178. #undef DEBSUB
  179. #define DEBSUB "CommInitializeCommSubsystem:"
  180. //
  181. // type must fit into a short
  182. //
  183. FRS_ASSERT(COMM_MAX <= 0xFFFF);
  184. }
  185. VOID
  186. CommCopyMemory(
  187. IN PCOMM_PACKET CommPkt,
  188. IN PUCHAR Src,
  189. IN ULONG Len
  190. )
  191. /*++
  192. Routine Description:
  193. Copy memory into a comm packet, extending as necessary
  194. Arguments:
  195. CommPkt
  196. Src
  197. Len
  198. Return Value:
  199. None.
  200. --*/
  201. {
  202. #undef DEBSUB
  203. #define DEBSUB "CommCopyMemory:"
  204. ULONG MemLeft;
  205. PUCHAR NewPkt;
  206. //
  207. // Adjust size of comm packet if necessary
  208. //
  209. // PERF: How many allocs get done to send a CO??? This looks expensive.
  210. MemLeft = CommPkt->MemLen - CommPkt->PktLen;
  211. if (Len > MemLeft) {
  212. //
  213. // Just filling memory; extend memory, tacking on a little extra
  214. //
  215. CommPkt->MemLen = (((CommPkt->MemLen + Len) + (COMM_MEM_SIZE - 1))
  216. / COMM_MEM_SIZE)
  217. * COMM_MEM_SIZE;
  218. NewPkt = FrsAlloc(CommPkt->MemLen);
  219. CopyMemory(NewPkt, CommPkt->Pkt, CommPkt->PktLen);
  220. FrsFree(CommPkt->Pkt);
  221. CommPkt->Pkt = NewPkt;
  222. }
  223. //
  224. // Copy into the packet
  225. //
  226. if (Src != NULL) {
  227. CopyMemory(CommPkt->Pkt + CommPkt->PktLen, Src, Len);
  228. } else {
  229. ZeroMemory(CommPkt->Pkt + CommPkt->PktLen, Len);
  230. }
  231. CommPkt->PktLen += Len;
  232. }
  233. BOOL
  234. CommFetchMemory(
  235. IN PCOMM_PACKET CommPkt,
  236. IN PUCHAR Dst,
  237. IN ULONG Len
  238. )
  239. /*++
  240. Routine Description:
  241. Fetch memory from a comm packet, reading as necessary
  242. Arguments:
  243. CommPkt
  244. Dst
  245. Len
  246. Return Value:
  247. None.
  248. --*/
  249. {
  250. #undef DEBSUB
  251. #define DEBSUB "CommFetchMemory:"
  252. PUCHAR Src;
  253. if ((CommPkt->UpkLen > (CommPkt->PktLen - Len)) ||
  254. (Len > CommPkt->PktLen)) {
  255. return FALSE;
  256. }
  257. Src = CommPkt->Pkt + CommPkt->UpkLen;
  258. CommPkt->UpkLen += Len;
  259. //
  260. // Copy into the packet
  261. //
  262. CopyMemory(Dst, Src, Len);
  263. return TRUE;
  264. }
  265. VOID
  266. CommCompletionRoutine(
  267. IN PCOMMAND_PACKET Cmd,
  268. IN PVOID Arg
  269. )
  270. /*++
  271. Routine Description:
  272. Completion routine for comm command servers. Free the
  273. comm packet and then call the generic completion routine
  274. to free the command packet.
  275. Arguments:
  276. Cmd - command packet
  277. Arg - Cmd->CompletionArg
  278. Return Value:
  279. None.
  280. --*/
  281. {
  282. #undef DEBSUB
  283. #define DEBSUB "CommCompletionRoutine:"
  284. PCOMM_PACKET CommPkt = SRCommPkt(Cmd);
  285. PCXTION Cxtion = SRCxtion(Cmd);
  286. COMMAND_SND_COMM_TRACE(4, Cmd, Cmd->ErrorStatus, "SndComplete");
  287. //
  288. // The SndCs and the ReplicaCs cooperate to limit the number of
  289. // active join "pings" so that the Snd threads are not hung
  290. // waiting for pings to dead servers to time out.
  291. //
  292. if ((CommPkt != NULL) &&
  293. (Cxtion != NULL) &&
  294. (CommPkt == Cxtion->ActiveJoinCommPkt)) {
  295. Cxtion->ActiveJoinCommPkt = NULL;
  296. }
  297. //
  298. // Free the comm packet and the attached return response command packet if
  299. // it's still attached. The Replica Cmd Server uses the CMD_JOINING_AFTER_FLUSH
  300. // command in this way.
  301. //
  302. if (CommPkt != NULL) {
  303. FrsFree(CommPkt->Pkt);
  304. FrsFree(CommPkt);
  305. }
  306. if (SRCmd(Cmd)) {
  307. FrsCompleteCommand(SRCmd(Cmd), Cmd->ErrorStatus);
  308. SRCmd(Cmd) = NULL;
  309. }
  310. //
  311. // Free the name/guid and Principal name params.
  312. //
  313. FrsFreeGName(SRTo(Cmd));
  314. FrsFree(SRPrincName(Cmd));
  315. //
  316. // Move the packet to the generic "done" routine
  317. //
  318. FrsSetCompletionRoutine(Cmd, FrsFreeCommand, NULL);
  319. FrsCompleteCommand(Cmd, Cmd->ErrorStatus);
  320. }
  321. PUCHAR
  322. CommGetHdr(
  323. IN PUCHAR Pnext,
  324. IN PUSHORT PCommType,
  325. IN PULONG PLen
  326. )
  327. /*++
  328. Routine Description:
  329. Get and skip a field header
  330. Arguments:
  331. Pnext
  332. PCommType
  333. PLen
  334. Return Value:
  335. Address of the field's data
  336. --*/
  337. {
  338. #undef DEBSUB
  339. #define DEBSUB "CommGetHdr:"
  340. CopyMemory(PCommType, Pnext, sizeof(USHORT));
  341. Pnext += sizeof(USHORT);
  342. CopyMemory(PLen, Pnext, sizeof(ULONG));
  343. Pnext += sizeof(ULONG);
  344. return Pnext;
  345. }
  346. BOOL
  347. CommValidatePkt(
  348. IN PCOMM_PACKET CommPkt
  349. )
  350. /*++
  351. Routine Description:
  352. Check the packet for basic validity (i.e., make sure it is well formed.)
  353. - Confirm that types and sizes of individual elements match with data in
  354. the CommPacketTable.
  355. - Check the value of CommPkt->Major
  356. - Ensure Pkt starts with BOP and ends with EOP
  357. - Check that internal offsets won't exceed the buffer
  358. May modify CommPkt->UpkLen.
  359. Arguments:
  360. CommPkt - pointer to the Comm Packet to validate.
  361. Assumptions:
  362. CommPkt was built either by a call to CommStartCommPkt or via an RPC call
  363. going to SERVER_FrsRpcSendCommPkt. Thus we assume that CommPkt is at least
  364. sizeof(COMM_PACKET) bytes long and that CommPkt->Pkt is CommPkt->PktLen
  365. bytes long.
  366. Return Value:
  367. TRUE - valid pkt (NOTE: this does not necessarily mean the data is
  368. meaningful, just well formed.)
  369. FALSE - invalid
  370. --*/
  371. {
  372. #undef DEBSUB
  373. #define DEBSUB "CommValidatePkt:"
  374. BOOL Result = FALSE;
  375. ULONG OriginalUpkLen = CommPkt->UpkLen;
  376. COMM_TYPE CommType = COMM_NONE;
  377. ULONG CommTypeSize = 0;
  378. ULONG DataSize = 0;
  379. ULONG DecodeType = COMM_DECODE_MAX;
  380. ULONG Size = 0;
  381. //
  382. // CommCheckPkt will:
  383. // - Check the value of CommPkt->Major
  384. // - Ensure Pkt starts with BOP and ends with EOP
  385. // - Check that PktLen does not exceed MemLen
  386. //
  387. if(!CommCheckPkt(CommPkt)) {
  388. Result = FALSE;
  389. DPRINT(4, "++ CommCheckPkt failed. [Invalid CommPkt]\n");
  390. goto exit;
  391. }
  392. //
  393. // At this point we have checked the basic COMM_PACKET structure. Now we
  394. // need to check CommPkt->Pkt.
  395. //
  396. //
  397. // Set CommPkt->UpkLen to zero so we read from the start of the Pkt.
  398. //
  399. CommPkt->UpkLen = 0;
  400. //
  401. // Loop through the data elements of the Pkt.
  402. // We have already assured above that the last element is an EOP.
  403. // It is possible that there is another EOP item before that. We don't
  404. // need to check past that item since nobody should read any of the
  405. // data beyond it.
  406. //
  407. while (CommGetNextElement(CommPkt, &CommType, &CommTypeSize) &&
  408. (CommType != COMM_EOP)) {
  409. //
  410. // Uplevel members could send us comm packet data elements we
  411. // don't handle.
  412. //
  413. if ((CommType >= COMM_MAX) || (CommType == COMM_NONE)) {
  414. if((CommTypeSize > CommPkt->PktLen) ||
  415. (CommPkt->UpkLen > (CommPkt->PktLen - CommTypeSize))) {
  416. //
  417. // This item is claiming to be larger than the remaining
  418. // space in the pkt.
  419. //
  420. Result = FALSE;
  421. DPRINT3(4,
  422. "++ CommTypeSize too large. CommType = %d, CommTypeSize = %d, UpkLen = %d [Invalid CommPkt]\n",
  423. CommType, CommTypeSize, CommPkt->UpkLen);
  424. goto exit;
  425. }
  426. CommPkt->UpkLen += CommTypeSize;
  427. continue;
  428. }
  429. //
  430. // Table index MUST match table CommType Field or table is
  431. // fouled up. This is not an error in the Pkt, rather a problem
  432. // with our internal structs so we assert.
  433. //
  434. FRS_ASSERT(CommType == CommPacketTable[CommType].CommType);
  435. //
  436. // This is the size we expect for this type.
  437. // COMM_SZ_NULL indicates that the size is not predetermined.
  438. //
  439. DataSize = CommPacketTable[CommType].DataSize;
  440. DecodeType = CommPacketTable[CommType].DecodeType;
  441. if((DataSize != COMM_SZ_NULL) && (CommTypeSize != DataSize)) {
  442. DPRINT2(4, "++ Invalid packet element size. CommType = %d, DataSize = %d [Invalid CommPkt]\n",
  443. CommType, CommTypeSize);
  444. Result = FALSE;
  445. goto exit;
  446. }
  447. //
  448. // If we made it this far then we know the type and size are
  449. // consistent. Now we need to check the internals of this element.
  450. //
  451. //
  452. // Only certain types have internal structure to check. Everything
  453. // else is defined completely by the type and size.
  454. //
  455. switch(DecodeType) {
  456. case COMM_DECODE_GNAME:
  457. // GUID_SIZE, GUID, STRING_SIZE, STRING
  458. // GUID_SIZE
  459. if(!CommFetchMemory(CommPkt, (PUCHAR)&Size, sizeof(ULONG))){
  460. DPRINT3(4, "++ COMM_DECODE_GNAME: Cannot read GuidSize. CommType = %d, CommTypeSize = %d UpkLen = %d [Invalid CommPkt]\n",
  461. CommType, CommTypeSize, CommPkt->UpkLen);
  462. Result = FALSE;
  463. goto exit;
  464. }
  465. // Must really be size of a guid
  466. if(Size != sizeof(GUID)) {
  467. DPRINT2(4, "++ COMM_DECODE_GNAME: GuidSize (%d) does not match sizeof GUID (%d) [Invalid CommPkt]\n", Size, sizeof(GUID));
  468. Result = FALSE;
  469. goto exit;
  470. }
  471. //
  472. // Don't need to check the guid data, just increment
  473. // the unpacked length.
  474. //
  475. if((Size > CommPkt->PktLen) ||
  476. (CommPkt->UpkLen > (CommPkt->PktLen - Size))) {
  477. //
  478. // This item is claiming to be larger than the remaining
  479. // space in the pkt.
  480. //
  481. DPRINT3(4,
  482. "++ COMM_DECODE_GNAME GuidSize too large. CommType = %d, GuidSize = %d, UpkLen = %d [Invalid CommPkt]\n",
  483. CommType, Size, CommPkt->UpkLen);
  484. Result = FALSE;
  485. goto exit;
  486. }
  487. CommPkt->UpkLen += Size;
  488. // STRING_SIZE
  489. if(!CommFetchMemory(CommPkt, (PUCHAR)&Size, sizeof(ULONG))){
  490. DPRINT3(4, "++ COMM_DECODE_GNAME: Cannot read StringSize. CommType = %d, CommTypeSize = %d UpkLen = %d [Invalid CommPkt]\n",
  491. CommType, CommTypeSize, CommPkt->UpkLen);
  492. Result = FALSE;
  493. goto exit;
  494. }
  495. // check for a valid size
  496. if((Size > CommPkt->PktLen) ||
  497. (CommPkt->UpkLen > (CommPkt->PktLen - Size))) {
  498. //
  499. // This item is claiming to be larger than the remaining
  500. // space in the pkt.
  501. //
  502. DPRINT3(4,
  503. "++ COMM_DECODE_GNAME StringSize too large. CommType = %d, StringSize = %d, UpkLen = %d [Invalid CommPkt]\n",
  504. CommType, Size, CommPkt->UpkLen);
  505. Result = FALSE;
  506. goto exit;
  507. }
  508. CommPkt->UpkLen += Size;
  509. //
  510. // We're all good.
  511. // On to the next element.
  512. //
  513. break;
  514. case COMM_DECODE_BLOB:
  515. // BLOB_SIZE, BLOB
  516. // BLOB_SIZE
  517. if(!CommFetchMemory(CommPkt, (PUCHAR)&Size, sizeof(ULONG))){
  518. DPRINT3(4, "++ COMM_DECODE_BLOB: Cannot read BlobSize. CommType = %d, CommTypeSize = %d UpkLen = %d [Invalid CommPkt]\n",
  519. CommType, CommTypeSize, CommPkt->UpkLen);
  520. Result = FALSE;
  521. goto exit;
  522. }
  523. // check for a valid size
  524. if((Size > CommPkt->PktLen) ||
  525. (CommPkt->UpkLen > (CommPkt->PktLen - Size))) {
  526. //
  527. // This item is claiming to be larger than the remaining
  528. // space in the pkt.
  529. //
  530. DPRINT3(4,
  531. "++ COMM_DECODE_BLOB BlobSize too large. CommType = %d, BlobSize = %d, UpkLen = %d [Invalid CommPkt]\n",
  532. CommType, Size, CommPkt->UpkLen);
  533. Result = FALSE;
  534. goto exit;
  535. }
  536. CommPkt->UpkLen += Size;
  537. //
  538. // We're all good.
  539. // On to the next element.
  540. //
  541. break;
  542. case COMM_DECODE_VAR_LEN_BLOB:
  543. // BLOB_SIZE, REST_OF_BLOB
  544. // the difference between this and a regular blob is that here
  545. // the size is part of the total blob.
  546. // BLOB_SIZE
  547. if(!CommFetchMemory(CommPkt, (PUCHAR)&Size, sizeof(ULONG))){
  548. DPRINT3(4, "++ COMM_DECODE_VAR_LEN_BLOB: Cannot read BlobSize. CommType = %d, CommTypeSize = %d UpkLen = %d [Invalid CommPkt]\n",
  549. CommType, CommTypeSize, CommPkt->UpkLen);
  550. Result = FALSE;
  551. goto exit;
  552. }
  553. //
  554. // Since the blob size includes the space used to store the
  555. // size itself, it must be at least as big as a ULONG.
  556. //
  557. if(Size < sizeof(ULONG)) {
  558. DPRINT1(4, "++ COMM_DECODE_VAR_LEN_BLOB: BlobSize (%d) too small. [Invalid CommPkt]\n", Size);
  559. Result = FALSE;
  560. goto exit;
  561. }
  562. //
  563. // Size includes the space taken up by BLOB_SIZE
  564. // We already successfully read that, so lets just check that
  565. // the rest of it fits.
  566. //
  567. Size -= sizeof(ULONG);
  568. // check for a valid size
  569. if((Size > CommPkt->PktLen) ||
  570. (CommPkt->UpkLen > (CommPkt->PktLen - Size))) {
  571. //
  572. // This item is claiming to be larger than the remaining
  573. // space in the pkt.
  574. //
  575. DPRINT3(4,
  576. "++ COMM_DECODE_VAR_LEN_BLOB BlobSize too large. CommType = %d, BlobSize = %d, UpkLen = %d [Invalid CommPkt]\n",
  577. CommType, Size, CommPkt->UpkLen);
  578. Result = FALSE;
  579. goto exit;
  580. }
  581. CommPkt->UpkLen += Size;
  582. //
  583. // We're all good.
  584. // On to the next element.
  585. //
  586. break;
  587. case COMM_DECODE_NONE:
  588. // We really shouldn't be getting this, but newer versions
  589. // might have a reason for sending it, so fall through to
  590. // the default case.
  591. default:
  592. // Everything else is just data with no special decoding
  593. if(CommPkt->UpkLen > (CommPkt->PktLen - CommTypeSize)) {
  594. //
  595. // This item is claiming to be larger than the remaining
  596. // space in the pkt.
  597. //
  598. DPRINT4(4,
  599. "++ CommDecodeType = %d, Size too large. CommType = %d, CommTypeSize = %d, UpkLen = %d [Invalid CommPkt]\n",
  600. DecodeType, CommType, CommTypeSize, CommPkt->UpkLen);
  601. Result = FALSE;
  602. goto exit;
  603. }
  604. CommPkt->UpkLen += CommTypeSize;
  605. break;
  606. }
  607. }
  608. if(CommType != COMM_EOP){
  609. //
  610. // We ended on something other than EOP
  611. //
  612. DPRINT1(4, "++ CommPkt does not end with EOP. Ends with CommType = %d [Invalid CommPkt]\n", CommType);
  613. Result = FALSE;
  614. goto exit;
  615. }
  616. Result = TRUE;
  617. exit:
  618. //
  619. // Set the UpkLen back to the original value.
  620. //
  621. CommPkt->UpkLen = OriginalUpkLen;
  622. return Result;
  623. }
  624. BOOL
  625. CommCheckPkt(
  626. IN PCOMM_PACKET CommPkt
  627. )
  628. /*++
  629. Routine Description:
  630. Check the packet for consistency
  631. Arguments:
  632. CommPkt
  633. Return Value:
  634. TRUE - consistent
  635. Otherwise - Assert failure
  636. --*/
  637. {
  638. #undef DEBSUB
  639. #define DEBSUB "CommCheckPkt:"
  640. ULONG Len;
  641. ULONG Data;
  642. PUCHAR Pfirst;
  643. PUCHAR Pnext;
  644. PUCHAR Pend;
  645. USHORT CommType;
  646. if (!CommPkt) {
  647. return FALSE;
  648. }
  649. //
  650. // Check major. Mismatched majors cannot be handled.
  651. //
  652. if (CommPkt->Major != NtFrsMajor) {
  653. DPRINT2(3, "WARN - RpcCommPkt: MAJOR MISMATCH %d major does not match %d; ignoring\n",
  654. CommPkt->Major, NtFrsMajor);
  655. return FALSE;
  656. }
  657. //
  658. // Check minor. This service can process packets with mismatched
  659. // minors, although some functionality may be lost.
  660. //
  661. if (CommPkt->Minor != NtFrsCommMinor) {
  662. DPRINT2(5, "RpcCommPkt: MINOR MISMATCH %d minor does not match %d\n",
  663. CommPkt->Minor, NtFrsCommMinor);
  664. }
  665. //
  666. // Compare the length of the packet with its memory allocation
  667. //
  668. if (CommPkt->PktLen > CommPkt->MemLen) {
  669. DPRINT2(4, "RpcCommPkt: Packet size (%d) > Alloced Memory (%d)\n",
  670. CommPkt->PktLen, CommPkt->MemLen);
  671. return FALSE;
  672. }
  673. //
  674. // Must have at least a beginning-of-packet and end-of-packet field
  675. //
  676. if (CommPkt->PktLen < MIN_COMM_PACKET_SIZE) {
  677. DPRINT2(4, "RpcCommPkt: Packet size (%d) < Minimum size (%d)\n",
  678. CommPkt->PktLen, MIN_COMM_PACKET_SIZE);
  679. return FALSE;
  680. }
  681. //
  682. // packets begin with a beginning-of-packet
  683. //
  684. Pfirst = CommPkt->Pkt;
  685. Pnext = CommGetHdr(Pfirst, &CommType, &Len);
  686. if (CommType != COMM_BOP || Len != sizeof(ULONG)) {
  687. return FALSE;
  688. }
  689. CopyMemory(&Data, Pnext, sizeof(ULONG));
  690. if (Data != 0) {
  691. return FALSE;
  692. }
  693. //
  694. // packets end with an end-of-packet
  695. //
  696. Pend = Pfirst + CommPkt->PktLen;
  697. if (Pend <= Pfirst) {
  698. return FALSE;
  699. }
  700. Pnext = ((Pend - sizeof(USHORT)) - sizeof(ULONG)) - sizeof(ULONG);
  701. Pnext = CommGetHdr(Pnext, &CommType, &Len);
  702. if (CommType != COMM_EOP || Len != sizeof(ULONG)) {
  703. return FALSE;
  704. }
  705. CopyMemory(&Data, Pnext, sizeof(ULONG));
  706. if (Data != COMM_NULL_DATA) {
  707. return FALSE;
  708. }
  709. return TRUE;
  710. }
  711. VOID
  712. CommDumpCommPkt(
  713. IN PCOMM_PACKET CommPkt,
  714. IN DWORD NumDump
  715. )
  716. /*++
  717. Routine Description:
  718. Dump some of the comm packet
  719. Arguments:
  720. CommPkt
  721. NumDump
  722. Return Value:
  723. None.
  724. --*/
  725. {
  726. #undef DEBSUB
  727. #define DEBSUB "CommDumpCommPkt:"
  728. ULONG Len;
  729. PUCHAR Pnext;
  730. USHORT CommType;
  731. DWORD i;
  732. DPRINT1(0, "%x:\n", CommPkt);
  733. DPRINT1(0, "\tMajor: %d\n", CommPkt->Major);
  734. DPRINT1(0, "\tMinor: %d\n", CommPkt->Minor);
  735. DPRINT1(0, "\tMemLen: %d\n", CommPkt->MemLen);
  736. DPRINT1(0, "\tPktLen: %d\n", CommPkt->PktLen);
  737. DPRINT1(0, "\tPkt: 0x%x\n", CommPkt->Pkt);
  738. //
  739. // packets begin with a beginning-of-packet
  740. //
  741. Pnext = CommPkt->Pkt;
  742. for (i = 0; i < NumDump; ++i) {
  743. Pnext = CommGetHdr(Pnext, &CommType, &Len);
  744. DPRINT4(0, "Dumping %d for %x: %d %d\n", i, CommPkt, CommType, Len);
  745. Pnext += Len;
  746. }
  747. }
  748. VOID
  749. CommPackULong(
  750. IN PCOMM_PACKET CommPkt,
  751. IN COMM_TYPE Type,
  752. IN ULONG Data
  753. )
  754. /*++
  755. Routine Description:
  756. Copy a header and a ulong into the comm packet.
  757. Arguments:
  758. CommPkt
  759. Type
  760. Data
  761. Return Value:
  762. None.
  763. --*/
  764. {
  765. #undef DEBSUB
  766. #define DEBSUB "CommPackULong:"
  767. ULONG Len = sizeof(ULONG);
  768. USHORT CommType = (USHORT)Type;
  769. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  770. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  771. CommCopyMemory(CommPkt, (PUCHAR)&Data, sizeof(ULONG));
  772. }
  773. PCOMM_PACKET
  774. CommStartCommPkt(
  775. IN PWCHAR Name
  776. )
  777. /*++
  778. Routine Description:
  779. Allocate a comm packet.
  780. Arguments:
  781. Name
  782. Return Value:
  783. Address of a comm packet.
  784. --*/
  785. {
  786. #undef DEBSUB
  787. #define DEBSUB "CommStartCommPkt:"
  788. ULONG Size;
  789. PCOMM_PACKET CommPkt;
  790. //
  791. // We can create a comm packet in a file or in memory
  792. //
  793. CommPkt = FrsAlloc(sizeof(COMM_PACKET));
  794. Size = COMM_MEM_SIZE;
  795. CommPkt->Pkt = FrsAlloc(Size);
  796. CommPkt->MemLen = Size;
  797. CommPkt->Major = NtFrsMajor;
  798. CommPkt->Minor = NtFrsCommMinor;
  799. //
  800. // Pack the beginning-of-packet
  801. //
  802. CommPackULong(CommPkt, COMM_BOP, 0);
  803. return CommPkt;
  804. }
  805. BOOL
  806. CommUnpackBlob(
  807. IN PCOMM_PACKET CommPkt,
  808. OUT ULONG *OutBlobSize,
  809. OUT PVOID *OutBlob
  810. )
  811. /*++
  812. Routine Description:
  813. Unpack a blob (length + data)
  814. Arguments:
  815. CommPkt
  816. OutBlobSize - size of blob from comm packet
  817. OutBlob - data from comm packet
  818. Return Value:
  819. TRUE - Blob retrieved from comm packet
  820. FALSE - Blob was not retrieved from comm packet; bad comm packet
  821. --*/
  822. {
  823. #undef DEBSUB
  824. #define DEBSUB "CommUnpackBlob:"
  825. ULONG BlobSize;
  826. //
  827. // Initialize return params
  828. //
  829. *OutBlob = NULL;
  830. //
  831. // Unpack the length of the blob
  832. //
  833. if (!CommFetchMemory(CommPkt, (PUCHAR)OutBlobSize, sizeof(ULONG))) {
  834. return FALSE;
  835. }
  836. BlobSize = *OutBlobSize;
  837. //
  838. // Empty blob, return NULL
  839. //
  840. if (BlobSize == 0) {
  841. return TRUE;
  842. }
  843. //
  844. // Allocate memory for the blob
  845. //
  846. *OutBlob = FrsAlloc(BlobSize);
  847. //
  848. // Unpack the blob
  849. //
  850. return CommFetchMemory(CommPkt, (PUCHAR)*OutBlob, BlobSize);
  851. }
  852. BOOL
  853. CommUnpackVariableLengthBlob(
  854. IN PCOMM_PACKET CommPkt,
  855. OUT ULONG *OutBlobSize,
  856. OUT PVOID *OutBlob
  857. )
  858. /*++
  859. Routine Description:
  860. Unpack a blob (length + data)
  861. Arguments:
  862. CommPkt
  863. OutBlobSize - size of blob from comm packet
  864. OutBlob - data from comm packet
  865. Return Value:
  866. TRUE - Blob retrieved from comm packet
  867. FALSE - Blob was not retrieved from comm packet; bad comm packet
  868. --*/
  869. {
  870. #undef DEBSUB
  871. #define DEBSUB "CommUnpackVariableLengthBlob:"
  872. ULONG BlobSize;
  873. //
  874. // Initialize return params
  875. //
  876. *OutBlob = NULL;
  877. //
  878. // Unpack the length of the blob
  879. //
  880. if ((CommPkt->UpkLen + sizeof(ULONG)) > CommPkt->PktLen) {
  881. return FALSE;
  882. }
  883. *OutBlobSize = *((ULONG UNALIGNED *)(CommPkt->Pkt + CommPkt->UpkLen));
  884. BlobSize = *OutBlobSize;
  885. //
  886. // Empty blob, return NULL
  887. //
  888. if (BlobSize == 0) {
  889. return TRUE;
  890. }
  891. //
  892. // Allocate memory for the blob
  893. //
  894. *OutBlob = FrsAlloc(BlobSize);
  895. //
  896. // Unpack the blob
  897. //
  898. return CommFetchMemory(CommPkt, (PUCHAR)*OutBlob, BlobSize);
  899. }
  900. BOOL
  901. CommUnpackGName(
  902. IN PCOMM_PACKET CommPkt,
  903. OUT PGNAME *OutGName
  904. )
  905. /*++
  906. Routine Description:
  907. Unpack the guid and wide char string that make up a gstring
  908. Arguments:
  909. CommPkt
  910. OutGName - From comm packet
  911. Return Value:
  912. TRUE - GName fetched from comm packet successfully
  913. FALSE - GName was not fetched from comm packet; bad comm packet
  914. --*/
  915. {
  916. #undef DEBSUB
  917. #define DEBSUB "CommUnpackGName:"
  918. ULONG BlobSize;
  919. PGNAME GName;
  920. //
  921. // Allocate a gstring (caller cleans up on error)
  922. //
  923. *OutGName = GName = FrsAlloc(sizeof(GNAME));
  924. if (!CommUnpackBlob(CommPkt, &BlobSize, &GName->Guid) ||
  925. BlobSize != sizeof(GUID)) {
  926. return FALSE;
  927. }
  928. if (!CommUnpackBlob(CommPkt, &BlobSize, &GName->Name) ||
  929. GName->Name[(BlobSize / sizeof(WCHAR)) - 1] != L'\0') {
  930. return FALSE;
  931. }
  932. return TRUE;
  933. }
  934. BOOL
  935. CommGetNextElement(
  936. IN PCOMM_PACKET CommPkt,
  937. OUT COMM_TYPE *CommType,
  938. OUT ULONG *CommTypeSize
  939. )
  940. /*++
  941. Routine Description:
  942. Advance to the next field in the comm packet
  943. Arguments:
  944. CommPkt
  945. CommType - type of packed field
  946. CommTypeSize - size of packed field (excluding type and size)
  947. Return Value:
  948. TRUE - CommType and CommTypeSize were unpacked
  949. FALSE - Could not unpack; bad comm packet
  950. --*/
  951. {
  952. #undef DEBSUB
  953. #define DEBSUB "CommGetNextElement:"
  954. USHORT Ushort;
  955. //
  956. // Find the type and length of this entry
  957. //
  958. if (CommFetchMemory(CommPkt, (PUCHAR)&Ushort, sizeof(USHORT)) &&
  959. CommFetchMemory(CommPkt, (PUCHAR)CommTypeSize, sizeof(ULONG))) {
  960. *CommType = Ushort;
  961. return TRUE;
  962. }
  963. return FALSE;
  964. }
  965. VOID
  966. CommInsertDataElement(
  967. IN PCOMM_PACKET CommPkt,
  968. IN COMM_TYPE CommType,
  969. IN PVOID CommData,
  970. IN ULONG CommDataLen
  971. )
  972. /*++
  973. Routine Description:
  974. Insert the data supplied using the CommType specific format into the
  975. Comm packet.
  976. Arguments:
  977. CommPkt - The Comm packet structure.
  978. CommType - The data type for this element.
  979. CommData - The address of the data.
  980. CommDataLen - The size for var len elements.
  981. Return Value:
  982. None.
  983. --*/
  984. {
  985. #undef DEBSUB
  986. #define DEBSUB "CommInsertDataElement:"
  987. ULONG Len;
  988. PGNAME GName;
  989. ULONG LenGuid;
  990. ULONG LenName;
  991. ULONG DataSize;
  992. ULONG DecodeType;
  993. PCHAR CommTag;
  994. if (CommData == NULL) {
  995. return;
  996. }
  997. FRS_ASSERT((CommType < COMM_MAX) && (CommType != COMM_NONE));
  998. //
  999. // Table index MUST match table CommType Field or table is fouled up.
  1000. //
  1001. FRS_ASSERT(CommType == CommPacketTable[CommType].CommType);
  1002. //
  1003. // Length check from table for fixed length fields.
  1004. //
  1005. //DataSize = CommPacketTable[CommType].DataSize;
  1006. //FRS_ASSERT((DataSize == COMM_SZ_NULL) || (CommDataLen == DataSize));
  1007. //
  1008. // Insert the data using the data type encoding.
  1009. //
  1010. DecodeType = CommPacketTable[CommType].DecodeType;
  1011. CommTag = CommPacketTable[CommType].CommTag;
  1012. switch (DecodeType) {
  1013. //
  1014. // Insert a ULONG size piece of data.
  1015. //
  1016. case COMM_DECODE_ULONG:
  1017. case COMM_DECODE_ULONG_TO_USHORT:
  1018. Len = sizeof(ULONG);
  1019. DPRINT2(5, ":SR: Dec_long: type: %s, len: %d\n", CommTag, Len);
  1020. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  1021. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  1022. CommCopyMemory(CommPkt, (PUCHAR)CommData, sizeof(ULONG));
  1023. break;
  1024. //
  1025. // Insert a Guid and Name string (GNAME).
  1026. //
  1027. case COMM_DECODE_GNAME:
  1028. GName = (PGNAME)CommData;
  1029. LenGuid = sizeof(GUID);
  1030. LenName = (wcslen(GName->Name) + 1) * sizeof(WCHAR);
  1031. Len = LenGuid + LenName + (2 * sizeof(ULONG));
  1032. DPRINT3(5, ":SR: Dec_gname: type: %s, len: %d - %ws\n", CommTag, Len, GName->Name);
  1033. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  1034. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  1035. CommCopyMemory(CommPkt, (PUCHAR)&LenGuid, sizeof(ULONG));
  1036. CommCopyMemory(CommPkt, (PUCHAR)GName->Guid, LenGuid);
  1037. CommCopyMemory(CommPkt, (PUCHAR)&LenName, sizeof(ULONG));
  1038. CommCopyMemory(CommPkt, (PUCHAR)GName->Name, LenName);
  1039. break;
  1040. //
  1041. // Insert a ULONGLONG.
  1042. //
  1043. case COMM_DECODE_ULONGLONG:
  1044. Len = sizeof(ULONGLONG);
  1045. DPRINT2(5, ":SR: Dec_longlong: type: %s, len: %d\n", CommTag, Len);
  1046. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  1047. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  1048. CommCopyMemory(CommPkt, (PUCHAR)CommData, sizeof(ULONGLONG));
  1049. break;
  1050. //
  1051. // Insert a Guid.
  1052. //
  1053. case COMM_DECODE_GUID:
  1054. Len = sizeof(GUID);
  1055. DPRINT2(5, ":SR: Dec_Guid: type: %s, len: %d\n", CommTag, Len);
  1056. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  1057. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  1058. CommCopyMemory(CommPkt, (PUCHAR)CommData, sizeof(GUID));
  1059. break;
  1060. case COMM_DECODE_VVECTOR:
  1061. //
  1062. // Version Vector data gets inserted into Comm packet as blobs.
  1063. //
  1064. NOTHING;
  1065. /* FALL THRU INTENDED */
  1066. //
  1067. // Insert a variable length BLOB. The problem with blobs as currently
  1068. // shipped in win2k is that the code on the unpack side checks for a
  1069. // match on a constant length based on the COMM Data Type. This means
  1070. // that a var len datatype like CHANGE_ORDER_EXTENSION can't change because
  1071. // the 40 byte size is wired into the code of down level members. Sigh.
  1072. //
  1073. case COMM_DECODE_BLOB:
  1074. Len = CommDataLen + sizeof(ULONG);
  1075. DPRINT2(5, ":SR: Dec_blob: type: %s, len: %d\n", CommTag, Len);
  1076. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  1077. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  1078. CommCopyMemory(CommPkt, (PUCHAR)&CommDataLen, sizeof(ULONG));
  1079. CommCopyMemory(CommPkt, (PUCHAR)CommData, CommDataLen);
  1080. break;
  1081. //
  1082. // Insert a true variable length data struct that is extensible.
  1083. // The actual length comes from the first DWORD of the data.
  1084. //
  1085. case COMM_DECODE_VAR_LEN_BLOB:
  1086. Len = *(PULONG)CommData;
  1087. DPRINT2(5, ":SR: Dec_var_len_blob: type: %s, len: %d\n", CommTag, Len);
  1088. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  1089. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  1090. CommCopyMemory(CommPkt, (PUCHAR)CommData, Len);
  1091. break;
  1092. //
  1093. // The CO contains four pointers occupying 16 bytes on 32 bit architectures and
  1094. // 32 bytes on 64 bit architectures (PART2). When the CO is sent in a comm packet
  1095. // the contents of these pointers are irrelevant so in comm packets these
  1096. // ptrs are always sent as 16 bytes of zeros, regardless of architecture.
  1097. // Note - In 32 bit Win2k this was sent as a BLOB so it matches BLOB format.
  1098. //
  1099. case COMM_DECODE_REMOTE_CO:
  1100. Len = COMM_SZ_COC;
  1101. CommDataLen = Len - sizeof(ULONG);
  1102. DPRINT2(4, ":SR: Dec_remote_co: type: %s, len: %d\n", CommTag, Len);
  1103. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  1104. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  1105. CommCopyMemory(CommPkt, (PUCHAR)&CommDataLen, sizeof(ULONG));
  1106. CommCopyMemory(CommPkt, (PUCHAR)CommData, sizeof(CHANGE_ORDER_COMMAND));
  1107. //CommCopyMemory(CommPkt, ((PUCHAR)CommData)+CO_PART1_OFFSET, CO_PART1_SIZE);
  1108. //CommCopyMemory(CommPkt, NULL, CO_PART2_SIZE);
  1109. //CommCopyMemory(CommPkt, ((PUCHAR)CommData)+CO_PART3_OFFSET, CO_PART3_SIZE);
  1110. break;
  1111. default:
  1112. //
  1113. // Table must be fouled up.
  1114. //
  1115. FRS_ASSERT((DecodeType > COMM_DECODE_NONE) && (DecodeType < COMM_DECODE_MAX));
  1116. break;
  1117. }
  1118. return;
  1119. }
  1120. PCOMM_PACKET
  1121. CommBuildCommPkt(
  1122. IN PREPLICA Replica,
  1123. IN PCXTION Cxtion,
  1124. IN ULONG Command,
  1125. IN PGEN_TABLE VVector,
  1126. IN PCOMMAND_PACKET Cmd,
  1127. IN PCHANGE_ORDER_COMMAND Coc
  1128. )
  1129. /*++
  1130. Routine Description:
  1131. Generate a comm packet with the info needed to execute the
  1132. command on the remote machine identified by Cxtion.
  1133. Arguments:
  1134. Replica - Sender
  1135. Cxtion - identifies the remote machine
  1136. Command - command to execute on the remote machine
  1137. VVector - some commands require the version vector
  1138. Cmd - original command packet
  1139. Coc - change order command
  1140. RemoteGVsn - guid/vsn pair
  1141. Return Value:
  1142. Address of a comm packet.
  1143. --*/
  1144. {
  1145. #undef DEBSUB
  1146. #define DEBSUB "CommBuildCommPkt:"
  1147. ULONGLONG FileTime;
  1148. GNAME GName;
  1149. PVOID Key;
  1150. PCOMM_PACKET CommPkt;
  1151. PGVSN GVsn;
  1152. PGEN_ENTRY Entry;
  1153. //
  1154. // Allocate and initialize a comm packet
  1155. //
  1156. CommPkt = CommStartCommPkt(NULL);
  1157. CommPkt->CsId = CS_RS;
  1158. CommInsertDataElement(CommPkt, COMM_COMMAND, &Command, 0);
  1159. CommInsertDataElement(CommPkt, COMM_TO, Cxtion->Partner, 0);
  1160. CommInsertDataElement(CommPkt, COMM_FROM, Replica->MemberName, 0);
  1161. GName.Guid = Cxtion->Partner->Guid;
  1162. GName.Name = Replica->ReplicaName->Name;
  1163. CommInsertDataElement(CommPkt, COMM_REPLICA, &GName, 0);
  1164. CommInsertDataElement(CommPkt, COMM_CXTION, Cxtion->Name, 0);
  1165. CommInsertDataElement(CommPkt, COMM_JOIN_GUID, &Cxtion->JoinGuid, sizeof(GUID));
  1166. CommInsertDataElement(CommPkt, COMM_LAST_JOIN_TIME, &Cxtion->LastJoinTime, 0);
  1167. //
  1168. // Version vector (if supplied)
  1169. //
  1170. //
  1171. // The caller is building a comm packet for join operation,
  1172. // automatically include the current time and the originator guid.
  1173. //
  1174. if (VVector) {
  1175. Key = NULL;
  1176. while (GVsn = GTabNextDatum(VVector, &Key)) {
  1177. CommInsertDataElement(CommPkt, COMM_VVECTOR, GVsn, sizeof(GVSN));
  1178. }
  1179. GetSystemTimeAsFileTime((FILETIME *)&FileTime);
  1180. CommInsertDataElement(CommPkt, COMM_JOIN_TIME, &FileTime, sizeof(ULONGLONG));
  1181. DPRINT1(4, ":X: Comm join time is %08x %08x\n", PRINTQUAD(FileTime));
  1182. CommInsertDataElement(CommPkt, COMM_REPLICA_VERSION_GUID,
  1183. &Replica->ReplicaVersionGuid, sizeof(GUID));
  1184. //
  1185. // Insert the list of Guids for compression algorithms that we understand.
  1186. //
  1187. GTabLockTable(CompressionTable);
  1188. Key = NULL;
  1189. while (Entry = GTabNextEntryNoLock(CompressionTable, &Key)) {
  1190. CommInsertDataElement(CommPkt, COMM_COMPRESSION_GUID, Entry->Key1, 0);
  1191. }
  1192. GTabUnLockTable(CompressionTable);
  1193. }
  1194. if (Cmd) {
  1195. CommInsertDataElement(CommPkt, COMM_BLOCK, RsBlock(Cmd), (ULONG)RsBlockSize(Cmd));
  1196. CommInsertDataElement(CommPkt, COMM_BLOCK_SIZE, &RsBlockSize(Cmd), 0);
  1197. CommInsertDataElement(CommPkt, COMM_FILE_SIZE, &RsFileSize(Cmd).QuadPart, 0);
  1198. CommInsertDataElement(CommPkt, COMM_FILE_OFFSET, &RsFileOffset(Cmd).QuadPart, 0);
  1199. CommInsertDataElement(CommPkt, COMM_GVSN, RsGVsn(Cmd), sizeof(GVSN));
  1200. CommInsertDataElement(CommPkt, COMM_CO_GUID, RsCoGuid(Cmd), sizeof(GUID));
  1201. CommInsertDataElement(CommPkt, COMM_CO_SEQUENCE_NUMBER, &RsCoSn(Cmd), 0);
  1202. CommInsertDataElement(CommPkt, COMM_MD5_DIGEST, RsMd5Digest(Cmd), MD5DIGESTLEN);
  1203. }
  1204. //
  1205. // Change Order Command
  1206. //
  1207. if (Coc) {
  1208. CommInsertDataElement(CommPkt, COMM_REMOTE_CO, Coc, 0);
  1209. if (Cxtion->PartnerMinor <= NTFRS_COMM_MINOR_4) {
  1210. //
  1211. // Convert the CHANGE_ORDER_RECORD_EXTENSION struct to a
  1212. // CO_RECORD_EXTENSION_WIN2K struct that downlevel members will
  1213. // understand. This is necessary because downlevel members want to
  1214. // check the size of the comm data element which makes it
  1215. // impossible to change the size of the CO_RECORD_EXTENSION_WIN2K
  1216. // structure. So the CHANGE_ORDER_RECORD_EXTENSION data element
  1217. // was added for post win2k members that is extensible. see
  1218. // comments in schema.h. see additional comments in frs.h re:
  1219. // NTFRS_COMM_MINOR rev levels.
  1220. //
  1221. if (Coc->Extension->Major != CO_RECORD_EXTENSION_VERSION_WIN2K) {
  1222. PCO_RECORD_EXTENSION_WIN2K CocExtW2K;
  1223. CocExtW2K = DbsDataConvertCocExtensionToWin2K(Coc->Extension);
  1224. CommInsertDataElement(CommPkt, COMM_CO_EXT_WIN2K, CocExtW2K,
  1225. sizeof(CO_RECORD_EXTENSION_WIN2K));
  1226. FrsFree(CocExtW2K);
  1227. } else {
  1228. CommInsertDataElement(CommPkt, COMM_CO_EXT_WIN2K, Coc->Extension,
  1229. sizeof(CO_RECORD_EXTENSION_WIN2K));
  1230. }
  1231. } else {
  1232. DWORD OldCount;
  1233. PDATA_EXTENSION_RETRY_TIMEOUT CoCmdRetryTimeout;
  1234. //
  1235. // For post win2k level members the CO extension info should be sent
  1236. // as follows since the length comes from the first dword of the data.
  1237. //
  1238. CoCmdRetryTimeout = DbsDataExtensionFind(Coc->Extension, DataExtend_Retry_Timeout);
  1239. //
  1240. // Zero out the count so that we start fresh on the next machine.
  1241. // But we don't want to overwrite the current count on this machine!
  1242. //
  1243. if(CoCmdRetryTimeout != NULL) {
  1244. OldCount = CoCmdRetryTimeout->Count;
  1245. CoCmdRetryTimeout->Count = 0;
  1246. }
  1247. CommInsertDataElement(CommPkt, COMM_CO_EXTENSION_2, Coc->Extension, 0);
  1248. if(CoCmdRetryTimeout != NULL) {
  1249. CoCmdRetryTimeout->Count = OldCount;
  1250. }
  1251. }
  1252. }
  1253. //
  1254. // Terminate the packet with EOP Ulong.
  1255. //
  1256. CommPackULong(CommPkt, COMM_EOP, COMM_NULL_DATA);
  1257. return CommPkt;
  1258. }
  1259. PCOMMAND_PACKET
  1260. CommPktToCmd(
  1261. IN PCOMM_PACKET CommPkt
  1262. )
  1263. /*++
  1264. Routine Description:
  1265. Unpack the data in a Comm packet and store it into a command struct.
  1266. Arguments:
  1267. CommPkt
  1268. Return Value:
  1269. Address of a command packet or NULL if unpack failed.
  1270. --*/
  1271. {
  1272. #undef DEBSUB
  1273. #define DEBSUB "CommPktToCmd:"
  1274. GUID *pTempGuid;
  1275. PCOMMAND_PACKET Cmd = NULL;
  1276. ULONG BlobSize;
  1277. PVOID Blob;
  1278. ULONG CommTypeSize;
  1279. COMM_TYPE CommType;
  1280. ULONG DataSize;
  1281. ULONG DecodeType;
  1282. ULONG NativeOffset;
  1283. PUCHAR DataDest;
  1284. ULONG TempUlong;
  1285. BOOL b;
  1286. GNAME GName;
  1287. PCHAR CommTag;
  1288. PUCHAR CommData;
  1289. PGEN_TABLE GTable;
  1290. //
  1291. // Create the command packet
  1292. //
  1293. Cmd = FrsAllocCommand(&ReplicaCmdServer.Queue, CMD_UNKNOWN);
  1294. FrsSetCompletionRoutine(Cmd, RcsCmdPktCompletionRoutine, NULL);
  1295. //
  1296. // Scan the comm packet from the beginning
  1297. //
  1298. CommPkt->UpkLen = 0;
  1299. b = TRUE;
  1300. while (CommGetNextElement(CommPkt, &CommType, &CommTypeSize) &&
  1301. CommType != COMM_EOP) {
  1302. //
  1303. // Uplevel members could send us comm packet data elements we don't handle.
  1304. //
  1305. if ((CommType >= COMM_MAX) || (CommType == COMM_NONE)) {
  1306. DPRINT2(0, "++ WARN - Skipping invalid comm packet element type. CommType = %d, From %ws\n",
  1307. CommType, RsFrom(Cmd) ? RsFrom(Cmd)->Name : L"<unknown>");
  1308. CommPkt->UpkLen += CommTypeSize;
  1309. b = !(CommPkt->UpkLen > CommPkt->PktLen || CommTypeSize > CommPkt->PktLen);
  1310. goto NEXT_ELEMENT;
  1311. }
  1312. //
  1313. // Table index MUST match table CommType Field or table is fouled up.
  1314. //
  1315. FRS_ASSERT(CommType == CommPacketTable[CommType].CommType);
  1316. DataSize = CommPacketTable[CommType].DataSize;
  1317. if ((DataSize != COMM_SZ_NULL) && (CommTypeSize != DataSize)) {
  1318. DPRINT3(0, "++ WARN - Invalid comm packet size. CommType = %d, DataSize = %d, From %ws\n",
  1319. CommType, CommTypeSize,
  1320. RsFrom(Cmd) ? RsFrom(Cmd)->Name : L"<unknown>");
  1321. goto CLEANUP_ON_ERROR;
  1322. }
  1323. //
  1324. // Calc the data offset in the Cmd struct to store the data.
  1325. //
  1326. NativeOffset = CommPacketTable[CommType].NativeOffset;
  1327. if (NativeOffset == RsOffsetSkip) {
  1328. CommPkt->UpkLen += CommTypeSize;
  1329. b = !(CommPkt->UpkLen > CommPkt->PktLen || CommTypeSize > CommPkt->PktLen);
  1330. goto NEXT_ELEMENT;
  1331. }
  1332. DataDest = (PUCHAR) Cmd + NativeOffset;
  1333. //
  1334. // Decode the data element and store it in Cmd at the NativeOffset.
  1335. //
  1336. DecodeType = CommPacketTable[CommType].DecodeType;
  1337. CommTag = CommPacketTable[CommType].CommTag;
  1338. //DPRINT6(5, ":SR: CommType: %s, Size: %d, Cmd offset: %d, data dest: %08x, Pkt->UpkLen = %d, Pkt->PktLen = %d\n",
  1339. // CommTag, CommTypeSize, NativeOffset,
  1340. // DataDest, CommPkt->UpkLen, CommPkt->PktLen);
  1341. switch (DecodeType) {
  1342. case COMM_DECODE_ULONG:
  1343. b = CommFetchMemory(CommPkt, DataDest, sizeof(ULONG));
  1344. DPRINT2(5, ":SR: rcv Dec_long: %s data: %d\n", CommTag, *(PULONG)DataDest);
  1345. break;
  1346. case COMM_DECODE_ULONG_TO_USHORT:
  1347. b = CommFetchMemory(CommPkt, (PUCHAR)&TempUlong, sizeof(ULONG));
  1348. * ((PUSHORT) DataDest) = (USHORT)TempUlong;
  1349. DPRINT2(5, ":SR: rcv Dec_ulong_to_ushort: %s data: %d\n", CommTag, TempUlong);
  1350. break;
  1351. case COMM_DECODE_GNAME:
  1352. *(PVOID *)DataDest = FrsFreeGName(*(PVOID *)DataDest);
  1353. b = CommUnpackGName(CommPkt, (PGNAME *) DataDest);
  1354. GName.Guid = (*(PGNAME *)DataDest)->Guid;
  1355. GName.Name = (*(PGNAME *)DataDest)->Name;
  1356. DPRINT2(5, ":SR: rcv Dec_Gname: %s name: %ws\n", CommTag, GName.Name);
  1357. break;
  1358. case COMM_DECODE_BLOB:
  1359. *(PVOID *)DataDest = FrsFree(*(PVOID *)DataDest);
  1360. b = CommUnpackBlob(CommPkt, &BlobSize, (PVOID *) DataDest);
  1361. DPRINT2(5, ":SR: rcv Dec_blob: BlobSize: %08x data: %08x\n", BlobSize, *(PULONG)DataDest);
  1362. break;
  1363. case COMM_DECODE_VAR_LEN_BLOB:
  1364. *(PVOID *)DataDest = FrsFree(*(PVOID *)DataDest);
  1365. b = CommUnpackVariableLengthBlob(CommPkt, &BlobSize, (PVOID *) DataDest);
  1366. DPRINT2(5, ":SR: rcv Dec_blob: BlobSize: %08x data: %08x\n", BlobSize, *(PULONG)DataDest);
  1367. break;
  1368. case COMM_DECODE_ULONGLONG:
  1369. b = CommFetchMemory(CommPkt, DataDest, sizeof(ULONGLONG));
  1370. DPRINT2(5, ":SR: rcv Dec_long_long: %s data: %08x %08x\n", CommTag,
  1371. PRINTQUAD(*(PULONGLONG)DataDest));
  1372. break;
  1373. //
  1374. // Version Vector data gets unpacked and inserted into Table.
  1375. //
  1376. case COMM_DECODE_VVECTOR:
  1377. GTable = *(PGEN_TABLE *)(DataDest);
  1378. if (GTable == NULL) {
  1379. GTable = GTabAllocTable();
  1380. *(PGEN_TABLE *)(DataDest) = GTable;
  1381. }
  1382. b = CommUnpackBlob(CommPkt, &BlobSize, &Blob);
  1383. DPRINT2(5, ":SR: rcv Dec_VV: %s bloblen: %d\n", CommTag, BlobSize);
  1384. if (b) {
  1385. VVInsertOutbound(GTable, Blob);
  1386. }
  1387. break;
  1388. //
  1389. // Compression Guid data gets unpacked and inserted into table.
  1390. //
  1391. case COMM_DECODE_GUID:
  1392. if (CommType == COMM_COMPRESSION_GUID) {
  1393. GTable = *(PGEN_TABLE *)(DataDest);
  1394. if (GTable == NULL) {
  1395. GTable = GTabAllocTable();
  1396. *(PGEN_TABLE *)(DataDest) = GTable;
  1397. }
  1398. pTempGuid = FrsAlloc(sizeof(GUID));
  1399. b = CommFetchMemory(CommPkt, (PUCHAR)pTempGuid, sizeof(GUID));
  1400. DPRINT2(5, ":SR: rcv Comp_Guid: %s bloblen: %d\n", CommTag, BlobSize);
  1401. if (b) {
  1402. GTabInsertEntry(GTable, NULL, pTempGuid, NULL);
  1403. }
  1404. } else {
  1405. //
  1406. // Else the guid gets stashed in the data dest.
  1407. //
  1408. b = CommFetchMemory(CommPkt, DataDest, sizeof(GUID));
  1409. DPRINT1(5, ":SR: rcv Guid: %s \n", CommTag);
  1410. }
  1411. break;
  1412. //
  1413. // The CO contains four pointers occupying 16 bytes on 32 bit architectures
  1414. // and 32 bytes on 64 bit architectures (PART2). When the CO is sent
  1415. // in a comm packet the contents of these pointers are irrelevant so in
  1416. // comm packets these ptrs are always sent as 16 bytes of zeros,
  1417. // regardless of architecture.
  1418. // Note - In 32 bit Win2k this was sent as a BLOB so it matches BLOB format.
  1419. //
  1420. case COMM_DECODE_REMOTE_CO:
  1421. *(PVOID *)DataDest = FrsFree(*(PVOID *)DataDest);
  1422. //
  1423. // Unpack the length of the CO and then unpack the CO data.
  1424. //
  1425. b = CommFetchMemory(CommPkt, (PUCHAR)&BlobSize, sizeof(ULONG));
  1426. if (!b || (BlobSize == 0)) {
  1427. break;
  1428. }
  1429. CommData = FrsAlloc(sizeof(CHANGE_ORDER_COMMAND));
  1430. CommFetchMemory(CommPkt, (PUCHAR)CommData, sizeof(CHANGE_ORDER_COMMAND));
  1431. //CommFetchMemory(CommPkt, ((PUCHAR)CommData)+CO_PART1_OFFSET, CO_PART1_SIZE);
  1432. //CommFetchMemory(CommPkt, ((PUCHAR)CommData)+CO_PART2_OFFSET, CO_PART2_SIZE);
  1433. //CommFetchMemory(CommPkt, ((PUCHAR)CommData)+CO_PART3_OFFSET, CO_PART3_SIZE);
  1434. DPRINT2(4, ":SR: rcv remote_co: type: %s, len: %d\n", CommTag, BlobSize);
  1435. *(PVOID *) DataDest = CommData;
  1436. break;
  1437. default:
  1438. //
  1439. // Decode data type from an uplevel client. Although we should
  1440. // not really get here because uplevel clients should only be using
  1441. // new decode data types with new decode data elements which got
  1442. // filtered out above.
  1443. //
  1444. DPRINT3(0, "++ WARN - Skipping invalid comm packet decode data type. CommType = %d, DecodeType = %d, From %ws\n",
  1445. CommType, DecodeType, RsFrom(Cmd) ? RsFrom(Cmd)->Name : L"<unknown>");
  1446. CommPkt->UpkLen += CommTypeSize;
  1447. b = !(CommPkt->UpkLen > CommPkt->PktLen || CommTypeSize > CommPkt->PktLen);
  1448. break;
  1449. }
  1450. NEXT_ELEMENT:
  1451. if (!b) {
  1452. DPRINT4(0, ":SR: PKT ERROR -- CommType = %s, DataSize = %d, CommPkt->UpkLen = %d, CommPkt->PktLen = %d\n",
  1453. CommTag, CommTypeSize, CommPkt->UpkLen, CommPkt->PktLen);
  1454. goto CLEANUP_ON_ERROR;
  1455. }
  1456. }
  1457. //
  1458. // SUCCESS
  1459. //
  1460. return Cmd;
  1461. //
  1462. // FAILURE
  1463. //
  1464. CLEANUP_ON_ERROR:
  1465. if (Cmd) {
  1466. FrsCompleteCommand(Cmd, ERROR_OPERATION_ABORTED);
  1467. }
  1468. return NULL;
  1469. }