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.

807 lines
20 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. tower.c
  5. Abstract:
  6. This file contains encoding/decoding for the tower representation
  7. of the binding information that DCE runtime uses.
  8. TowerConstruct/TowerExplode will be called by the Runtime EpResolveBinding
  9. on the client side, TowerExplode will be called by the Endpoint Mapper
  10. and in addition the name service may call TowerExplode, TowerConstruct.
  11. Author:
  12. Bharat Shah (barats) 3-23-92
  13. KamenM 05/02/2002 Major security and cleanup changes
  14. Revision History:
  15. --*/
  16. #include <precomp.hxx>
  17. #include <epmp.h>
  18. #include <twrtypes.h>
  19. #include <twrproto.h>
  20. //
  21. // TowerVerify() defines.
  22. //
  23. // Note: DECnet Protocol uses 6 Floors, all others 5.
  24. //
  25. #define MAX_FLOOR_COUNT 6
  26. #define MIN_FLOOR_COUNT 3
  27. #ifndef UNALIGNED
  28. #error UNALIGNED not defined by sysinc.h or its includes and is needed.
  29. #endif
  30. #pragma pack(1)
  31. /*
  32. Some Lrpc specific stuff
  33. */
  34. #define NP_TRANSPORTID_LRPC 0x10
  35. #define NP_TOWERS_LRPC 0x04
  36. // "ncalrpc" including the NULL terminator
  37. const int LrpcProtocolSequenceLength = 8;
  38. RPC_STATUS
  39. Floor0or1ToId(
  40. IN PFLOOR_0OR1 Floor,
  41. OUT PGENERIC_ID Id
  42. )
  43. /*++
  44. Routine Description:
  45. This function extracts Xfer Syntax or If info from a
  46. a DCE tower Floor 0 or 1 encoding
  47. Arguments:
  48. Floor - A pointer to Floor0 or Floor 1 encoding
  49. Id - on output, the transfer syntax or interface id
  50. Return Value:
  51. EP_S_CANT_PERFORM_OP - The Encoding for the floor [0 or 1] is incorrect.
  52. N.B.
  53. Caller must have verified that the whole floor is present (i.e. we can't walk
  54. off the end of the buffer)
  55. --*/
  56. {
  57. if (Floor->FloorId != UUID_ENCODING)
  58. {
  59. return (EP_S_CANT_PERFORM_OP);
  60. }
  61. RpcpMemoryCopy((char PAPI *)&Id->Uuid, (char PAPI *) &Floor->Uuid,
  62. sizeof(UUID));
  63. Id->MajorVersion = Floor->MajorVersion;
  64. Id->MinorVersion = Floor->MinorVersion;
  65. return(RPC_S_OK);
  66. }
  67. RPC_STATUS
  68. CopyIdToFloor(
  69. OUT PFLOOR_0OR1 Floor,
  70. IN PGENERIC_ID Id
  71. )
  72. /*++
  73. Routine Description:
  74. This function constructs FLOOR 0 or 1 from the given IF-id or Transfer
  75. Syntax Id.
  76. Arguments:
  77. Floor - Pointer to Floor 0 or 1 structure that will be constructed
  78. Id - Pointer to If-id or Xfer Syntax Id.
  79. Return Value:
  80. RPC_S_OK
  81. --*/
  82. {
  83. Floor->FloorId = UUID_ENCODING;
  84. Floor->ProtocolIdByteCount = sizeof(Floor->Uuid) + sizeof(Floor->FloorId)
  85. + sizeof(Floor->MajorVersion);
  86. Floor->AddressByteCount = sizeof(Floor->MinorVersion);
  87. RpcpMemoryCopy((char PAPI *) &Floor->Uuid, (char PAPI *) &Id->Uuid,
  88. sizeof(UUID));
  89. Floor->MajorVersion = Id->MajorVersion;
  90. Floor->MinorVersion = Id->MinorVersion;
  91. return(RPC_S_OK);
  92. }
  93. BYTE *
  94. VerifyFloorLHSAndRHS (
  95. IN BYTE *FloorStart,
  96. IN BYTE *UpperBound,
  97. IN ULONG FloorNum
  98. )
  99. /*++
  100. Routine Description:
  101. Verifies that the left hand side (LHS) byte count and the
  102. right hand side (RHS) byte count in the given floor are accurate
  103. with respect to the floor start and size (i.e. jumping from the LHS
  104. we go to the right hand side, and from there, to the end of the floor
  105. without walking off the end).
  106. Arguments:
  107. FloorStart - the start of the current floor.
  108. UpperBound - pointer to first invalid byte after the buffer.
  109. FloorNum - the number of the floor. Used for debugging only
  110. Return Value:
  111. The position of the next floor, or NULL if the floor fails the check.
  112. --*/
  113. {
  114. USHORT LHSBytes, RHSBytes;
  115. if (FloorStart + 2 >= UpperBound)
  116. return NULL;
  117. LHSBytes = *(unsigned short UNALIGNED *)FloorStart;
  118. if (FloorStart + (ULONG)LHSBytes + 4 >= UpperBound) // the LHSBytes counter itself is 2 bytes, and we
  119. { // must provide at least 2 bytes for the RHSBytes
  120. #ifdef DEBUGRPC
  121. PrintToDebugger("RPC: TowerVerify(): LHS of Tower floor %d "
  122. "greater than equal to FloorSize\n", FloorNum);
  123. #endif // DEBUGRPC
  124. return NULL;
  125. }
  126. FloorStart += LHSBytes + 2;
  127. RHSBytes = *(unsigned short UNALIGNED *)FloorStart;
  128. if (FloorStart + (ULONG)RHSBytes + 2 > UpperBound) // the RHSBytes counter itself is 2 bytes
  129. {
  130. #ifdef DEBUGRPC
  131. PrintToDebugger("RPC: TowerVerify(): RHS of Tower floor %d "
  132. "greater than equal to FloorSize\n", FloorNum);
  133. #endif // DEBUGRPC
  134. return NULL;
  135. }
  136. return FloorStart + RHSBytes + 2;
  137. }
  138. RPC_STATUS
  139. ExtractStringFromUntrustedPacket (
  140. IN BYTE *UpperBound,
  141. IN ULONG ClaimedStringLength,
  142. IN char *StringStart,
  143. OUT char **ExtractedString
  144. )
  145. /*++
  146. Routine Description:
  147. Extracts a string from untrusted packet. Verifies
  148. string boundaries, reasonable length (at least one character
  149. and no more than 1000), and null termination.
  150. Arguments:
  151. UpperBound - the first invalid byte after the end of the buffer.
  152. ClaimedStringLength - the string length that the packet claims.
  153. StringStart - the alleged start of the string - untrusted.
  154. ExtractedString - the extracted string. Must be freed with delete. Undefined
  155. on failure.
  156. Return Value:
  157. RPC_S_OK, RPC_S_OUT_OF_MEMORY or EP_S_CANT_PERFORM_OP
  158. --*/
  159. {
  160. char *NewString;
  161. if ((ClaimedStringLength < 2) || (ClaimedStringLength > 1000))
  162. return EP_S_CANT_PERFORM_OP;
  163. if (StringStart + ClaimedStringLength > (char *)UpperBound)
  164. return EP_S_CANT_PERFORM_OP;
  165. // the claimed string length includes the terminating NULL
  166. if (StringStart[ClaimedStringLength - 1] != '\0')
  167. return EP_S_CANT_PERFORM_OP;
  168. NewString = new char [ClaimedStringLength];
  169. if (NewString == NULL)
  170. return RPC_S_OUT_OF_MEMORY;
  171. RpcpMemoryCopy(NewString, StringStart, ClaimedStringLength);
  172. *ExtractedString = NewString;
  173. return RPC_S_OK;
  174. }
  175. RPC_STATUS
  176. LrpcTowerConstruct(
  177. IN char PAPI * Endpoint,
  178. OUT unsigned short PAPI UNALIGNED * Floors,
  179. OUT unsigned long PAPI UNALIGNED * ByteCount,
  180. OUT unsigned char PAPI * UNALIGNED PAPI * Tower
  181. )
  182. {
  183. unsigned long TowerSize;
  184. FLOOR_234 UNALIGNED *Floor;
  185. int EndpointLength;
  186. *Floors = NP_TOWERS_LRPC;
  187. if ((Endpoint == NULL) || (*Endpoint == '\0'))
  188. {
  189. EndpointLength = 0;
  190. }
  191. else
  192. {
  193. EndpointLength = RpcpStringLengthA(Endpoint) + 1;
  194. }
  195. if (EndpointLength == 0)
  196. TowerSize = 2;
  197. else
  198. TowerSize = EndpointLength;
  199. TowerSize += sizeof(FLOOR_234) - 2;
  200. *ByteCount = TowerSize;
  201. if ((*Tower = (unsigned char *)I_RpcAllocate(TowerSize)) == NULL)
  202. {
  203. return (RPC_S_OUT_OF_MEMORY);
  204. }
  205. Floor = (PFLOOR_234) *Tower;
  206. Floor->ProtocolIdByteCount = 1;
  207. Floor->FloorId = (unsigned char)(NP_TRANSPORTID_LRPC & 0xFF);
  208. if (EndpointLength)
  209. {
  210. Floor->AddressByteCount = (unsigned short)EndpointLength;
  211. RpcpMemoryCopy((char PAPI *)&Floor->Data[0], Endpoint,
  212. EndpointLength);
  213. }
  214. else
  215. {
  216. Floor->AddressByteCount = 2;
  217. Floor->Data[0] = 0;
  218. }
  219. return(RPC_S_OK);
  220. }
  221. RPC_STATUS
  222. LrpcTowerExplode(
  223. IN PFLOOR_234 Floor34,
  224. IN BYTE *UpperBound,
  225. IN ULONG RemainingFloors,
  226. OUT char ** Protseq, OPTIONAL
  227. OUT char ** Endpoint, OPTIONAL
  228. OUT char ** NetworkAddress OPTIONAL
  229. )
  230. {
  231. BYTE *CurrentPosition;
  232. BYTE *NextFloor;
  233. RPC_STATUS RpcStatus;
  234. ULONG EndpointLength;
  235. // Initialize all our OUT pointers so we don't end up deleting uninitialized memory
  236. if (Protseq)
  237. *Protseq = NULL;
  238. if (Endpoint)
  239. *Endpoint = NULL;
  240. // we expect only one floor more
  241. if (RemainingFloors != 1)
  242. return EP_S_CANT_PERFORM_OP;
  243. if (Protseq != NULL)
  244. {
  245. *Protseq = new char[LrpcProtocolSequenceLength];
  246. if (*Protseq == NULL)
  247. {
  248. return(RPC_S_OUT_OF_MEMORY);
  249. }
  250. RpcpMemoryCopy(*Protseq, "ncalrpc", LrpcProtocolSequenceLength);
  251. }
  252. if (Endpoint == NULL)
  253. {
  254. return (RPC_S_OK);
  255. }
  256. CurrentPosition = (BYTE *)Floor34;
  257. // an endpoint must be at least two chars long (null terminator included).
  258. // Since FLOOR_234 has space for 2 chars, we need to subtract one
  259. if (CurrentPosition + sizeof(FLOOR_234) >= UpperBound)
  260. return EP_S_CANT_PERFORM_OP;
  261. NextFloor = VerifyFloorLHSAndRHS (CurrentPosition,
  262. UpperBound,
  263. 3 // FloorNum
  264. );
  265. if (NextFloor == NULL)
  266. {
  267. RpcStatus = EP_S_CANT_PERFORM_OP;
  268. goto AbortAndExit;
  269. }
  270. EndpointLength = Floor34->AddressByteCount;
  271. RpcStatus = ExtractStringFromUntrustedPacket (UpperBound,
  272. EndpointLength,
  273. (char *)&Floor34->Data[0],
  274. Endpoint
  275. );
  276. if (RpcStatus == RPC_S_OK)
  277. return(RPC_S_OK);
  278. else
  279. {
  280. // fall through to cleanup call below
  281. }
  282. AbortAndExit:
  283. if (Protseq && *Protseq)
  284. delete [] *Protseq;
  285. if (Endpoint && *Endpoint)
  286. delete [] *Endpoint;
  287. return RpcStatus;
  288. }
  289. RPC_STATUS
  290. GetProtseqAndEndpointFromFloor3(
  291. IN PFLOOR_234 Floor,
  292. IN BYTE *UpperBound,
  293. IN ULONG RemainingFloors,
  294. OUT char **Protseq, OPTIONAL
  295. OUT char **Endpoint, OPTIONAL
  296. OUT char **NWAddress OPTIONAL
  297. )
  298. {
  299. /*++
  300. Routine Description:
  301. This function extracts the Protocol Sequence and Endpoint info
  302. from a "Lower Tower" representation
  303. Arguments:
  304. Floor - Pointer to Floor2 structure.
  305. UpperBound - the first invalid byte after the end of the buffer.
  306. RemainingFloors - the number of floors remaining.
  307. Protseq - A pointer that will contain Protocol seq on return
  308. The memory will be allocated by this routine and caller
  309. will have to free this memory using delete. Undefined on
  310. failure.
  311. Endpoint - A pointer that will contain Endpoint on return
  312. The memory will be allocated by this routine and caller
  313. will have to free this memory using delete. Undefined on
  314. failure.
  315. NWAddress - A pointer that will contain Endpoint on return
  316. The memory will be allocated by this routine and caller
  317. will have to free this memory using delete. Undefined on
  318. failure.
  319. Return Value:
  320. RPC_S_OK
  321. RPC_S_OUT_OF_MEMORY - There is no memory to return Protseq or Endpoint string
  322. EP_S_CANT_PERFORM_OP - Lower Tower Encoding is incorrect.
  323. --*/
  324. USHORT ProtocolType;
  325. RPC_STATUS Status;
  326. BYTE *CurrentPosition;
  327. PFLOOR_234 Floor34;
  328. CurrentPosition = (BYTE *)Floor;
  329. if (CurrentPosition + sizeof(FLOOR_234) >= UpperBound)
  330. {
  331. return EP_S_CANT_PERFORM_OP;
  332. }
  333. Floor34 = (PFLOOR_234)VerifyFloorLHSAndRHS(CurrentPosition,
  334. UpperBound,
  335. 2 // FloorNum
  336. );
  337. if (Floor34 == NULL)
  338. return EP_S_CANT_PERFORM_OP;
  339. ProtocolType = Floor->FloorId;
  340. if (NWAddress != 0)
  341. {
  342. *NWAddress = 0;
  343. }
  344. switch(ProtocolType)
  345. {
  346. case CONN_LRPC:
  347. Status = LrpcTowerExplode(Floor34, UpperBound, RemainingFloors - 1,
  348. Protseq, Endpoint, NWAddress);
  349. break;
  350. case CONNECTIONFUL:
  351. case CONNECTIONLESS:
  352. Status = OsfTowerExplode((BYTE *)Floor34, UpperBound, RemainingFloors - 1,
  353. Protseq, Endpoint, NWAddress);
  354. break;
  355. default:
  356. Status = EP_S_CANT_PERFORM_OP;
  357. }
  358. return(Status);
  359. }
  360. RPC_STATUS
  361. TowerExplode(
  362. IN twr_p_t Tower,
  363. OUT RPC_IF_ID *Ifid, OPTIONAL
  364. OUT RPC_TRANSFER_SYNTAX *XferId, OPTIONAL
  365. OUT char **Protseq, OPTIONAL
  366. OUT char **Endpoint, OPTIONAL
  367. OUT char **NWAddress OPTIONAL
  368. )
  369. /*++
  370. Routine Description:
  371. This function converts a DCE tower representation of various binding
  372. information to binding info that is suitable to MS runtime.
  373. Specically it returns Ifid, Xferid, Protseq and Endpoint information
  374. encoded in the tower.
  375. Arguments:
  376. Tower - Tower encoding.
  377. Ifid - A pointer to Ifid
  378. Xferid - A pointer to Xferid
  379. Protseq - A pointer to pointer returning Protseq
  380. Endpoint- A pointer to pointer returning Endpoint
  381. Return Value:
  382. RPC_S_OK
  383. EP_S_CANT_PERFORM_OP - Error while parsing the Tower encoding
  384. RPC_S_OUT_OF_MEMORY - There is no memory to return Protseq and Endpoint
  385. strings.
  386. --*/
  387. {
  388. PFLOOR_0OR1 Floor00;
  389. PFLOOR_0OR1 Floor01;
  390. PFLOOR_234 Floor234;
  391. unsigned short FloorCount;
  392. RPC_STATUS RpcStatus;
  393. BYTE *UpperBound, *LowerBound;
  394. BYTE *CurrentPosition;
  395. if (Tower == NULL)
  396. {
  397. RpcStatus = EP_S_CANT_PERFORM_OP;
  398. goto CleanupAndExit;
  399. }
  400. //
  401. // LowerBound points to Floor1
  402. // UpperBound points to the byte after the last Floor
  403. //
  404. LowerBound = Tower->tower_octet_string + 2; // FloorCount is 2 bytes
  405. UpperBound = Tower->tower_octet_string + Tower->tower_length;
  406. // make sure we at least have the floor count
  407. if (UpperBound <= LowerBound)
  408. {
  409. RpcStatus = EP_S_CANT_PERFORM_OP;
  410. goto CleanupAndExit;
  411. }
  412. // go to the floor count
  413. CurrentPosition = Tower->tower_octet_string;
  414. // the tower octet string immediately follows the tower_length in the IDL
  415. // so we know it is 4 bytes aligned. No need for unaligned here.
  416. FloorCount = *((USHORT *)CurrentPosition);
  417. if ( FloorCount > MAX_FLOOR_COUNT
  418. || FloorCount < MIN_FLOOR_COUNT)
  419. {
  420. #ifdef DEBUGRPC
  421. PrintToDebugger("RPC: TowerVerify(): Too many/few floors - %d\n",
  422. FloorCount);
  423. #endif // DEBUGRPC
  424. RpcStatus = EP_S_CANT_PERFORM_OP;
  425. goto CleanupAndExit;
  426. }
  427. // skip the floor count and go to the first floor
  428. CurrentPosition += 2; // floor count is 2 bytes
  429. if (CurrentPosition + sizeof(FLOOR_0OR1) >= UpperBound)
  430. {
  431. RpcStatus = EP_S_CANT_PERFORM_OP;
  432. goto CleanupAndExit;
  433. }
  434. Floor01 = (PFLOOR_0OR1)VerifyFloorLHSAndRHS(CurrentPosition,
  435. UpperBound,
  436. 0 // FloorNum
  437. );
  438. if (Floor01 == NULL)
  439. {
  440. RpcStatus = EP_S_CANT_PERFORM_OP;
  441. goto CleanupAndExit;
  442. }
  443. Floor00 = (PFLOOR_0OR1) CurrentPosition;
  444. //Process Floor 0 Interface Spec.
  445. if (Ifid != NULL)
  446. {
  447. RpcStatus = Floor0or1ToId(Floor00, (PGENERIC_ID) Ifid);
  448. if (RpcStatus != RPC_S_OK)
  449. {
  450. RpcStatus = EP_S_CANT_PERFORM_OP;
  451. goto CleanupAndExit;
  452. }
  453. }
  454. CurrentPosition = (BYTE *)Floor01;
  455. if (CurrentPosition + sizeof(FLOOR_0OR1) >= UpperBound)
  456. {
  457. RpcStatus = EP_S_CANT_PERFORM_OP;
  458. goto CleanupAndExit;
  459. }
  460. Floor234 = (PFLOOR_234)VerifyFloorLHSAndRHS(CurrentPosition,
  461. UpperBound,
  462. 1 // FloorNum
  463. );
  464. if (Floor234 == NULL)
  465. {
  466. RpcStatus = EP_S_CANT_PERFORM_OP;
  467. goto CleanupAndExit;
  468. }
  469. //Now we point to and process Floor 1 Transfer Syntax Spec.
  470. if (XferId != NULL)
  471. {
  472. RpcStatus = Floor0or1ToId(Floor01, (PGENERIC_ID) XferId);
  473. if (RpcStatus != RPC_S_OK)
  474. {
  475. RpcStatus = EP_S_CANT_PERFORM_OP;
  476. goto CleanupAndExit;
  477. }
  478. }
  479. // Now Floor234 points to Floor 2. RpcProtocol [Connect-Datagram]
  480. // we already did 2 floors - subtract them from the count of floors
  481. RpcStatus = GetProtseqAndEndpointFromFloor3(Floor234, UpperBound, FloorCount - 2, Protseq, Endpoint, NWAddress);
  482. // fall through with the status
  483. CleanupAndExit:
  484. #if DBG
  485. if (RpcStatus != RPC_S_OK)
  486. {
  487. DbgPrint("RPCRT4: %X: TowerExplode: Failed to decrypt tower: %X\n",
  488. GetCurrentProcessId(), RpcStatus);
  489. }
  490. #endif // DBG
  491. return RpcStatus;
  492. }
  493. RPC_STATUS
  494. TowerConstruct(
  495. IN RPC_IF_ID PAPI * Ifid,
  496. IN RPC_TRANSFER_SYNTAX PAPI * Xferid,
  497. IN char PAPI * RpcProtocolSequence,
  498. IN char PAPI * Endpoint, OPTIONAL
  499. IN char PAPI * NWAddress, OPTIONAL
  500. OUT twr_t PAPI * PAPI * Tower
  501. )
  502. /*++
  503. Routine Description:
  504. This function constructs a DCE tower representation from
  505. Protseq, Endpoint, XferId and IfId
  506. Arguments:
  507. Ifid - A pointer to Ifid
  508. Xferid - A pointer to Xferid
  509. Protseq - A pointer to Protseq
  510. Endpoint- A pointer to Endpoint
  511. Tower - The constructed tower returmed - The memory is allocated
  512. by the routine and caller will have to free it.
  513. Return Value:
  514. RPC_S_OK
  515. EP_S_CANT_PERFORM_OP - Error while parsing the Tower encoding
  516. RPC_S_OUT_OF_MEMORY - There is no memory to return the constructed
  517. Tower.
  518. --*/
  519. {
  520. unsigned short Numfloors, PAPI *FloorCnt;
  521. twr_t PAPI * Twr;
  522. PFLOOR_0OR1 Floor;
  523. PFLOOR_234 Floor234, Floor234_1;
  524. RPC_STATUS Status;
  525. unsigned long TowerLen, ByteCount;
  526. char PAPI * UpperTower;
  527. unsigned short ProtocolType;
  528. if ( RpcpStringCompareA(RpcProtocolSequence, "ncalrpc") == 0 )
  529. {
  530. ProtocolType = CONN_LRPC;
  531. Status = LrpcTowerConstruct(Endpoint, &Numfloors,
  532. &ByteCount, (unsigned char **)&UpperTower);
  533. }
  534. else
  535. {
  536. if ( (RpcProtocolSequence[0] == 'n')
  537. && (RpcProtocolSequence[1] == 'c')
  538. && (RpcProtocolSequence[2] == 'a')
  539. && (RpcProtocolSequence[3] == 'c')
  540. && (RpcProtocolSequence[4] == 'n')
  541. && (RpcProtocolSequence[5] == '_'))
  542. {
  543. ProtocolType = CONNECTIONFUL;
  544. }
  545. else if ( (RpcProtocolSequence[0] == 'n')
  546. && (RpcProtocolSequence[1] == 'c')
  547. && (RpcProtocolSequence[2] == 'a')
  548. && (RpcProtocolSequence[3] == 'd')
  549. && (RpcProtocolSequence[4] == 'g')
  550. && (RpcProtocolSequence[5] == '_'))
  551. {
  552. ProtocolType = CONNECTIONLESS;
  553. }
  554. else
  555. {
  556. return(RPC_S_INVALID_RPC_PROTSEQ);
  557. }
  558. Status = OsfTowerConstruct(
  559. RpcProtocolSequence,
  560. Endpoint,
  561. NWAddress,
  562. &Numfloors,
  563. &ByteCount,
  564. (unsigned char **)&UpperTower
  565. );
  566. }
  567. if (Status != RPC_S_OK)
  568. {
  569. return (Status);
  570. }
  571. TowerLen = 2 + ByteCount;
  572. TowerLen += 2 * sizeof(FLOOR_0OR1) + sizeof(FLOOR_2) ;
  573. if ( (*Tower = Twr = (twr_t *)I_RpcAllocate((unsigned int)TowerLen+4)) == NULL)
  574. {
  575. I_RpcFree(UpperTower);
  576. return(RPC_S_OUT_OF_MEMORY);
  577. }
  578. Twr->tower_length = TowerLen;
  579. FloorCnt = (unsigned short PAPI *)&Twr->tower_octet_string;
  580. *FloorCnt = Numfloors;
  581. Floor = (PFLOOR_0OR1)(FloorCnt+1);
  582. //Floor 0 - IfUuid and IfVersion
  583. CopyIdToFloor(Floor, (PGENERIC_ID)Ifid);
  584. Floor++;
  585. //Floor 1 - XferUuid and XferVersion
  586. CopyIdToFloor(Floor, (PGENERIC_ID)Xferid);
  587. //Floor 2
  588. //ProtocolId = CONNECTIONFUL/CONNECTIONLESS/LRPC and Address = 0(ushort)
  589. Floor234 = (PFLOOR_234) (Floor + 1);
  590. Floor234->ProtocolIdByteCount = 1;
  591. Floor234->FloorId = (byte) ProtocolType;
  592. Floor234->Data[0] = 0x0;
  593. Floor234->Data[1] = 0x0;
  594. Floor234->AddressByteCount = 2;
  595. //Floor 3,4,5.. use the tower encoded by the Transports
  596. Floor234_1 = NEXTFLOOR(PFLOOR_234, Floor234);
  597. RpcpMemoryCopy((char PAPI *)Floor234_1, (char PAPI *)UpperTower,
  598. (size_t)ByteCount);
  599. I_RpcFree(UpperTower);
  600. return(RPC_S_OK);
  601. }
  602. #pragma pack()