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.

1324 lines
38 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. extern PGEN_TABLE CompressionTable;
  18. //
  19. // Types for the common comm subsystem
  20. //
  21. // WARNING: The order of these entries can never change. This ensures that
  22. // packets can be exchanged between uplevel and downlevel members.
  23. //
  24. typedef enum _COMMTYPE {
  25. COMM_NONE = 0,
  26. COMM_BOP, // beginning of packet
  27. COMM_COMMAND, // command packet stuff
  28. COMM_TO,
  29. COMM_FROM,
  30. COMM_REPLICA,
  31. COMM_JOIN_GUID,
  32. COMM_VVECTOR,
  33. COMM_CXTION,
  34. COMM_BLOCK, // file data
  35. COMM_BLOCK_SIZE,
  36. COMM_FILE_SIZE,
  37. COMM_FILE_OFFSET,
  38. COMM_REMOTE_CO, // remote change order command
  39. COMM_GVSN, // version (guid, vsn)
  40. COMM_CO_GUID, // change order guid
  41. COMM_CO_SEQUENCE_NUMBER,// CO Seq number for ack.
  42. COMM_JOIN_TIME, // machine's can't join if there times or badly out of sync
  43. COMM_LAST_JOIN_TIME, // The Last time this connection was joined.
  44. // Used to detect Database mismatch.
  45. COMM_EOP, // end of packet
  46. COMM_REPLICA_VERSION_GUID, // replica version guid (originator guid)
  47. COMM_MD5_DIGEST, // md5 digest
  48. //
  49. // Change Order Record Extension. If not supplied the the ptr for
  50. // what was Spare1Bin (now Extension) is left as Null. So comm packets
  51. // sent from down level members still work.
  52. //
  53. COMM_CO_EXT_WIN2K, // in down level code this was called COMM_CO_EXTENSION.
  54. //
  55. // See comment in schema.h for why we need to seperate the var len
  56. // COMM_CO_EXTENSION_2 from COMM_CO_EXT_WIN2K above.
  57. //
  58. COMM_CO_EXTENSION_2,
  59. COMM_COMPRESSION_GUID, // Guid for a supported compression algorithm.
  60. //
  61. // WARNING: To ensure that down level members can read Comm packets
  62. // from uplevel clients always add net data type codes here.
  63. //
  64. COMM_MAX
  65. } COMM_TYPE, *PCOMM_TYPE;
  66. #define COMM_NULL_DATA (-1)
  67. //
  68. // The decode data types are defined below. They are used in the CommPacketTable
  69. // to aid in decode dispatching and comm packet construction
  70. // They DO NOT get sent in the actual packet.
  71. //
  72. typedef enum _COMM_PACKET_DECODE_TYPE {
  73. COMM_DECODE_NONE = 0,
  74. COMM_DECODE_ULONG,
  75. COMM_DECODE_ULONG_TO_USHORT,
  76. COMM_DECODE_GNAME,
  77. COMM_DECODE_BLOB,
  78. COMM_DECODE_ULONGLONG,
  79. COMM_DECODE_VVECTOR,
  80. COMM_DECODE_VAR_LEN_BLOB,
  81. COMM_DECODE_REMOTE_CO,
  82. COMM_DECODE_GUID,
  83. COMM_DECODE_MAX
  84. } COMM_PACKET_DECODE_TYPE, *PCOMM_PACKET_DECODE_TYPE;
  85. //
  86. // The COMM_PACKET_ELEMENT struct is used in a table to describe the data
  87. // elements in a Comm packet.
  88. //
  89. typedef struct _COMM_PACKET_ELEMENT_ {
  90. COMM_TYPE CommType;
  91. PCHAR CommTag;
  92. ULONG DataSize;
  93. ULONG DecodeType;
  94. ULONG NativeOffset;
  95. } COMM_PACKET_ELEMENT, *PCOMM_PACKET_ELEMENT;
  96. #define COMM_MEM_SIZE (128)
  97. //
  98. // Size of the required Beginning-of-packet and End-of-Packet fields
  99. //
  100. #define MIN_COMM_PACKET_SIZE (2 * (sizeof(USHORT) + sizeof(ULONG) + sizeof(ULONG)))
  101. #define COMM_SZ_UL sizeof(ULONG)
  102. #define COMM_SZ_ULL sizeof(ULONGLONG)
  103. #define COMM_SZ_GUID sizeof(GUID)
  104. #define COMM_SZ_GUL sizeof(GUID) + sizeof(ULONG)
  105. #define COMM_SZ_GVSN sizeof(GVSN) + sizeof(ULONG)
  106. #define COMM_SZ_NULL 0
  107. #define COMM_SZ_COC sizeof(CHANGE_ORDER_COMMAND) + sizeof(ULONG)
  108. //#define COMM_SZ_COC CO_PART1_SIZE + CO_PART2_SIZE + CO_PART3_SIZE + sizeof(ULONG)
  109. #define COMM_SZ_COEXT_W2K sizeof(CO_RECORD_EXTENSION_WIN2K) + sizeof(ULONG)
  110. #define COMM_SZ_MD5 MD5DIGESTLEN + sizeof(ULONG)
  111. #define COMM_SZ_JTIME sizeof(ULONGLONG) + sizeof(ULONG)
  112. //
  113. // Note: When using COMM_DECODE_VAR_LEN_BLOB you must also use COMM_SZ_NULL
  114. // in the table below so that no length check is made when the field is decoded.
  115. // This allows the field size to grow. Down level members must be able to
  116. // handle this by ignoring var len field components they do not understand.
  117. //
  118. //
  119. // The Communication packet element table below is used to construct and
  120. // decode comm packet data sent between members.
  121. // *** WARNING *** - the order of the rows in the table must match the
  122. // the order of the elements in the COMM_TYPE enum. See comments for COMM_TYPE
  123. // enum for restrictions on adding new elements to the table.
  124. //
  125. // Data Element Type DisplayText Size Decode Type Offset to Native Cmd Packet
  126. //
  127. COMM_PACKET_ELEMENT CommPacketTable[COMM_MAX] = {
  128. {COMM_NONE, "NONE" , COMM_SZ_NULL, COMM_DECODE_NONE, 0 },
  129. {COMM_BOP, "BOP" , COMM_SZ_UL, COMM_DECODE_ULONG, RsOffsetSkip },
  130. {COMM_COMMAND, "COMMAND" , COMM_SZ_UL, COMM_DECODE_ULONG_TO_USHORT, OFFSET(COMMAND_PACKET, Command)},
  131. {COMM_TO, "TO" , COMM_SZ_NULL, COMM_DECODE_GNAME, RsOffset(To) },
  132. {COMM_FROM, "FROM" , COMM_SZ_NULL, COMM_DECODE_GNAME, RsOffset(From) },
  133. {COMM_REPLICA, "REPLICA" , COMM_SZ_NULL, COMM_DECODE_GNAME, RsOffset(ReplicaName) },
  134. {COMM_JOIN_GUID, "JOIN_GUID" , COMM_SZ_GUL, COMM_DECODE_BLOB, RsOffset(JoinGuid) },
  135. {COMM_VVECTOR, "VVECTOR" , COMM_SZ_GVSN, COMM_DECODE_VVECTOR, RsOffset(VVector) },
  136. {COMM_CXTION, "CXTION" , COMM_SZ_NULL, COMM_DECODE_GNAME, RsOffset(Cxtion) },
  137. {COMM_BLOCK, "BLOCK" , COMM_SZ_NULL, COMM_DECODE_BLOB, RsOffset(Block) },
  138. {COMM_BLOCK_SIZE, "BLOCK_SIZE" , COMM_SZ_ULL, COMM_DECODE_ULONGLONG, RsOffset(BlockSize) },
  139. {COMM_FILE_SIZE, "FILE_SIZE" , COMM_SZ_ULL, COMM_DECODE_ULONGLONG, RsOffset(FileSize) },
  140. {COMM_FILE_OFFSET, "FILE_OFFSET" , COMM_SZ_ULL, COMM_DECODE_ULONGLONG, RsOffset(FileOffset) },
  141. {COMM_REMOTE_CO, "REMOTE_CO" , COMM_SZ_COC, COMM_DECODE_REMOTE_CO, RsOffset(PartnerChangeOrderCommand)},
  142. {COMM_GVSN, "GVSN" , COMM_SZ_GVSN, COMM_DECODE_BLOB, RsOffset(GVsn) },
  143. {COMM_CO_GUID, "CO_GUID" , COMM_SZ_GUL, COMM_DECODE_BLOB, RsOffset(ChangeOrderGuid) },
  144. {COMM_CO_SEQUENCE_NUMBER, "CO_SEQUENCE_NUMBER" , COMM_SZ_UL, COMM_DECODE_ULONG, RsOffset(ChangeOrderSequenceNumber)},
  145. {COMM_JOIN_TIME, "JOIN_TIME" , COMM_SZ_JTIME, COMM_DECODE_BLOB, RsOffset(JoinTime) },
  146. {COMM_LAST_JOIN_TIME, "LAST_JOIN_TIME" , COMM_SZ_ULL, COMM_DECODE_ULONGLONG, RsOffset(LastJoinTime) },
  147. {COMM_EOP, "EOP" , COMM_SZ_UL, COMM_DECODE_ULONG, RsOffsetSkip },
  148. {COMM_REPLICA_VERSION_GUID, "REPLICA_VERSION_GUID", COMM_SZ_GUL, COMM_DECODE_BLOB, RsOffset(ReplicaVersionGuid)},
  149. {COMM_MD5_DIGEST, "MD5_DIGEST" , COMM_SZ_MD5, COMM_DECODE_BLOB, RsOffset(Md5Digest) },
  150. {COMM_CO_EXT_WIN2K, "CO_EXT_WIN2K" , COMM_SZ_COEXT_W2K,COMM_DECODE_BLOB, RsOffset(PartnerChangeOrderCommandExt)},
  151. {COMM_CO_EXTENSION_2, "CO_EXTENSION_2" , COMM_SZ_NULL, COMM_DECODE_VAR_LEN_BLOB, RsOffset(PartnerChangeOrderCommandExt)},
  152. {COMM_COMPRESSION_GUID, "COMPRESSION_GUID" , COMM_SZ_GUID, COMM_DECODE_GUID, RsOffset(CompressionTable)}
  153. };
  154. VOID
  155. CommInitializeCommSubsystem(
  156. VOID
  157. )
  158. /*++
  159. Routine Description:
  160. Initialize the generic comm subsystem
  161. Arguments:
  162. None.
  163. Return Value:
  164. None.
  165. --*/
  166. {
  167. #undef DEBSUB
  168. #define DEBSUB "CommInitializeCommSubsystem:"
  169. //
  170. // type must fit into a short
  171. //
  172. FRS_ASSERT(COMM_MAX <= 0xFFFF);
  173. }
  174. VOID
  175. CommCopyMemory(
  176. IN PCOMM_PACKET CommPkt,
  177. IN PUCHAR Src,
  178. IN ULONG Len
  179. )
  180. /*++
  181. Routine Description:
  182. Copy memory into a comm packet, extending as necessary
  183. Arguments:
  184. CommPkt
  185. Src
  186. Len
  187. Return Value:
  188. None.
  189. --*/
  190. {
  191. #undef DEBSUB
  192. #define DEBSUB "CommCopyMemory:"
  193. ULONG MemLeft;
  194. PUCHAR NewPkt;
  195. //
  196. // Adjust size of comm packet if necessary
  197. //
  198. // PERF: How many allocs get done to send a CO??? This looks expensive.
  199. MemLeft = CommPkt->MemLen - CommPkt->PktLen;
  200. if (Len > MemLeft) {
  201. //
  202. // Just filling memory; extend memory, tacking on a little extra
  203. //
  204. CommPkt->MemLen = (((CommPkt->MemLen + Len) + (COMM_MEM_SIZE - 1))
  205. / COMM_MEM_SIZE)
  206. * COMM_MEM_SIZE;
  207. NewPkt = FrsAlloc(CommPkt->MemLen);
  208. CopyMemory(NewPkt, CommPkt->Pkt, CommPkt->PktLen);
  209. FrsFree(CommPkt->Pkt);
  210. CommPkt->Pkt = NewPkt;
  211. }
  212. //
  213. // Copy into the packet
  214. //
  215. if (Src != NULL) {
  216. CopyMemory(CommPkt->Pkt + CommPkt->PktLen, Src, Len);
  217. } else {
  218. ZeroMemory(CommPkt->Pkt + CommPkt->PktLen, Len);
  219. }
  220. CommPkt->PktLen += Len;
  221. }
  222. BOOL
  223. CommFetchMemory(
  224. IN PCOMM_PACKET CommPkt,
  225. IN PUCHAR Dst,
  226. IN ULONG Len
  227. )
  228. /*++
  229. Routine Description:
  230. Fetch memory from a comm packet, reading as necessary
  231. Arguments:
  232. CommPkt
  233. Dst
  234. Len
  235. Return Value:
  236. None.
  237. --*/
  238. {
  239. #undef DEBSUB
  240. #define DEBSUB "CommFetchMemory:"
  241. PUCHAR Src;
  242. Src = CommPkt->Pkt + CommPkt->UpkLen;
  243. CommPkt->UpkLen += Len;
  244. if (CommPkt->UpkLen > CommPkt->PktLen || Len > CommPkt->PktLen) {
  245. return FALSE;
  246. }
  247. //
  248. // Copy into the packet
  249. //
  250. CopyMemory(Dst, Src, Len);
  251. return TRUE;
  252. }
  253. VOID
  254. CommCompletionRoutine(
  255. IN PCOMMAND_PACKET Cmd,
  256. IN PVOID Arg
  257. )
  258. /*++
  259. Routine Description:
  260. Completion routine for comm command servers. Free the
  261. comm packet and then call the generic completion routine
  262. to free the command packet.
  263. Arguments:
  264. Cmd - command packet
  265. Arg - Cmd->CompletionArg
  266. Return Value:
  267. None.
  268. --*/
  269. {
  270. #undef DEBSUB
  271. #define DEBSUB "CommCompletionRoutine:"
  272. PCOMM_PACKET CommPkt = SRCommPkt(Cmd);
  273. PCXTION Cxtion = SRCxtion(Cmd);
  274. COMMAND_SND_COMM_TRACE(4, Cmd, Cmd->ErrorStatus, "SndComplete");
  275. //
  276. // The SndCs and the ReplicaCs cooperate to limit the number of
  277. // active join "pings" so that the Snd threads are not hung
  278. // waiting for pings to dead servers to time out.
  279. //
  280. if ((CommPkt != NULL) &&
  281. (Cxtion != NULL) &&
  282. (CommPkt == Cxtion->ActiveJoinCommPkt)) {
  283. Cxtion->ActiveJoinCommPkt = NULL;
  284. }
  285. //
  286. // Free the comm packet and the attached return response command packet if
  287. // it's still attached. The Replica Cmd Server uses the CMD_JOINING_AFTER_FLUSH
  288. // command in this way.
  289. //
  290. if (CommPkt != NULL) {
  291. FrsFree(CommPkt->Pkt);
  292. FrsFree(CommPkt);
  293. }
  294. if (SRCmd(Cmd)) {
  295. FrsCompleteCommand(SRCmd(Cmd), Cmd->ErrorStatus);
  296. SRCmd(Cmd) = NULL;
  297. }
  298. //
  299. // Free the name/guid and Principal name params.
  300. //
  301. FrsFreeGName(SRTo(Cmd));
  302. FrsFree(SRPrincName(Cmd));
  303. //
  304. // Move the packet to the generic "done" routine
  305. //
  306. FrsSetCompletionRoutine(Cmd, FrsFreeCommand, NULL);
  307. FrsCompleteCommand(Cmd, Cmd->ErrorStatus);
  308. }
  309. PUCHAR
  310. CommGetHdr(
  311. IN PUCHAR Pnext,
  312. IN PUSHORT PCommType,
  313. IN PULONG PLen
  314. )
  315. /*++
  316. Routine Description:
  317. Get and skip a field header
  318. Arguments:
  319. Pnext
  320. PCommType
  321. PLen
  322. Return Value:
  323. Address of the field's data
  324. --*/
  325. {
  326. #undef DEBSUB
  327. #define DEBSUB "CommGetHdr:"
  328. CopyMemory(PCommType, Pnext, sizeof(USHORT));
  329. Pnext += sizeof(USHORT);
  330. CopyMemory(PLen, Pnext, sizeof(ULONG));
  331. Pnext += sizeof(ULONG);
  332. return Pnext;
  333. }
  334. BOOL
  335. CommCheckPkt(
  336. IN PCOMM_PACKET CommPkt
  337. )
  338. /*++
  339. Routine Description:
  340. Check the packet for consistency
  341. Arguments:
  342. CommPkt
  343. Return Value:
  344. TRUE - consistent
  345. Otherwise - Assert failure
  346. --*/
  347. {
  348. #undef DEBSUB
  349. #define DEBSUB "CommCheckPkt:"
  350. ULONG Len;
  351. ULONG Data;
  352. PUCHAR Pfirst;
  353. PUCHAR Pnext;
  354. PUCHAR Pend;
  355. USHORT CommType;
  356. if (!CommPkt) {
  357. return FALSE;
  358. }
  359. //
  360. // Check major. Mismatched majors cannot be handled.
  361. //
  362. if (CommPkt->Major != NtFrsMajor) {
  363. DPRINT2(3, "WARN - RpcCommPkt: MAJOR MISMATCH %d major does not match %d; ignoring\n",
  364. CommPkt->Major, NtFrsMajor);
  365. return FALSE;
  366. }
  367. //
  368. // Check minor. This service can process packets with mismatched
  369. // minors, although some functionality may be lost.
  370. //
  371. if (CommPkt->Minor != NtFrsCommMinor) {
  372. DPRINT2(5, "RpcCommPkt: MINOR MISMATCH %d minor does not match %d\n",
  373. CommPkt->Minor, NtFrsCommMinor);
  374. }
  375. //
  376. // Compare the length of the packet with its memory allocation
  377. //
  378. if (CommPkt->PktLen > CommPkt->MemLen) {
  379. DPRINT2(4, "RpcCommPkt: Packet size (%d) > Alloced Memory (%d)\n",
  380. CommPkt->PktLen, CommPkt->MemLen);
  381. return FALSE;
  382. }
  383. //
  384. // Must have at least a beginning-of-packet and end-of-packet field
  385. //
  386. if (CommPkt->PktLen < MIN_COMM_PACKET_SIZE) {
  387. DPRINT2(4, "RpcCommPkt: Packet size (%d) < Minimum size (%d)\n",
  388. CommPkt->PktLen, MIN_COMM_PACKET_SIZE);
  389. return FALSE;
  390. }
  391. //
  392. // packets begin with a beginning-of-packet
  393. //
  394. Pfirst = CommPkt->Pkt;
  395. Pnext = CommGetHdr(Pfirst, &CommType, &Len);
  396. if (CommType != COMM_BOP || Len != sizeof(ULONG)) {
  397. return FALSE;
  398. }
  399. CopyMemory(&Data, Pnext, sizeof(ULONG));
  400. if (Data != 0) {
  401. return FALSE;
  402. }
  403. //
  404. // packets end with an end-of-packet
  405. //
  406. Pend = Pfirst + CommPkt->PktLen;
  407. if (Pend <= Pfirst) {
  408. return FALSE;
  409. }
  410. Pnext = ((Pend - sizeof(USHORT)) - sizeof(ULONG)) - sizeof(ULONG);
  411. Pnext = CommGetHdr(Pnext, &CommType, &Len);
  412. if (CommType != COMM_EOP || Len != sizeof(ULONG)) {
  413. return FALSE;
  414. }
  415. CopyMemory(&Data, Pnext, sizeof(ULONG));
  416. if (Data != COMM_NULL_DATA) {
  417. return FALSE;
  418. }
  419. return TRUE;
  420. }
  421. VOID
  422. CommDumpCommPkt(
  423. IN PCOMM_PACKET CommPkt,
  424. IN DWORD NumDump
  425. )
  426. /*++
  427. Routine Description:
  428. Dump some of the comm packet
  429. Arguments:
  430. CommPkt
  431. NumDump
  432. Return Value:
  433. None.
  434. --*/
  435. {
  436. #undef DEBSUB
  437. #define DEBSUB "CommDumpCommPkt:"
  438. ULONG Len;
  439. PUCHAR Pnext;
  440. USHORT CommType;
  441. DWORD i;
  442. DPRINT1(0, "%x:\n", CommPkt);
  443. DPRINT1(0, "\tMajor: %d\n", CommPkt->Major);
  444. DPRINT1(0, "\tMinor: %d\n", CommPkt->Minor);
  445. DPRINT1(0, "\tMemLen: %d\n", CommPkt->MemLen);
  446. DPRINT1(0, "\tPktLen: %d\n", CommPkt->PktLen);
  447. DPRINT1(0, "\tPkt: 0x%x\n", CommPkt->Pkt);
  448. //
  449. // packets begin with a beginning-of-packet
  450. //
  451. Pnext = CommPkt->Pkt;
  452. for (i = 0; i < NumDump; ++i) {
  453. Pnext = CommGetHdr(Pnext, &CommType, &Len);
  454. DPRINT4(0, "Dumping %d for %x: %d %d\n", i, CommPkt, CommType, Len);
  455. Pnext += Len;
  456. }
  457. }
  458. VOID
  459. CommPackULong(
  460. IN PCOMM_PACKET CommPkt,
  461. IN COMM_TYPE Type,
  462. IN ULONG Data
  463. )
  464. /*++
  465. Routine Description:
  466. Copy a header and a ulong into the comm packet.
  467. Arguments:
  468. CommPkt
  469. Type
  470. Data
  471. Return Value:
  472. None.
  473. --*/
  474. {
  475. #undef DEBSUB
  476. #define DEBSUB "CommPackULong:"
  477. ULONG Len = sizeof(ULONG);
  478. USHORT CommType = (USHORT)Type;
  479. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  480. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  481. CommCopyMemory(CommPkt, (PUCHAR)&Data, sizeof(ULONG));
  482. }
  483. PCOMM_PACKET
  484. CommStartCommPkt(
  485. IN PWCHAR Name
  486. )
  487. /*++
  488. Routine Description:
  489. Allocate a comm packet.
  490. Arguments:
  491. Name
  492. Return Value:
  493. Address of a comm packet.
  494. --*/
  495. {
  496. #undef DEBSUB
  497. #define DEBSUB "CommStartCommPkt:"
  498. ULONG Size;
  499. PCOMM_PACKET CommPkt;
  500. //
  501. // We can create a comm packet in a file or in memory
  502. //
  503. CommPkt = FrsAlloc(sizeof(COMM_PACKET));
  504. Size = COMM_MEM_SIZE;
  505. CommPkt->Pkt = FrsAlloc(Size);
  506. CommPkt->MemLen = Size;
  507. CommPkt->Major = NtFrsMajor;
  508. CommPkt->Minor = NtFrsCommMinor;
  509. //
  510. // Pack the beginning-of-packet
  511. //
  512. CommPackULong(CommPkt, COMM_BOP, 0);
  513. return CommPkt;
  514. }
  515. BOOL
  516. CommUnpackBlob(
  517. IN PCOMM_PACKET CommPkt,
  518. OUT ULONG *OutBlobSize,
  519. OUT PVOID *OutBlob
  520. )
  521. /*++
  522. Routine Description:
  523. Unpack a blob (length + data)
  524. Arguments:
  525. CommPkt
  526. OutBlobSize - size of blob from comm packet
  527. OutBlob - data from comm packet
  528. Return Value:
  529. TRUE - Blob retrieved from comm packet
  530. FALSE - Blob was not retrieved from comm packet; bad comm packet
  531. --*/
  532. {
  533. #undef DEBSUB
  534. #define DEBSUB "CommUnpackBlob:"
  535. ULONG BlobSize;
  536. //
  537. // Initialize return params
  538. //
  539. *OutBlob = NULL;
  540. //
  541. // Unpack the length of the blob
  542. //
  543. if (!CommFetchMemory(CommPkt, (PUCHAR)OutBlobSize, sizeof(ULONG))) {
  544. return FALSE;
  545. }
  546. BlobSize = *OutBlobSize;
  547. //
  548. // Empty blob, return NULL
  549. //
  550. if (BlobSize == 0) {
  551. return TRUE;
  552. }
  553. //
  554. // Allocate memory for the blob
  555. //
  556. *OutBlob = FrsAlloc(BlobSize);
  557. //
  558. // Unpack the blob
  559. //
  560. return CommFetchMemory(CommPkt, (PUCHAR)*OutBlob, BlobSize);
  561. }
  562. BOOL
  563. CommUnpackGName(
  564. IN PCOMM_PACKET CommPkt,
  565. OUT PGNAME *OutGName
  566. )
  567. /*++
  568. Routine Description:
  569. Unpack the guid and wide char string that make up a gstring
  570. Arguments:
  571. CommPkt
  572. OutGName - From comm packet
  573. Return Value:
  574. TRUE - GName fetched from comm packet successfully
  575. FALSE - GName was not fetched from comm packet; bad comm packet
  576. --*/
  577. {
  578. #undef DEBSUB
  579. #define DEBSUB "CommUnpackGName:"
  580. ULONG BlobSize;
  581. PGNAME GName;
  582. //
  583. // Allocate a gstring (caller cleans up on error)
  584. //
  585. *OutGName = GName = FrsAlloc(sizeof(GNAME));
  586. if (!CommUnpackBlob(CommPkt, &BlobSize, &GName->Guid) ||
  587. BlobSize != sizeof(GUID)) {
  588. return FALSE;
  589. }
  590. if (!CommUnpackBlob(CommPkt, &BlobSize, &GName->Name) ||
  591. GName->Name[(BlobSize / sizeof(WCHAR)) - 1] != L'\0') {
  592. return FALSE;
  593. }
  594. return TRUE;
  595. }
  596. BOOL
  597. CommGetNextElement(
  598. IN PCOMM_PACKET CommPkt,
  599. OUT COMM_TYPE *CommType,
  600. OUT ULONG *CommTypeSize
  601. )
  602. /*++
  603. Routine Description:
  604. Advance to the next field in the comm packet
  605. Arguments:
  606. CommPkt
  607. CommType - type of packed field
  608. CommTypeSize - size of packed field (excluding type and size)
  609. Return Value:
  610. TRUE - CommType and CommTypeSize were unpacked
  611. FALSE - Could not unpack; bad comm packet
  612. --*/
  613. {
  614. #undef DEBSUB
  615. #define DEBSUB "CommGetNextElement:"
  616. USHORT Ushort;
  617. //
  618. // Find the type and length of this entry
  619. //
  620. if (CommFetchMemory(CommPkt, (PUCHAR)&Ushort, sizeof(USHORT)) &&
  621. CommFetchMemory(CommPkt, (PUCHAR)CommTypeSize, sizeof(ULONG))) {
  622. *CommType = Ushort;
  623. return TRUE;
  624. }
  625. return FALSE;
  626. }
  627. VOID
  628. CommInsertDataElement(
  629. IN PCOMM_PACKET CommPkt,
  630. IN COMM_TYPE CommType,
  631. IN PVOID CommData,
  632. IN ULONG CommDataLen
  633. )
  634. /*++
  635. Routine Description:
  636. Insert the data supplied using the CommType specific format into the
  637. Comm packet.
  638. Arguments:
  639. CommPkt - The Comm packet structure.
  640. CommType - The data type for this element.
  641. CommData - The address of the data.
  642. CommDataLen - The size for var len elements.
  643. Return Value:
  644. None.
  645. --*/
  646. {
  647. #undef DEBSUB
  648. #define DEBSUB "CommInsertDataElement:"
  649. ULONG Len;
  650. PGNAME GName;
  651. ULONG LenGuid;
  652. ULONG LenName;
  653. ULONG DataSize;
  654. ULONG DecodeType;
  655. PCHAR CommTag;
  656. if (CommData == NULL) {
  657. return;
  658. }
  659. FRS_ASSERT((CommType < COMM_MAX) && (CommType != COMM_NONE));
  660. //
  661. // Table index MUST match table CommType Field or table is fouled up.
  662. //
  663. FRS_ASSERT(CommType == CommPacketTable[CommType].CommType);
  664. //
  665. // Length check from table for fixed length fields.
  666. //
  667. //DataSize = CommPacketTable[CommType].DataSize;
  668. //FRS_ASSERT((DataSize == COMM_SZ_NULL) || (CommDataLen == DataSize));
  669. //
  670. // Insert the data using the data type encoding.
  671. //
  672. DecodeType = CommPacketTable[CommType].DecodeType;
  673. CommTag = CommPacketTable[CommType].CommTag;
  674. switch (DecodeType) {
  675. //
  676. // Insert a ULONG size piece of data.
  677. //
  678. case COMM_DECODE_ULONG:
  679. case COMM_DECODE_ULONG_TO_USHORT:
  680. Len = sizeof(ULONG);
  681. DPRINT2(5, ":SR: Dec_long: type: %s, len: %d\n", CommTag, Len);
  682. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  683. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  684. CommCopyMemory(CommPkt, (PUCHAR)CommData, sizeof(ULONG));
  685. break;
  686. //
  687. // Insert a Guid and Name string (GNAME).
  688. //
  689. case COMM_DECODE_GNAME:
  690. GName = (PGNAME)CommData;
  691. LenGuid = sizeof(GUID);
  692. LenName = (wcslen(GName->Name) + 1) * sizeof(WCHAR);
  693. Len = LenGuid + LenName + (2 * sizeof(ULONG));
  694. DPRINT3(5, ":SR: Dec_gname: type: %s, len: %d - %ws\n", CommTag, Len, GName->Name);
  695. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  696. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  697. CommCopyMemory(CommPkt, (PUCHAR)&LenGuid, sizeof(ULONG));
  698. CommCopyMemory(CommPkt, (PUCHAR)GName->Guid, LenGuid);
  699. CommCopyMemory(CommPkt, (PUCHAR)&LenName, sizeof(ULONG));
  700. CommCopyMemory(CommPkt, (PUCHAR)GName->Name, LenName);
  701. break;
  702. //
  703. // Insert a ULONGLONG.
  704. //
  705. case COMM_DECODE_ULONGLONG:
  706. Len = sizeof(ULONGLONG);
  707. DPRINT2(5, ":SR: Dec_longlong: type: %s, len: %d\n", CommTag, Len);
  708. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  709. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  710. CommCopyMemory(CommPkt, (PUCHAR)CommData, sizeof(ULONGLONG));
  711. break;
  712. //
  713. // Insert a Guid.
  714. //
  715. case COMM_DECODE_GUID:
  716. Len = sizeof(GUID);
  717. DPRINT2(5, ":SR: Dec_Guid: type: %s, len: %d\n", CommTag, Len);
  718. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  719. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  720. CommCopyMemory(CommPkt, (PUCHAR)CommData, sizeof(GUID));
  721. break;
  722. case COMM_DECODE_VVECTOR:
  723. //
  724. // Version Vector data gets inserted into Comm packet as blobs.
  725. //
  726. NOTHING;
  727. /* FALL THRU INTENDED */
  728. //
  729. // Insert a variable length BLOB. The problem with blobs as currently
  730. // shipped in win2k is that the code on the unpack side checks for a
  731. // match on a constant length based on the COMM Data Type. This means
  732. // that a var len datatype like CHANGE_ORDER_EXTENSION can't change because
  733. // the 40 byte size is wired into the code of down level members. Sigh.
  734. //
  735. case COMM_DECODE_BLOB:
  736. Len = CommDataLen + sizeof(ULONG);
  737. DPRINT2(5, ":SR: Dec_blob: type: %s, len: %d\n", CommTag, Len);
  738. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  739. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  740. CommCopyMemory(CommPkt, (PUCHAR)&CommDataLen, sizeof(ULONG));
  741. CommCopyMemory(CommPkt, (PUCHAR)CommData, CommDataLen);
  742. break;
  743. //
  744. // Insert a true variable length data struct that is extensible.
  745. // The actual length comes from the first DWORD of the data.
  746. //
  747. case COMM_DECODE_VAR_LEN_BLOB:
  748. Len = *(PULONG)CommData;
  749. DPRINT2(5, ":SR: Dec_var_len_blob: type: %s, len: %d\n", CommTag, Len);
  750. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  751. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  752. CommCopyMemory(CommPkt, (PUCHAR)CommData, CommDataLen);
  753. break;
  754. //
  755. // The CO contains four pointers occupying 16 bytes on 32 bit architectures and
  756. // 32 bytes on 64 bit architectures (PART2). When the CO is sent in a comm packet
  757. // the contents of these pointers are irrelevant so in comm packets these
  758. // ptrs are always sent as 16 bytes of zeros, regardless of architecture.
  759. // Note - In 32 bit Win2k this was sent as a BLOB so it matches BLOB format.
  760. //
  761. case COMM_DECODE_REMOTE_CO:
  762. Len = COMM_SZ_COC;
  763. CommDataLen = Len - sizeof(ULONG);
  764. DPRINT2(4, ":SR: Dec_remote_co: type: %s, len: %d\n", CommTag, Len);
  765. CommCopyMemory(CommPkt, (PUCHAR)&CommType, sizeof(USHORT));
  766. CommCopyMemory(CommPkt, (PUCHAR)&Len, sizeof(ULONG));
  767. CommCopyMemory(CommPkt, (PUCHAR)&CommDataLen, sizeof(ULONG));
  768. CommCopyMemory(CommPkt, (PUCHAR)CommData, sizeof(CHANGE_ORDER_COMMAND));
  769. //CommCopyMemory(CommPkt, ((PUCHAR)CommData)+CO_PART1_OFFSET, CO_PART1_SIZE);
  770. //CommCopyMemory(CommPkt, NULL, CO_PART2_SIZE);
  771. //CommCopyMemory(CommPkt, ((PUCHAR)CommData)+CO_PART3_OFFSET, CO_PART3_SIZE);
  772. break;
  773. default:
  774. //
  775. // Table must be fouled up.
  776. //
  777. FRS_ASSERT((DecodeType > COMM_DECODE_NONE) && (DecodeType < COMM_DECODE_MAX));
  778. break;
  779. }
  780. return;
  781. }
  782. PCOMM_PACKET
  783. CommBuildCommPkt(
  784. IN PREPLICA Replica,
  785. IN PCXTION Cxtion,
  786. IN ULONG Command,
  787. IN PGEN_TABLE VVector,
  788. IN PCOMMAND_PACKET Cmd,
  789. IN PCHANGE_ORDER_COMMAND Coc
  790. )
  791. /*++
  792. Routine Description:
  793. Generate a comm packet with the info needed to execute the
  794. command on the remote machine identified by Cxtion.
  795. Arguments:
  796. Replica - Sender
  797. Cxtion - identifies the remote machine
  798. Command - command to execute on the remote machine
  799. VVector - some commands require the version vector
  800. Cmd - original command packet
  801. Coc - change order command
  802. RemoteGVsn - guid/vsn pair
  803. Return Value:
  804. Address of a comm packet.
  805. --*/
  806. {
  807. #undef DEBSUB
  808. #define DEBSUB "CommBuildCommPkt:"
  809. ULONGLONG FileTime;
  810. GNAME GName;
  811. PVOID Key;
  812. PCOMM_PACKET CommPkt;
  813. PGVSN GVsn;
  814. PGEN_ENTRY Entry;
  815. //
  816. // Allocate and initialize a comm packet
  817. //
  818. CommPkt = CommStartCommPkt(NULL);
  819. CommPkt->CsId = CS_RS;
  820. CommInsertDataElement(CommPkt, COMM_COMMAND, &Command, 0);
  821. CommInsertDataElement(CommPkt, COMM_TO, Cxtion->Partner, 0);
  822. CommInsertDataElement(CommPkt, COMM_FROM, Replica->MemberName, 0);
  823. GName.Guid = Cxtion->Partner->Guid;
  824. GName.Name = Replica->ReplicaName->Name;
  825. CommInsertDataElement(CommPkt, COMM_REPLICA, &GName, 0);
  826. CommInsertDataElement(CommPkt, COMM_CXTION, Cxtion->Name, 0);
  827. CommInsertDataElement(CommPkt, COMM_JOIN_GUID, &Cxtion->JoinGuid, sizeof(GUID));
  828. CommInsertDataElement(CommPkt, COMM_LAST_JOIN_TIME, &Cxtion->LastJoinTime, 0);
  829. //
  830. // Version vector (if supplied)
  831. //
  832. //
  833. // The caller is building a comm packet for join operation,
  834. // automatically include the current time and the originator guid.
  835. //
  836. if (VVector) {
  837. Key = NULL;
  838. while (GVsn = GTabNextDatum(VVector, &Key)) {
  839. CommInsertDataElement(CommPkt, COMM_VVECTOR, GVsn, sizeof(GVSN));
  840. }
  841. GetSystemTimeAsFileTime((FILETIME *)&FileTime);
  842. CommInsertDataElement(CommPkt, COMM_JOIN_TIME, &FileTime, sizeof(ULONGLONG));
  843. DPRINT1(4, ":X: Comm join time is %08x %08x\n", PRINTQUAD(FileTime));
  844. CommInsertDataElement(CommPkt, COMM_REPLICA_VERSION_GUID,
  845. &Replica->ReplicaVersionGuid, sizeof(GUID));
  846. //
  847. // Insert the list of Guids for compression algorithms that we understand.
  848. //
  849. GTabLockTable(CompressionTable);
  850. Key = NULL;
  851. while (Entry = GTabNextEntryNoLock(CompressionTable, &Key)) {
  852. CommInsertDataElement(CommPkt, COMM_COMPRESSION_GUID, Entry->Key1, 0);
  853. }
  854. GTabUnLockTable(CompressionTable);
  855. }
  856. if (Cmd) {
  857. CommInsertDataElement(CommPkt, COMM_BLOCK, RsBlock(Cmd), (ULONG)RsBlockSize(Cmd));
  858. CommInsertDataElement(CommPkt, COMM_BLOCK_SIZE, &RsBlockSize(Cmd), 0);
  859. CommInsertDataElement(CommPkt, COMM_FILE_SIZE, &RsFileSize(Cmd).QuadPart, 0);
  860. CommInsertDataElement(CommPkt, COMM_FILE_OFFSET, &RsFileOffset(Cmd).QuadPart, 0);
  861. CommInsertDataElement(CommPkt, COMM_GVSN, RsGVsn(Cmd), sizeof(GVSN));
  862. CommInsertDataElement(CommPkt, COMM_CO_GUID, RsCoGuid(Cmd), sizeof(GUID));
  863. CommInsertDataElement(CommPkt, COMM_CO_SEQUENCE_NUMBER, &RsCoSn(Cmd), 0);
  864. CommInsertDataElement(CommPkt, COMM_MD5_DIGEST, RsMd5Digest(Cmd), MD5DIGESTLEN);
  865. }
  866. //
  867. // Change Order Command
  868. //
  869. if (Coc) {
  870. CommInsertDataElement(CommPkt, COMM_REMOTE_CO, Coc, 0);
  871. //
  872. // Warning: See comment in schema.h on CHANGE_ORDER_RECORD_EXTENSION for
  873. // down level conversion info if Coc->Extension ever changes.
  874. //
  875. CommInsertDataElement(CommPkt, COMM_CO_EXT_WIN2K, Coc->Extension,
  876. sizeof(CO_RECORD_EXTENSION_WIN2K));
  877. //
  878. // For post win2k level members the CO extension info should be sent
  879. // as follows since the length comes from the first dword of the data.
  880. //
  881. //CommInsertDataElement(CommPkt, COMM_CO_EXTENSION_2, Coc->Extension, 0);
  882. }
  883. //
  884. // Terminate the packet with EOP Ulong.
  885. //
  886. CommPackULong(CommPkt, COMM_EOP, COMM_NULL_DATA);
  887. return CommPkt;
  888. }
  889. PCOMMAND_PACKET
  890. CommPktToCmd(
  891. IN PCOMM_PACKET CommPkt
  892. )
  893. /*++
  894. Routine Description:
  895. Unpack the data in a Comm packet and store it into a command struct.
  896. Arguments:
  897. CommPkt
  898. Return Value:
  899. Address of a command packet or NULL if unpack failed.
  900. --*/
  901. {
  902. #undef DEBSUB
  903. #define DEBSUB "CommPktToCmd:"
  904. GUID *pTempGuid;
  905. PCOMMAND_PACKET Cmd = NULL;
  906. ULONG BlobSize;
  907. PVOID Blob;
  908. ULONG CommTypeSize;
  909. COMM_TYPE CommType;
  910. ULONG DataSize;
  911. ULONG DecodeType;
  912. ULONG NativeOffset;
  913. PUCHAR DataDest;
  914. ULONG TempUlong;
  915. BOOL b;
  916. GNAME GName;
  917. PCHAR CommTag;
  918. PUCHAR CommData;
  919. PGEN_TABLE GTable;
  920. //
  921. // Create the command packet
  922. //
  923. Cmd = FrsAllocCommand(&ReplicaCmdServer.Queue, CMD_UNKNOWN);
  924. FrsSetCompletionRoutine(Cmd, RcsCmdPktCompletionRoutine, NULL);
  925. //
  926. // Scan the comm packet from the beginning
  927. //
  928. CommPkt->UpkLen = 0;
  929. b = TRUE;
  930. while (CommGetNextElement(CommPkt, &CommType, &CommTypeSize) &&
  931. CommType != COMM_EOP) {
  932. //
  933. // Uplevel members could send us comm packet data elements we don't handle.
  934. //
  935. if ((CommType >= COMM_MAX) || (CommType == COMM_NONE)) {
  936. DPRINT2(0, "++ WARN - Skipping invalid comm packet element type. CommType = %d, From %ws\n",
  937. CommType, RsFrom(Cmd) ? RsFrom(Cmd)->Name : L"<unknown>");
  938. CommPkt->UpkLen += CommTypeSize;
  939. b = !(CommPkt->UpkLen > CommPkt->PktLen || CommTypeSize > CommPkt->PktLen);
  940. goto NEXT_ELEMENT;
  941. }
  942. //
  943. // Table index MUST match table CommType Field or table is fouled up.
  944. //
  945. FRS_ASSERT(CommType == CommPacketTable[CommType].CommType);
  946. DataSize = CommPacketTable[CommType].DataSize;
  947. if ((DataSize != COMM_SZ_NULL) && (CommTypeSize != DataSize)) {
  948. DPRINT3(0, "++ WARN - Invalid comm packet size. CommType = %d, DataSize = %d, From %ws\n",
  949. CommType, CommTypeSize,
  950. RsFrom(Cmd) ? RsFrom(Cmd)->Name : L"<unknown>");
  951. goto CLEANUP_ON_ERROR;
  952. }
  953. //
  954. // Calc the data offset in the Cmd struct to store the data.
  955. //
  956. NativeOffset = CommPacketTable[CommType].NativeOffset;
  957. if (NativeOffset == RsOffsetSkip) {
  958. CommPkt->UpkLen += CommTypeSize;
  959. b = !(CommPkt->UpkLen > CommPkt->PktLen || CommTypeSize > CommPkt->PktLen);
  960. goto NEXT_ELEMENT;
  961. }
  962. DataDest = (PUCHAR) Cmd + NativeOffset;
  963. //
  964. // Decode the data element and store it in Cmd at the NativeOffset.
  965. //
  966. DecodeType = CommPacketTable[CommType].DecodeType;
  967. CommTag = CommPacketTable[CommType].CommTag;
  968. //DPRINT6(5, ":SR: CommType: %s, Size: %d, Cmd offset: %d, data dest: %08x, Pkt->UpkLen = %d, Pkt->PktLen = %d\n",
  969. // CommTag, CommTypeSize, NativeOffset,
  970. // DataDest, CommPkt->UpkLen, CommPkt->PktLen);
  971. switch (DecodeType) {
  972. case COMM_DECODE_ULONG:
  973. b = CommFetchMemory(CommPkt, DataDest, sizeof(ULONG));
  974. DPRINT2(5, ":SR: rcv Dec_long: %s data: %d\n", CommTag, *(PULONG)DataDest);
  975. break;
  976. case COMM_DECODE_ULONG_TO_USHORT:
  977. b = CommFetchMemory(CommPkt, (PUCHAR)&TempUlong, sizeof(ULONG));
  978. * ((PUSHORT) DataDest) = (USHORT)TempUlong;
  979. DPRINT2(5, ":SR: rcv Dec_ulong_to_ushort: %s data: %d\n", CommTag, TempUlong);
  980. break;
  981. case COMM_DECODE_GNAME:
  982. *(PVOID *)DataDest = FrsFreeGName(*(PVOID *)DataDest);
  983. b = CommUnpackGName(CommPkt, (PGNAME *) DataDest);
  984. GName.Guid = (*(PGNAME *)DataDest)->Guid;
  985. GName.Name = (*(PGNAME *)DataDest)->Name;
  986. DPRINT2(5, ":SR: rcv Dec_Gname: %s name: %ws\n", CommTag, GName.Name);
  987. break;
  988. case COMM_DECODE_BLOB:
  989. case COMM_DECODE_VAR_LEN_BLOB:
  990. *(PVOID *)DataDest = FrsFree(*(PVOID *)DataDest);
  991. b = CommUnpackBlob(CommPkt, &BlobSize, (PVOID *) DataDest);
  992. DPRINT1(5, ":SR: rcv Dec_blob: data: %08x\n", *(PULONG)DataDest);
  993. break;
  994. case COMM_DECODE_ULONGLONG:
  995. b = CommFetchMemory(CommPkt, DataDest, sizeof(ULONGLONG));
  996. DPRINT2(5, ":SR: rcv Dec_long_long: %s data: %08x %08x\n", CommTag,
  997. PRINTQUAD(*(PULONGLONG)DataDest));
  998. break;
  999. //
  1000. // Version Vector data gets unpacked and inserted into Table.
  1001. //
  1002. case COMM_DECODE_VVECTOR:
  1003. GTable = *(PGEN_TABLE *)(DataDest);
  1004. if (GTable == NULL) {
  1005. GTable = GTabAllocTable();
  1006. *(PGEN_TABLE *)(DataDest) = GTable;
  1007. }
  1008. b = CommUnpackBlob(CommPkt, &BlobSize, &Blob);
  1009. DPRINT2(5, ":SR: rcv Dec_VV: %s bloblen: %d\n", CommTag, BlobSize);
  1010. if (b) {
  1011. VVInsertOutbound(GTable, Blob);
  1012. }
  1013. break;
  1014. //
  1015. // Compression Guid data gets unpacked and inserted into table.
  1016. //
  1017. case COMM_DECODE_GUID:
  1018. if (CommType == COMM_COMPRESSION_GUID) {
  1019. GTable = *(PGEN_TABLE *)(DataDest);
  1020. if (GTable == NULL) {
  1021. GTable = GTabAllocTable();
  1022. *(PGEN_TABLE *)(DataDest) = GTable;
  1023. }
  1024. pTempGuid = FrsAlloc(sizeof(GUID));
  1025. b = CommFetchMemory(CommPkt, (PUCHAR)pTempGuid, sizeof(GUID));
  1026. DPRINT2(5, ":SR: rcv Comp_Guid: %s bloblen: %d\n", CommTag, BlobSize);
  1027. if (b) {
  1028. GTabInsertEntry(GTable, NULL, pTempGuid, NULL);
  1029. }
  1030. } else {
  1031. //
  1032. // Else the guid gets stashed in the data dest.
  1033. //
  1034. b = CommFetchMemory(CommPkt, DataDest, sizeof(GUID));
  1035. DPRINT1(5, ":SR: rcv Guid: %s \n", CommTag);
  1036. }
  1037. break;
  1038. //
  1039. // The CO contains four pointers occupying 16 bytes on 32 bit architectures
  1040. // and 32 bytes on 64 bit architectures (PART2). When the CO is sent
  1041. // in a comm packet the contents of these pointers are irrelevant so in
  1042. // comm packets these ptrs are always sent as 16 bytes of zeros,
  1043. // regardless of architecture.
  1044. // Note - In 32 bit Win2k this was sent as a BLOB so it matches BLOB format.
  1045. //
  1046. case COMM_DECODE_REMOTE_CO:
  1047. *(PVOID *)DataDest = FrsFree(*(PVOID *)DataDest);
  1048. //
  1049. // Unpack the length of the CO and then unpack the CO data.
  1050. //
  1051. b = CommFetchMemory(CommPkt, (PUCHAR)&BlobSize, sizeof(ULONG));
  1052. if (!b || (BlobSize == 0)) {
  1053. break;
  1054. }
  1055. CommData = FrsAlloc(sizeof(CHANGE_ORDER_COMMAND));
  1056. CommFetchMemory(CommPkt, (PUCHAR)CommData, sizeof(CHANGE_ORDER_COMMAND));
  1057. //CommFetchMemory(CommPkt, ((PUCHAR)CommData)+CO_PART1_OFFSET, CO_PART1_SIZE);
  1058. //CommFetchMemory(CommPkt, ((PUCHAR)CommData)+CO_PART2_OFFSET, CO_PART2_SIZE);
  1059. //CommFetchMemory(CommPkt, ((PUCHAR)CommData)+CO_PART3_OFFSET, CO_PART3_SIZE);
  1060. DPRINT2(4, ":SR: rcv remote_co: type: %s, len: %d\n", CommTag, BlobSize);
  1061. *(PVOID *) DataDest = CommData;
  1062. break;
  1063. default:
  1064. //
  1065. // Decode data type from an uplevel client. Although we should
  1066. // not really get here because uplevel clients should only be using
  1067. // new decode data types with new decode data elements which got
  1068. // filtered out above.
  1069. //
  1070. DPRINT3(0, "++ WARN - Skipping invalid comm packet decode data type. CommType = %d, DecodeType = %d, From %ws\n",
  1071. CommType, DecodeType, RsFrom(Cmd) ? RsFrom(Cmd)->Name : L"<unknown>");
  1072. CommPkt->UpkLen += CommTypeSize;
  1073. b = !(CommPkt->UpkLen > CommPkt->PktLen || CommTypeSize > CommPkt->PktLen);
  1074. break;
  1075. }
  1076. NEXT_ELEMENT:
  1077. if (!b) {
  1078. DPRINT4(0, ":SR: PKT ERROR -- CommType = %s, DataSize = %d, CommPkt->UpkLen = %d, CommPkt->PktLen = %d\n",
  1079. CommTag, CommTypeSize, CommPkt->UpkLen, CommPkt->PktLen);
  1080. goto CLEANUP_ON_ERROR;
  1081. }
  1082. }
  1083. //
  1084. // SUCCESS
  1085. //
  1086. return Cmd;
  1087. //
  1088. // FAILURE
  1089. //
  1090. CLEANUP_ON_ERROR:
  1091. if (Cmd) {
  1092. FrsCompleteCommand(Cmd, ERROR_OPERATION_ABORTED);
  1093. }
  1094. return NULL;
  1095. }