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.

659 lines
21 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1994 - 1999
  6. //
  7. // File: np.c
  8. //
  9. //--------------------------------------------------------------------------
  10. /////////////////////////////////////////////////////////////////////////
  11. //
  12. // Filename: np.c
  13. //
  14. // Description: This file contains common routines for named pipe
  15. // routines for use with IPC raw networl performance
  16. // tests.
  17. // This module is written using win32 API calls.
  18. //
  19. // Authors: Scott Holden (Translator from NT API to win32 API)
  20. // Mahesh Keni (Mahesh wrote this application using mostly
  21. // NT native API calls)
  22. //
  23. /////////////////////////////////////////////////////////////////////////
  24. #include "rawcom.h"
  25. #include "np.h"
  26. /*++
  27. NamedPipe function implementations
  28. --*/
  29. /************************************************************************/
  30. NTSTATUS
  31. NMP_Initialize(
  32. IN USHORT NClients,
  33. IN PCHAR ServerName,
  34. IN USHORT SrvCli)
  35. {
  36. CHAR TempSrv[256];
  37. // use local pipe name for server or if Name not provided
  38. if (SrvCli || (!ServerName)) {
  39. strcpy(TempSrv,PERF_PIPE);
  40. }
  41. else{
  42. if (!ServerName) {
  43. strcpy(TempSrv, RM_PERF_PIPE_PRFX);
  44. }
  45. else {
  46. strcpy(TempSrv, (const char *)ServerName);
  47. }
  48. strcat(TempSrv, RM_PERF_PIPE_SUFX);
  49. }
  50. printf("NMP: Pipe name - %s\n", TempSrv);
  51. pipeName = _strdup(TempSrv);
  52. return(STATUS_SUCCESS);
  53. }
  54. /************************************************************************/
  55. /*++
  56. This routine is responsible Creating a NamedPipe instance for the given
  57. thread.
  58. --*/
  59. NTSTATUS
  60. NMP_PerClientInit(
  61. IN USHORT CIndex, // client index
  62. IN USHORT SrvCli )
  63. {
  64. NTSTATUS pstatus = 0;
  65. if (SrvCli) {
  66. // create namedpipe for this client
  67. pstatus = CreateNamedPipeInstance(CIndex);
  68. }
  69. else { // for Client initialize all the thread parameters
  70. ;
  71. }
  72. return pstatus;
  73. }
  74. /************************************************************************/
  75. /*++
  76. This routine is responsible for issueing Listen and waiting till a
  77. client is connected. When this routine returns successfully we can
  78. assume that a connection is established.
  79. --*/
  80. NTSTATUS
  81. NMP_Wait_For_Client(
  82. IN USHORT CIndex) // client index and namedpipe instance number
  83. {
  84. NTSTATUS wstatus;
  85. wstatus = ConnectNamedPipe(Clients[CIndex].c_Nmp.c_PipeHandle,
  86. NULL);
  87. if (wstatus == FALSE) {
  88. printf("Error: ConnectNamedPipe - 0x%08x, %ld\n", GetLastError(), GetLastError());
  89. }
  90. return (wstatus);
  91. }
  92. /************************************************************************/
  93. /*++
  94. This routine is responsible for issueing Disconnect to close the
  95. connection with a client.
  96. --*/
  97. NTSTATUS
  98. NMP_Disconnect_Client(
  99. IN USHORT CIndex) // client index and namedpipe instance number
  100. {
  101. NTSTATUS dstatus;
  102. // post a Disconnect
  103. // first find the status of the pipe to make sure that it's empty
  104. dstatus = FlushFileBuffers(Clients[CIndex].c_Nmp.c_PipeHandle);
  105. if (dstatus == FALSE) {
  106. printf("Error: FlushFileBuffers failed - 0x%08x\n", GetLastError());
  107. }
  108. dstatus = DisconnectNamedPipe(Clients[CIndex].c_Nmp.c_PipeHandle);
  109. if (dstatus == FALSE) {
  110. printf("Error: DisconnectNamedPipe failed - 0x%08x, %ld\n", GetLastError(), GetLastError());
  111. }
  112. return dstatus;
  113. }
  114. /************************************************************************/
  115. /*++
  116. This routine is responsible for establishing a connection to the
  117. server side. When this routine returns successfully we can assume that
  118. a connection is established.
  119. --*/
  120. NTSTATUS
  121. NMP_Connect_To_Server(
  122. IN USHORT CIndex) // client index and namedpipe instance number
  123. {
  124. NTSTATUS cstatus;
  125. DWORD dwPipeMode;
  126. Clients[CIndex].c_Nmp.c_PipeHandle = CreateFile( //connect to the server
  127. pipeName, // address of filename
  128. GENERIC_READ | GENERIC_WRITE, // access mode
  129. 0L, // share mode
  130. NULL, // security attributes
  131. OPEN_EXISTING, // create mode
  132. 0L, // attributes and flags
  133. NULL); // template file handle
  134. if (Clients[CIndex].c_Nmp.c_PipeHandle == INVALID_HANDLE_VALUE) {
  135. printf("Error: CreateFile failed - 0x%08x\n", GetLastError());
  136. cstatus = FALSE;
  137. }
  138. else {
  139. dwPipeMode = PIPE_READMODE_MESSAGE;
  140. cstatus = SetNamedPipeHandleState(Clients[CIndex].c_Nmp.c_PipeHandle, // pipe handle
  141. &dwPipeMode, // new pipe mode
  142. NULL, // do not set the max bytes
  143. NULL); // do not set the max time
  144. if (cstatus == FALSE) {
  145. printf("Error: SetNamedPipeHandleState failed - 0x%08x\n", GetLastError());
  146. }
  147. }
  148. return(cstatus);
  149. }
  150. /************************************************************************/
  151. /*++
  152. This routine allocates memory required for all the buffers for a client.
  153. --*/
  154. NTSTATUS
  155. NMP_Allocate_Memory(
  156. IN USHORT CIndex) // client index and namedpipe instance number
  157. {
  158. NTSTATUS astatus = STATUS_SUCCESS;
  159. ULONG AllocSize;
  160. AllocSize = MAXBUFSIZE;
  161. (LPVOID) Clients[CIndex].c_pSendBuf = VirtualAlloc(
  162. (LPVOID) Clients[CIndex].c_pSendBuf,
  163. (DWORD)AllocSize,
  164. (DWORD)MEM_COMMIT,
  165. (DWORD)PAGE_READWRITE);
  166. sprintf(Clients[CIndex].c_pSendBuf,"Client%d Send Data",CIndex+1);
  167. if (Clients[CIndex].c_pSendBuf == NULL) {
  168. astatus = GetLastError();
  169. printf("\nVirtual Alloc error\n");
  170. }
  171. AllocSize = MAXBUFSIZE;
  172. (LPVOID) Clients[CIndex].c_pRecvBuf = VirtualAlloc(
  173. (LPVOID) Clients[CIndex].c_pRecvBuf,
  174. (DWORD)AllocSize,
  175. (DWORD)MEM_COMMIT,
  176. (DWORD)PAGE_READWRITE);
  177. sprintf(Clients[CIndex].c_pRecvBuf,"Client%d Recv Data",CIndex+1);
  178. if (Clients[CIndex].c_pRecvBuf == NULL) {
  179. astatus = GetLastError();
  180. printf("\nVirtual Alloc error\n");
  181. }
  182. return astatus;
  183. }
  184. /************************************************************************/
  185. /*++
  186. This routine deallocates memory for a client.
  187. --*/
  188. NTSTATUS
  189. NMP_Deallocate_Memory(
  190. IN USHORT CIndex) // client index and namedpipe instance number
  191. {
  192. NTSTATUS dstatus;
  193. ULONG DeallocSize;
  194. DeallocSize = MAXBUFSIZE;
  195. dstatus = VirtualFree(
  196. (LPVOID) Clients[CIndex].c_pSendBuf,
  197. DeallocSize,
  198. MEM_DECOMMIT);
  199. if (!NT_SUCCESS(dstatus)) {
  200. return dstatus;
  201. }
  202. DeallocSize = MAXBUFSIZE;
  203. dstatus = VirtualFree(
  204. (LPVOID) Clients[CIndex].c_pRecvBuf,
  205. DeallocSize,
  206. MEM_DECOMMIT);
  207. if (!NT_SUCCESS(dstatus)) {
  208. return dstatus;
  209. }
  210. return dstatus;
  211. }
  212. /************************************************************************/
  213. /*++
  214. This routine is responsible for disconnecting a session.
  215. --*/
  216. NTSTATUS
  217. NMP_Disconnect_From_Server(
  218. IN USHORT CIndex) // client index and namedpipe instance number
  219. {
  220. NTSTATUS dstatus;
  221. dstatus = CloseHandle(Clients[CIndex].c_Nmp.c_PipeHandle);
  222. if (!NT_SUCCESS(dstatus)) {
  223. //DbgPrint("Nmp: Error in Disconnect err: %lx \n", dstatus);
  224. }
  225. return (dstatus);
  226. }
  227. /************************************************************************/
  228. // no need for this function
  229. /*
  230. NTSTATUS
  231. NamedPipe_FsControl(
  232. IN HANDLE lhandle,
  233. IN ULONG FsControlCode,
  234. IN PVOID pInBuffer,
  235. IN ULONG InBufLen,
  236. OUT PVOID pOutBuffer,
  237. IN ULONG OutBufLen)
  238. {
  239. NTSTATUS lstatus;
  240. IO_STATUS_BLOCK ioStatusBlock;
  241. DWORD actOutBufLen;
  242. // now post listen on this handle
  243. lstatus = NtFsControlFile (
  244. lhandle,
  245. NULL,
  246. NULL,
  247. NULL,
  248. &ioStatusBlock,
  249. FsControlCode, // LISTEN or DISCONNECT or TRANSCEIVE maybe PEEK
  250. pInBuffer,
  251. InBufLen,
  252. pOutBuffer, // Xceive or Peek buffer NULL otherwise
  253. OutBufLen // Xceive or peek buffer length 0L otherwise
  254. );
  255. lstatus = TransactNamedPipe(lhandle, // pipe handle
  256. pInBuffer, // write buffer
  257. InBufLen, // write buffer length
  258. pOutBuffer, // read buffer
  259. OutBufLen, // read buffer length
  260. &actOutBufLen, // the actual number of bytes read from the buffer
  261. NULL);
  262. if (lstatus == STATUS_PENDING) {
  263. lstatus = WaitForSingleObjectEx(lhandle,
  264. INFINITE,
  265. TRUE);
  266. if (NT_SUCCESS(lstatus)) {
  267. lstatus = ioStatusBlock.Status;
  268. if (!NT_SUCCESS(lstatus) &&(FsControlCode != FSCTL_PIPE_TRANSCEIVE)) {
  269. //DbgPrint("Listen/Disconn/Xceive failed, err=%lx\n", lstatus);
  270. }
  271. }
  272. else {
  273. //DbgPrint("Error in Wait while FsCtrl %lx\n",lstatus);}
  274. }
  275. else {
  276. if (NT_SUCCESS(lstatus)) {
  277. lstatus = ioStatusBlock.Status;
  278. }
  279. else {
  280. //DbgPrint("Error in FSCTL: %lx\n", lstatus);
  281. }
  282. }
  283. return(lstatus);
  284. }
  285. /*
  286. /************************************************************************/
  287. /*++
  288. This routine does handshake with it's peer. For Server this means
  289. receiving request message from a client. For Client it means just the
  290. opposite.
  291. --*/
  292. NTSTATUS
  293. NMP_DoHandshake(
  294. IN USHORT CIndex, // client index and namedpipe instance number
  295. IN USHORT SrvCli // if it's a server or client
  296. )
  297. {
  298. NTSTATUS dstatus;
  299. ULONG RWLen;
  300. ULONG RWreqLen;
  301. RWreqLen = sizeof(struct reqbuf);
  302. // for server do receive for a request buffer
  303. if (SrvCli) {
  304. dstatus = ReadNamedPipe(
  305. Clients[CIndex].c_Nmp.c_PipeHandle,
  306. RWreqLen,
  307. (PVOID) &(Clients[CIndex].c_reqbuf),
  308. (PULONG) &RWLen);
  309. if (!NT_SUCCESS(dstatus)) {
  310. //DbgPrint("Nmp: Error in ReadNamedPipe: err:%lx \n", dstatus);
  311. return dstatus;
  312. }
  313. }
  314. else { // for Client do send of reqbuf size
  315. // Based on TestCmd make changes i.e. 'U'->'P'
  316. dstatus = WriteNamedPipe(
  317. Clients[CIndex].c_Nmp.c_PipeHandle,
  318. RWreqLen,
  319. (PVOID) &(Clients[CIndex].c_reqbuf),
  320. (PULONG) &RWLen);
  321. if (!NT_SUCCESS(dstatus)) {
  322. //DbgPrint("Nmp: Error in WriteNamedPipe: err:%lx \n", dstatus);
  323. return dstatus;
  324. }
  325. }
  326. // check if read/write length is ok
  327. if (RWLen != sizeof(struct reqbuf)) {
  328. //DbgPrint("Nmp: Read/WriteNamedPipe Len mismatch: read %ld \n", RWLen);
  329. }
  330. // MyDbgPrint("handshake: Sendl:%ld Recvl:%ld \n",Clients[CIndex].c_reqbuf.SendSize,Clients[CIndex].c_reqbuf.RecvSize);
  331. return dstatus;
  332. }
  333. /************************************************************************/
  334. /*++
  335. This routine Reads data from IPC. For server it means reading data
  336. NumSends times in SendBuffers and for a client NumRecvs times into
  337. RecvBuffer.
  338. --*/
  339. NTSTATUS
  340. NMP_ReadFromIPC(
  341. IN USHORT CIndex, // client index and namedpipe instance number
  342. IN OUT PULONG pReadDone,
  343. IN USHORT SrvCli) // if it's a server or client
  344. {
  345. NTSTATUS rstatus;
  346. ULONG NumReads;
  347. ULONG ReadLen;
  348. PCHAR ReadBuf;
  349. if (SrvCli) { // set proper iterations and buffer for Server
  350. NumReads = Clients[CIndex].c_reqbuf.NumSends;
  351. ReadBuf = Clients[CIndex].c_pSendBuf;
  352. ReadLen = Clients[CIndex].c_reqbuf.SendSize;
  353. }
  354. else { // for client do proper settings
  355. NumReads = Clients[CIndex].c_reqbuf.NumRecvs;
  356. ReadBuf = Clients[CIndex].c_pRecvBuf;
  357. ReadLen = Clients[CIndex].c_reqbuf.RecvSize;
  358. }
  359. while (NumReads--) {
  360. rstatus = ReadNamedPipe(
  361. Clients[CIndex].c_Nmp.c_PipeHandle,
  362. ReadLen,
  363. (PVOID) ReadBuf,
  364. (PULONG) pReadDone);
  365. if (!NT_SUCCESS(rstatus)) {
  366. //DbgPrint("Nmp: Error in ReadNamedPipe: err:%lx \n", rstatus);
  367. break;
  368. }
  369. }
  370. return rstatus;
  371. }
  372. /************************************************************************/
  373. NTSTATUS
  374. ReadNamedPipe(
  375. IN HANDLE rhandle,
  376. IN ULONG rlength,
  377. IN OUT PVOID rpbuffer,
  378. IN OUT PULONG rpdatalen)
  379. {
  380. NTSTATUS rstatus;
  381. DWORD actRLength;
  382. rstatus = ReadFile( rhandle, // pipe handle
  383. rpbuffer, // buffer to receive reply
  384. rlength, // size of the buffer
  385. &actRLength, // number of bytes read
  386. NULL); // not overlapped
  387. if (rstatus == TRUE) {
  388. *rpdatalen = actRLength;
  389. }
  390. else {
  391. if (GetLastError() == ERROR_MORE_DATA) {
  392. rstatus = WaitForSingleObjectEx(rhandle,
  393. INFINITE,
  394. TRUE);
  395. if (rstatus == TRUE) {
  396. *rpdatalen = actRLength;
  397. if (rlength != *rpdatalen) {
  398. printf("Error: No. of bytes read != buffer length\n");
  399. }
  400. }
  401. }
  402. }
  403. return(rstatus);
  404. }
  405. /************************************************************************/
  406. /*++
  407. This routine Writes data to IPC. For server it means writing data
  408. NumRecvs times in RecvBuffers and for a client NumSends times into
  409. SendBuffer.
  410. --*/
  411. NTSTATUS
  412. NMP_WriteToIPC(
  413. IN USHORT CIndex, // client index and namedpipe instance number
  414. IN OUT PULONG pWriteDone,
  415. IN USHORT SrvCli) // if it's a server or client
  416. {
  417. NTSTATUS wstatus;
  418. ULONG NumWrites;
  419. ULONG WriteLen;
  420. PCHAR WriteBuf;
  421. if (SrvCli) { // set proper iterations and buffer for Server
  422. NumWrites = Clients[CIndex].c_reqbuf.NumRecvs;
  423. WriteBuf = Clients[CIndex].c_pRecvBuf;
  424. WriteLen = Clients[CIndex].c_reqbuf.RecvSize;
  425. }
  426. else { // for client do proper settings
  427. NumWrites = Clients[CIndex].c_reqbuf.NumSends;
  428. WriteBuf = Clients[CIndex].c_pSendBuf;
  429. WriteLen = Clients[CIndex].c_reqbuf.SendSize;
  430. }
  431. while (NumWrites--) {
  432. wstatus = WriteNamedPipe(
  433. Clients[CIndex].c_Nmp.c_PipeHandle,
  434. WriteLen,
  435. (PVOID) WriteBuf,
  436. (PULONG) pWriteDone);
  437. if (!NT_SUCCESS(wstatus)) {
  438. //DbgPrint("Nmp: Error in WriteNamedPipe: err:%lx \n", wstatus);
  439. break;
  440. }
  441. }
  442. return wstatus;
  443. }
  444. /************************************************************************/
  445. /*++
  446. This routine does transaction type IO to IPC. This just assumes that
  447. both Number of reads and writes are equal and will use Number of reads
  448. as it's basis.
  449. --*/
  450. NTSTATUS
  451. NMP_XactIO(
  452. IN USHORT CIndex, // client index and namedpipe instance number
  453. IN OUT PULONG pReadDone,
  454. IN OUT PULONG pWriteDone,
  455. IN USHORT SrvCli, // if it's a server or client
  456. IN BOOLEAN FirstIter) // ignore for NamedPipe
  457. {
  458. NTSTATUS xstatus;
  459. ULONG NumReads;
  460. ULONG ReadLen;
  461. PCHAR ReadBuf;
  462. ULONG WriteLen;
  463. PCHAR WriteBuf;
  464. DWORD actReadLen;
  465. NumReads = Clients[CIndex].c_reqbuf.NumRecvs;
  466. if (SrvCli) { // set proper iterations and buffer for Server
  467. ReadBuf = Clients[CIndex].c_pSendBuf;
  468. ReadLen = Clients[CIndex].c_reqbuf.SendSize;
  469. WriteBuf = Clients[CIndex].c_pRecvBuf;
  470. WriteLen = Clients[CIndex].c_reqbuf.RecvSize;
  471. }
  472. else { // for client do proper settings
  473. ReadBuf = Clients[CIndex].c_pRecvBuf;
  474. ReadLen = Clients[CIndex].c_reqbuf.RecvSize;
  475. WriteBuf = Clients[CIndex].c_pSendBuf;
  476. WriteLen = Clients[CIndex].c_reqbuf.SendSize;
  477. }
  478. while (NumReads--) {
  479. xstatus = TransactNamedPipe(Clients[CIndex].c_Nmp.c_PipeHandle, // pipe name
  480. WriteBuf, // write buffer
  481. WriteLen, // write buffer length
  482. ReadBuf, // read buffer
  483. ReadLen, // read buffer length
  484. &actReadLen, // actual read buffer length
  485. NULL); // not overlapped
  486. if (xstatus == FALSE) {
  487. printf("Error: TransactNamedPipe failed - 0x%08x\n", GetLastError());
  488. *pReadDone = 0L;
  489. *pWriteDone = 0L;
  490. break;
  491. }
  492. *pReadDone = ReadLen;
  493. *pWriteDone = WriteLen;
  494. }
  495. return xstatus;
  496. }
  497. /************************************************************************/
  498. NTSTATUS
  499. WriteNamedPipe(
  500. IN HANDLE whandle,
  501. IN ULONG wlength,
  502. IN OUT PVOID wpbuffer,
  503. IN OUT PULONG wpdatalen)
  504. {
  505. NTSTATUS wstatus;
  506. DWORD actWLength;
  507. wstatus = WriteFile(whandle, // pipe handle
  508. wpbuffer, // address of data buffer to write to file
  509. wlength, // length of data buffer
  510. &actWLength,// actual length of data read
  511. NULL); // not overlapped
  512. if (wstatus == TRUE) {
  513. *wpdatalen = actWLength;
  514. }
  515. else {
  516. if (GetLastError() == ERROR_MORE_DATA) {
  517. wstatus = WaitForSingleObjectEx(whandle,
  518. INFINITE,
  519. TRUE);
  520. if (wstatus == TRUE) {
  521. *wpdatalen = actWLength;
  522. if (wlength != *wpdatalen) {
  523. printf("Error: No. of bytes written != buffer length\n");
  524. }
  525. }
  526. }
  527. }
  528. return(wstatus);
  529. }
  530. /************************************************************************/
  531. // this is now a win32 defined function
  532. /*
  533. NTSTATUS DisconnectNamedPipe(IN HANDLE dhandle)
  534. {
  535. NTSTATUS wstatus;
  536. // IO_STATUS_BLOCK ioStatusBlock;
  537. wstatus = NamedPipe_FsControl( // post DisConnect
  538. dhandle,
  539. FSCTL_PIPE_DISCONNECT,
  540. NULL, // input buffer
  541. 0L, // inbuf len
  542. NULL, // output buffer
  543. 0L); // outbuf len
  544. if (!NT_SUCCESS(wstatus)) {
  545. //DbgPrint ("Pipe Disconnect failed, err=%lx\n", wstatus);
  546. }
  547. return(wstatus);
  548. }
  549. */
  550. /************************************************************************/
  551. /*++ This routine creates one instance of NamedPipe for a given client.
  552. A client is identified by its index number.
  553. --*/
  554. NTSTATUS
  555. CreateNamedPipeInstance(
  556. IN USHORT Nindex) // client index and namedpipe instance number
  557. {
  558. NTSTATUS nstatus = 0;
  559. HANDLE NMPhandle;
  560. NMPhandle = CreateNamedPipe(pipeName, // the given pipe name entered by the user
  561. PIPE_ACCESS_DUPLEX, // GENERIC_READ | GENERIC_WRITE
  562. PIPE_READMODE_MESSAGE | // pipe mode (message...)
  563. PIPE_TYPE_MESSAGE |
  564. PIPE_WAIT,
  565. NClients, // max number of instances(clients)
  566. Quotas, // max in buffer length
  567. Quotas, // max out buffer length
  568. 600000, // 60 second default timeout
  569. NULL); // default security attributes
  570. if (NMPhandle == INVALID_HANDLE_VALUE) {
  571. nstatus = GetLastError();
  572. printf ("Failed to Create NamedPipe, err=%lx, %ld\n", nstatus, nstatus);
  573. }
  574. else {
  575. // initialize this client's values
  576. Clients[Nindex].c_Nmp.c_PipeHandle = NMPhandle;
  577. Clients[Nindex].c_client_num = Nindex;//index into the Client array
  578. }
  579. return(nstatus);
  580. }
  581. /************************************************************************/
  582. NTSTATUS
  583. NMP_Cleanup(VOID)
  584. {
  585. return STATUS_SUCCESS;
  586. }
  587. /************************************************************************/
  588. /*++
  589. This routine does a client specific cleanup work.
  590. --*/
  591. NTSTATUS
  592. NMP_ThreadCleanUp(
  593. IN USHORT CIndex)
  594. {
  595. return STATUS_SUCCESS;
  596. }
  597. /************************************************************************/