Windows NT 4.0 source code leak
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.

682 lines
15 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. cltnvns.c
  5. Abstract:
  6. This is the client side loadable transport module for VINES
  7. Author:
  8. tony chan (tonychan) 5-May-1995 Creation
  9. Revision History:
  10. --*/
  11. typedef int SOCKET;
  12. #define SOCKADDR_VNS struct vns_sockaddr
  13. #define FD_SETSIZE 1
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include "sysinc.h"
  17. #include "rpc.h"
  18. #include "rpcdcep.h"
  19. #include "rpctran.h"
  20. #include "rpcerrp.h"
  21. // Vines includes
  22. #define INCL_SOCK
  23. #define INCL_ST
  24. #define INCL_WS
  25. #include <vnsapi.h>
  26. #define PFC_FIRST_FRAG 0x01
  27. typedef struct
  28. {
  29. SOCKET Socket;
  30. long Timeout;
  31. unsigned long TickCount;
  32. char PAPI * Buffer;
  33. unsigned short State;
  34. unsigned short PeekInfo;
  35. /* bogus int for sockset */
  36. int SockSet;
  37. BOOL LocalRpc;
  38. IPCPORT remoteport; /* address to keep around for VINES */
  39. unsigned int cid;
  40. IPCPORT localport;
  41. } CONNECTION, *PCONNECTION;
  42. typedef struct
  43. {
  44. short numofport;
  45. char porttype;
  46. IPCPORT ipcport;
  47. } VNSRECORD;
  48. #define ENDIAN_MASK 16
  49. #define NO_MORE_SENDS_OR_RECVS 2
  50. #define ENDPOINT_LEN 5
  51. // The maximum send is the size of four user data frames on an ethernet.
  52. #define MAXIMUM_SEND ((3 * 1450) & 0xFFF8)
  53. #define HOSTNAME_LEN 32
  54. #define DLL_NAME "rpcltc8.dll"
  55. #define ENDPOINT_MAPPER_EP "385"
  56. #define ADDRESS_FAMILY AF_BAN
  57. #define SOCKET_TYPE SOCK_SEQPACKET
  58. #define PROTOCOL -1
  59. typedef unsigned char BYTE;
  60. typedef unsigned short WORD;
  61. #define LOBYTE(w) ((BYTE)(w))
  62. #define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF))
  63. #define MAKEWORD(a, b) ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))
  64. #define SET_PORT(p,wkp) \
  65. ((p[8] = (unsigned char)HIBYTE((unsigned short) wkp), \
  66. p[9] = (unsigned char)LOBYTE((unsigned short) wkp)))
  67. /* define to make compiler happy, llibban calls malloc, free */
  68. void * __cdecl __loadds malloc(size_t x)
  69. {
  70. return(I_RpcAllocate(x));
  71. }
  72. void __cdecl __loadds free(void * t)
  73. {
  74. I_RpcFree(t);
  75. }
  76. /*
  77. Shutdown Detection Garbage
  78. */
  79. /* BUG: do we need these? */
  80. #define NOPENDINGRPC 0
  81. #define RPCINITIATED 1
  82. #define NOPEEKINFO 0
  83. #define PEEKEDHEADER 1
  84. #define PEEKEDBUFFER 2
  85. #define rpc_shutdown 17
  86. #define rpc_fault 3
  87. /*
  88. Following Macros and structs are needed for Tower Stuff
  89. */
  90. #pragma pack(1)
  91. #define TRANSPORTID 0x1A
  92. #define TRANSPORTHOSTID 0x1C
  93. #define TOWERFLOORS 5
  94. #define TOWEREPSIZE 4
  95. #define TOWERSIZE (TOWEREPSIZE+2)
  96. #define PROTSEQ "ncacn_vns_spp"
  97. typedef struct _FLOOR_234 {
  98. unsigned short ProtocolIdByteCount;
  99. unsigned char FloorId;
  100. unsigned short AddressByteCount;
  101. unsigned char Data[2];
  102. } FLOOR_234;
  103. typedef FLOOR_234 PAPI UNALIGNED * PFLOOR_234;
  104. #define NEXTFLOOR(t,x) (t)((unsigned char PAPI *)x +((t)x)->ProtocolIdByteCount\
  105. + ((t)x)->AddressByteCount\
  106. + sizeof(((t)x)->ProtocolIdByteCount)\
  107. + sizeof(((t)x)->AddressByteCount))
  108. /*
  109. End of Tower Stuff!
  110. */
  111. #pragma pack()
  112. RPC_STATUS RPC_ENTRY
  113. ClientOpen (
  114. IN PCONNECTION pConn,
  115. IN RPC_CHAR * NetworkAddress,
  116. IN RPC_CHAR * Endpoint,
  117. IN RPC_CHAR * NetworkOptions,
  118. IN RPC_CHAR * TransportAddress,
  119. IN RPC_CHAR * RpcProtocolSequence,
  120. IN unsigned int Timeout
  121. )
  122. // Open a client connection
  123. {
  124. int err;
  125. // Vines add on
  126. VNS_ST_SESS StSess;
  127. IPCPORT remoteport;
  128. struct sockreq srdata; /* to send/receive data */
  129. CallStatus cs;
  130. VNSRECORD vnsrecord ;
  131. short len = STNAMELEN;
  132. char LocalNetworkAddress[63];
  133. #if 0
  134. _asm
  135. {
  136. int 3
  137. }
  138. #endif
  139. /* copy to the stack */
  140. _fstrcpy(LocalNetworkAddress, NetworkAddress);
  141. if (NetworkAddress == NULL || NetworkAddress[0] == '\0')
  142. {
  143. /* local server is not supported right? */
  144. return(RPC_S_SERVER_UNAVAILABLE);
  145. }
  146. memset(&remoteport,0,sizeof(IPCPORT));
  147. memset(&StSess, 0, sizeof(VNS_ST_SESS));
  148. memset(&srdata, 0, sizeof(struct sockreq));
  149. cs = VnsStartStSession(NULL, TRUE, NULL, &StSess);
  150. if(cs != 0)
  151. {
  152. #ifdef DEBUGPRC
  153. _asm
  154. {
  155. int 3
  156. }
  157. #endif
  158. return(RPC_S_SERVER_UNAVAILABLE);
  159. }
  160. memset(&vnsrecord, 0, sizeof(VNSRECORD));
  161. vnsrecord.numofport = 1;
  162. vnsrecord.porttype = 1;
  163. /* find out which interrupt to call */
  164. {
  165. _asm
  166. {
  167. push ax
  168. push bx
  169. push dx
  170. push ds
  171. push di
  172. mov ax, 0d701h
  173. /* calling BANYAN to find out interrupt */
  174. mov bx, 0
  175. int 2fh
  176. cmp bl, 60h
  177. jb BAD
  178. clc
  179. mov ax, bx
  180. jmp BANCALL
  181. BAD:
  182. int 3
  183. }
  184. }
  185. {
  186. _asm
  187. {
  188. BANCALL:
  189. /* creating self-modifiing code
  190. WARNING: don't put vnsrecord as global
  191. DS of overlads != SS of Caller
  192. */
  193. mov ah, al
  194. mov al, 0CDh
  195. lea bx, SELF
  196. mov WORD PTR CS:[bx], ax
  197. mov ax, ss
  198. lea dx, LocalNetworkAddress
  199. lea di, vnsrecord
  200. mov ds, ax
  201. mov bx, 2
  202. mov ax, 7
  203. jmp SELF /* instruction becomes CDint#
  204. usually it's CD63 means int 63
  205. the jmp is for flushing the i cache
  206. */
  207. SELF:
  208. nop /* leave space for the self modify code */
  209. nop
  210. /* need to check ax for error message */
  211. pop di
  212. pop ds
  213. pop dx
  214. pop bx
  215. pop ax
  216. }
  217. }
  218. VnsEndStSession( &StSess );
  219. memcpy(&remoteport, &(vnsrecord.ipcport), sizeof(IPCPORT));
  220. SET_PORT(remoteport, atoi(Endpoint) );
  221. memcpy(&(pConn->remoteport), &(remoteport), sizeof(IPCPORT));
  222. //
  223. // Get a socket
  224. //
  225. err = VnsOpenSocket(&pConn->Socket, ADDRESS_FAMILY,
  226. SOCKET_TYPE, PROTOCOL, pConn->localport , 0);
  227. if (err != 0)
  228. {
  229. #if DEBUGRPC
  230. _asm
  231. {
  232. int 3
  233. }
  234. #endif
  235. return (RPC_S_SERVER_UNAVAILABLE);
  236. }
  237. err = 0;
  238. srdata.type = SO_CONNECT;
  239. srdata.msg = (char FAR *) NetworkAddress;
  240. srdata.len = 0;
  241. srdata.s = pConn->Socket;
  242. srdata.flags = SO_EOM ;
  243. srdata.timeout = (unsigned int)-1;
  244. memcpy(srdata.addr, remoteport, sizeof(IPCPORT));
  245. err = VnsSocketSend(&srdata);
  246. if (!err) err = srdata.error;
  247. if (err)
  248. {
  249. #if DEBUGRPC
  250. _asm
  251. {
  252. int 3
  253. }
  254. return(err);
  255. #endif
  256. return(RPC_S_SERVER_UNAVAILABLE);
  257. }
  258. /* save the cid for next send */
  259. pConn->cid = srdata.cid;
  260. pConn->Timeout = RPC_C_CANCEL_INFINITE_TIMEOUT;
  261. pConn->State = NOPENDINGRPC;
  262. pConn->PeekInfo = NOPEEKINFO;
  263. pConn->TickCount = 0;
  264. // Create hidden window to receive Async messages
  265. return (RPC_S_OK);
  266. }
  267. RPC_STATUS RPC_ENTRY
  268. ClientClose (
  269. IN PCONNECTION pConn
  270. )
  271. // Close a client connection
  272. {
  273. struct sockreq srdata;
  274. int err;
  275. srdata.type = SO_DISCONNECT;
  276. srdata.len = 0;
  277. srdata.s = pConn->Socket;
  278. srdata.flags = SO_EOM ;
  279. srdata.timeout = (unsigned int)-1;
  280. srdata.cid = pConn->cid;
  281. memcpy(srdata.addr, pConn->remoteport, sizeof(IPCPORT));
  282. err = VnsSocketSend(&srdata);
  283. if (!err) err = srdata.error;
  284. if (err)
  285. {
  286. return(RPC_S_INTERNAL_ERROR);
  287. }
  288. return (RPC_S_OK);
  289. }
  290. RPC_STATUS RPC_ENTRY
  291. ClientSend (
  292. IN PCONNECTION pConn,
  293. IN void PAPI * Buffer,
  294. IN unsigned int BufferLength
  295. )
  296. // Write a message to a connection. This operation is retried in case
  297. // the server is "busy".
  298. {
  299. struct sockreq srdata;
  300. int err;
  301. srdata.type = SO_DATA;
  302. srdata.msg = Buffer;
  303. srdata.len = BufferLength;
  304. srdata.s = pConn->Socket;
  305. srdata.flags = SO_EOM ;
  306. srdata.timeout = (unsigned int)-1;
  307. srdata.cid = pConn->cid;
  308. memcpy(srdata.addr, pConn->remoteport, sizeof(IPCPORT));
  309. err = VnsSocketSend(&srdata);
  310. if (!err)
  311. {
  312. err = srdata.error;
  313. }
  314. if (err)
  315. {
  316. return(RPC_P_SEND_FAILED);
  317. }
  318. return(RPC_S_OK);
  319. }
  320. RPC_TRANS_STATUS RPC_ENTRY
  321. ClientRecv (
  322. IN PCONNECTION pConn,
  323. IN OUT void PAPI * PAPI * Buffer,
  324. IN OUT unsigned int PAPI * BufferLength
  325. )
  326. // Read a message from a connection.
  327. {
  328. RPC_STATUS RpcStatus;
  329. struct sockreq srdata;
  330. int err;
  331. int total_bytes = 0;
  332. /* init */
  333. memset(&srdata,0,sizeof(struct sockreq));
  334. srdata.type = SO_DATA ;
  335. srdata.s = pConn->Socket;
  336. srdata.timeout = (unsigned int) -1 ;
  337. srdata.cid = pConn->cid;
  338. srdata.flags = SO_CREC;
  339. memcpy(srdata.addr, pConn->localport, sizeof(IPCPORT));
  340. /* allocate 1k for small messages */
  341. *BufferLength = 1450; /* that's the default buffer size for VINES */
  342. RpcStatus = I_RpcTransClientReallocBuffer(pConn,
  343. Buffer,
  344. 0,
  345. *BufferLength);
  346. if (RpcStatus != RPC_S_OK)
  347. {
  348. ClientClose(pConn);
  349. return(RPC_S_OUT_OF_MEMORY);
  350. }
  351. while(1)
  352. {
  353. srdata.msg =(char FAR *)*Buffer + total_bytes;
  354. srdata.len = *BufferLength - total_bytes;
  355. err = VnsSocketReceive(&srdata);
  356. if (!err)
  357. {
  358. err = srdata.error;
  359. }
  360. if((err != 0) && (err != BYMSGSIZE))
  361. {
  362. ClientClose ( pConn );
  363. return(RPC_P_RECEIVE_FAILED);
  364. }
  365. /* if((srdata.flags && SO_EOM )== SO_EOM) */
  366. if((srdata.flags != (SO_CREC + SO_EOM)))
  367. {
  368. total_bytes += srdata.cc;
  369. *BufferLength = MAXIMUM_SEND;
  370. RpcStatus = I_RpcTransClientReallocBuffer(pConn,
  371. Buffer,
  372. total_bytes,
  373. *BufferLength);
  374. if (RpcStatus != RPC_S_OK)
  375. {
  376. ClientClose ( pConn );
  377. return(RPC_S_OUT_OF_MEMORY);
  378. }
  379. }
  380. else
  381. {
  382. total_bytes += srdata.cc;
  383. *BufferLength = total_bytes;
  384. return(RPC_S_OK);
  385. }
  386. }
  387. return(RPC_S_INTERNAL_ERROR);
  388. }
  389. #pragma pack(1)
  390. RPC_STATUS RPC_ENTRY
  391. ClientTowerConstruct(
  392. IN char PAPI * Endpoint,
  393. IN char PAPI * NetworkAddress,
  394. OUT short PAPI * Floors,
  395. OUT unsigned long PAPI * ByteCount,
  396. OUT unsigned char PAPI * PAPI * Tower,
  397. IN char PAPI * Protseq
  398. )
  399. {
  400. unsigned long TowerSize;
  401. unsigned short portnum;
  402. UNALIGNED PFLOOR_234 Floor;
  403. unsigned short AddressSize = 0;
  404. /* Compute the memory size of the tower. */
  405. *Floors = TOWERFLOORS;
  406. TowerSize = TOWERSIZE;
  407. if (NetworkAddress == NULL || NetworkAddress[0] == '\0')
  408. {
  409. /* local server is not supported right? */
  410. return(RPC_S_SERVER_UNAVAILABLE);
  411. }
  412. AddressSize = (unsigned short) strlen(NetworkAddress) + 1;
  413. TowerSize += 2*sizeof(FLOOR_234) - 4 + AddressSize;
  414. /* Allocate memory for the tower. */
  415. *ByteCount = TowerSize;
  416. if ((*Tower = (unsigned char PAPI*)I_RpcAllocate((unsigned int)
  417. TowerSize)) == NULL)
  418. {
  419. return (RPC_S_OUT_OF_MEMORY);
  420. }
  421. memset(*Tower, 0, TowerSize);
  422. /* Put the endpoint address and transport protocol id in the first floor. */
  423. Floor = (PFLOOR_234) *Tower;
  424. Floor->ProtocolIdByteCount = 1;
  425. Floor->FloorId = (unsigned char)(TRANSPORTID & 0xFF);
  426. Floor->AddressByteCount = 2;
  427. if (Endpoint == NULL || *Endpoint == '\0')
  428. {
  429. Endpoint = ENDPOINT_MAPPER_EP;
  430. }
  431. portnum = (unsigned short) atoi (Endpoint) ;
  432. Floor->Data[0] = HIBYTE(portnum) ;
  433. Floor->Data[1] = LOBYTE(portnum) ;
  434. /* Put the network address and the transport host protocol id in the
  435. second floor. */
  436. Floor = NEXTFLOOR(PFLOOR_234, Floor);
  437. Floor->ProtocolIdByteCount = 1;
  438. Floor->FloorId = (unsigned char)(TRANSPORTHOSTID & 0xFF);
  439. Floor->AddressByteCount = TOWEREPSIZE;
  440. Floor->Data[0] = '\0';
  441. Floor->Data[1] = '\0';
  442. if ((NetworkAddress) && (*NetworkAddress))
  443. {
  444. Floor->AddressByteCount = AddressSize ;
  445. memcpy((char PAPI *)&Floor->Data[0], NetworkAddress, AddressSize);
  446. }
  447. else
  448. return ( RPC_S_OUT_OF_MEMORY ) ;
  449. return(RPC_S_OK);
  450. }
  451. RPC_STATUS RPC_ENTRY
  452. ClientTowerExplode(
  453. IN unsigned char PAPI * Tower,
  454. OUT char PAPI * PAPI * Protseq,
  455. OUT char PAPI * PAPI * Endpoint,
  456. OUT char PAPI * PAPI * NetworkAddress
  457. )
  458. {
  459. UNALIGNED PFLOOR_234 Floor = (PFLOOR_234) Tower;
  460. RPC_STATUS Status = RPC_S_OK;
  461. unsigned short portnum;
  462. if (Protseq != NULL)
  463. {
  464. *Protseq = I_RpcAllocate(strlen(PROTSEQ) + 1);
  465. if (*Protseq == NULL)
  466. Status = RPC_S_OUT_OF_MEMORY;
  467. else
  468. memcpy(*Protseq, PROTSEQ, strlen(PROTSEQ) + 1);
  469. }
  470. if ((Endpoint == NULL) || (Status != RPC_S_OK))
  471. {
  472. return (Status);
  473. }
  474. *Endpoint = I_RpcAllocate(ENDPOINT_LEN+1); //Ports are all <64K [5 decimal dig +1]
  475. if (*Endpoint == NULL)
  476. {
  477. Status = RPC_S_OUT_OF_MEMORY;
  478. if (Protseq != NULL)
  479. {
  480. I_RpcFree(*Protseq);
  481. }
  482. }
  483. else
  484. {
  485. portnum = MAKEWORD(Floor->Data[1], Floor->Data[0]) ;
  486. _itoa(portnum, *Endpoint, 10);
  487. }
  488. return(Status);
  489. }
  490. #pragma pack()
  491. RPC_CLIENT_TRANSPORT_INFO TransInfo =
  492. {
  493. RPC_TRANSPORT_INTERFACE_VERSION,
  494. TRANSPORTID,
  495. ClientTowerConstruct,
  496. ClientTowerExplode,
  497. MAXIMUM_SEND,
  498. sizeof (CONNECTION),
  499. ClientOpen,
  500. ClientClose,
  501. ClientSend,
  502. ClientRecv,
  503. NULL,
  504. 0,
  505. 0,
  506. 0
  507. };
  508. RPC_CLIENT_TRANSPORT_INFO PAPI * RPC_ENTRY TransportLoad (
  509. IN RPC_CHAR PAPI * RpcProtocolSequence
  510. )
  511. // Loadable transport initialization function
  512. {
  513. UNUSED (RpcProtocolSequence);
  514. return(&TransInfo);
  515. }