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.

1167 lines
33 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1994 - 1999
  3. Module Name:
  4. Server.c
  5. Abstract:
  6. Server side of RPC runtime performance test.
  7. Author:
  8. Mario Goertzel (mariogo) 31-Mar-1994
  9. Revision History:
  10. --*/
  11. #include <rpcperf.h>
  12. #include <assert.h>
  13. #include <DataTran.h>
  14. #include <DTCommon.h>
  15. // Usage
  16. const char *USAGE =
  17. "[-i iterations] [-l logfile] [-n Clients] [-n MinThreads]\n"
  18. "\t\t[-c ChunkSize] [-z size] [-d FtpRoot] [-w WwwRoot] [-n case] *\n"
  19. " Clients - default 1\n"
  20. " MinThreads - default 3\n"
  21. " FtpRoot - root directory for ftp\n"
  22. " required for FTP tests\n"
  23. " WwwRoot - root diretory for Http\n"
  24. " required for HTTP tests\n"
  25. " Size - default 50k,100k,200k,400k\n"
  26. " ChunkSize - default 4000,8192,32768\n"
  27. " filename - you may specify a file to transfer (not implemented yet)\n\n"
  28. " Cases, you may specify up to five, default is all:\n"
  29. " 0: Write using RPC\n"
  30. " 1: Read using RPC\n"
  31. " 2: Write using RPC Pipes\n"
  32. " 3: Read using RPC Pipes\n"
  33. " 4: Write using FTP (InternetReadFile)\n"
  34. " 5: Read using FTP (InternetWriteFile)\n"
  35. " 6: Write using HTTP Get\n"
  36. " 7: Read using HTTP Put\n"
  37. " 8: Write using RPC with File I/O\n"
  38. " 9: Read using RPC with File I/O\n"
  39. " 10: Write using RPC Pipes with File I/O\n"
  40. " 11: Read using RPC Pipes with File I/O\n"
  41. " 12: Write using FTP\n"
  42. " 13: Read using FTP\n"
  43. " 14: Write using FTP (InternetReadFile) with File I/O\n"
  44. " 15: Read using FTP (InternetWriteFile) with File I/O\n"
  45. " 16: Write using HTTP Get with File I/O\n"
  46. " 17: Read using HTTP Put\n"
  47. "\n"
  48. " Note: Results are milliseconds/call/client\n"
  49. ;
  50. //
  51. // Globals making it easier.
  52. //
  53. int CurrentChunkIndex;
  54. int CurrentTotalIndex;
  55. int CurrentCase;
  56. char TestCases[TEST_MAX];
  57. char *pFtpRoot = NULL; // Root Directory used for FTP
  58. char *pWwwRoot = NULL; // Root Directory used for HTTP
  59. //
  60. // If this is non-NULL, then use this file instead of creating
  61. // temporary ones. Not implemented...
  62. //
  63. char *pFileName = 0;
  64. long CurrentIter;
  65. unsigned long *Results;
  66. long Clients, ActiveClients, ClientsLeft;
  67. CRITICAL_SECTION CritSec;
  68. HANDLE GoEvent = 0;
  69. HANDLE DoneEvent = 0;
  70. char *TestNames[TEST_MAX] =
  71. {
  72. "S to C RPC : %9ld / %7ld",
  73. "C to S RPC : %9ld / %7ld",
  74. "S to C Pipes : %9ld / %7ld",
  75. "C to S Pipes : %9ld / %7ld",
  76. "S to C FTP1 : %9ld / %7ld",
  77. "C to S FTP1 : %9ld / %7ld",
  78. "S to C HTTP : %9ld / %7ld",
  79. "C to S HTTP : %9ld / %7ld",
  80. "S to C RPC w/File : %9ld / %7ld",
  81. "C to S RPC w/File : %9ld / %7ld",
  82. "S to C Pipes w/File : %9ld / %7ld",
  83. "C to S Pipes w/File : %9ld / %7ld",
  84. "S to C FTP w/File : %9ld / %7ld",
  85. "C to S FTP w/File : %9ld / %7ld",
  86. "S to C FTP1 w/File : %9ld / %7ld",
  87. "C to S FTP1 w/File : %9ld / %7ld",
  88. "S to C HTTP w/File : %9ld / %7ld",
  89. "C to S HTTP w/File : %9ld / %7ld"
  90. };
  91. //
  92. // These arrays are NULL terminated. Don't let the last entry get used!
  93. //
  94. unsigned long ChunkSizes[10] = {4000, 8192, 32*1024L, 0, 0, 0, 0, 0, 0, 0};
  95. unsigned long TotalSizes[10] = {50L*1024L, 100L*1024L, 200L*1024L, 400L*1024L, 0,
  96. 0, 0, 0, 0, 0};
  97. ///////////////////////////////////////////////////////////////////////////////
  98. /*++
  99. FUNCTION: DTParseArgv
  100. DESCRIPTION: Parses arguments
  101. --*/
  102. static void DTParseArgv(int argc, char **argv)
  103. {
  104. int fMissingParm = 0;
  105. char *Name = *argv;
  106. char option;
  107. int options_count;
  108. int totalsize_count = 0;
  109. int chunksize_count = 0;
  110. for(options_count = 0; options_count < 7; options_count++)
  111. Options[options_count] = -1;
  112. options_count = 0;
  113. argc--;
  114. argv++;
  115. while(argc)
  116. {
  117. if (**argv != '/' &&
  118. **argv != '-')
  119. {
  120. printf("Invalid switch: %s\n", *argv);
  121. argc--;
  122. argv++;
  123. }
  124. else
  125. {
  126. option = argv[0][1];
  127. argc--;
  128. argv++;
  129. // Most switches require a second command line arg.
  130. if (argc < 1)
  131. fMissingParm = 1;
  132. switch(option)
  133. {
  134. case 'e':
  135. Endpoint = *argv;
  136. argc--;
  137. argv++;
  138. break;
  139. case 't':
  140. Protseq = *argv;
  141. argc--;
  142. argv++;
  143. break;
  144. case 's':
  145. NetworkAddr = *argv;
  146. argc--;
  147. argv++;
  148. break;
  149. case 'i':
  150. Iterations = atoi(*argv);
  151. argc--;
  152. argv++;
  153. if (Iterations == 0)
  154. Iterations = 10;
  155. break;
  156. case 'm':
  157. MinThreads = atoi(*argv);
  158. argc--;
  159. argv++;
  160. if (MinThreads == 0)
  161. MinThreads = 1;
  162. break;
  163. case 'a':
  164. AuthnLevelStr = *argv;
  165. argc--;
  166. argv++;
  167. break;
  168. case 'n':
  169. if (options_count < 7)
  170. {
  171. Options[options_count] = atoi(*argv);
  172. options_count++;
  173. }
  174. else
  175. printf("Maximum of seven -n switchs, extra ignored.\n");
  176. argc--;
  177. argv++;
  178. break;
  179. case 'l':
  180. LogFileName = *argv;
  181. argc--;
  182. argv++;
  183. break;
  184. #ifdef __RPC_WIN16__
  185. case 'y':
  186. RpcWinSetYieldInfo(0, FALSE, 0, 0);
  187. fMissingParm = 0;
  188. break;
  189. #endif
  190. case 'z':
  191. if (totalsize_count < 9)
  192. {
  193. TotalSizes[totalsize_count++] = atol(*argv);
  194. TotalSizes[totalsize_count] = 0;
  195. }
  196. else printf("Maximum of 9 -z switches, extra ignored.\n");
  197. argc--;
  198. argv++;
  199. break;
  200. case 'c':
  201. if (chunksize_count < 9)
  202. {
  203. ChunkSizes[chunksize_count++] = atoi(*argv);
  204. ChunkSizes[chunksize_count] = 0;
  205. }
  206. else printf("Maximum of 9 -c switches, extra ignored.\n");
  207. argc--;
  208. argv++;
  209. break;
  210. case 'd':
  211. pFtpRoot = *argv;
  212. argc--;
  213. argv++;
  214. break;
  215. case 'w':
  216. pWwwRoot = *argv;
  217. argc--;
  218. argv++;
  219. break;
  220. default:
  221. fMissingParm = 0;
  222. printf("Usage: %s: %s\n", Name, USAGE);
  223. exit(0);
  224. break;
  225. }
  226. if (fMissingParm)
  227. {
  228. printf("Invalid switch %s, missing required parameter\n", *argv);
  229. }
  230. }
  231. } // while argc
  232. // determine the security level
  233. if (strcmp("none", AuthnLevelStr) == 0)
  234. AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
  235. else if (strcmp("connect", AuthnLevelStr) == 0)
  236. AuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT;
  237. else if (strcmp("call", AuthnLevelStr) == 0)
  238. AuthnLevel = RPC_C_AUTHN_LEVEL_CALL;
  239. else if (strcmp("pkt", AuthnLevelStr) == 0)
  240. AuthnLevel = RPC_C_AUTHN_LEVEL_PKT;
  241. else if (strcmp("integrity", AuthnLevelStr) == 0)
  242. AuthnLevel = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
  243. else if (strcmp("privacy", AuthnLevelStr) == 0)
  244. AuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
  245. else
  246. {
  247. printf("%s is NOT a valid authentication level, default is NONE\n", AuthnLevelStr);
  248. }
  249. #if 0
  250. printf("Config: %s:%s[%s]\n"
  251. "Iterations: %d\n"
  252. "Server threads %d\n"
  253. "Options: %d %d %d\n",
  254. Protseq, NetworkAddr, Endpoint, Iterations, MinThreads,
  255. Options[0], Options[1], Options[2]);
  256. #endif
  257. #ifdef WIN32
  258. printf("Process ID: %d\n", GetCurrentProcessId());
  259. #else
  260. #endif
  261. return;
  262. }
  263. /////////////////////////////////////////////////////////////////////
  264. // Figure out what we're testing and start listening.
  265. //
  266. int __cdecl
  267. main (int argc, char **argv)
  268. {
  269. unsigned int MinThreads;
  270. unsigned long i, status;
  271. RPC_BINDING_VECTOR *pBindingVector;
  272. DTParseArgv(argc, argv);
  273. MinThreads = 3;
  274. ClientsLeft = Clients = 1;
  275. ActiveClients = 0;
  276. Iterations = 1;
  277. if (Options[0] > 0) ClientsLeft = Clients = Options[0]; // Clients
  278. Results = MIDL_user_allocate(4 * Clients);
  279. if (Options[1] > 0) MinThreads = Options[1]; // MinThreads
  280. if (Options[2] < 0)
  281. {
  282. memset(TestCases, 1, TEST_MAX); // Default: Run all tests
  283. //
  284. // HTTP PUT doesn't work. Don't do these tests by default.
  285. //
  286. TestCases[RECV_BUFFER_HTTP] = 0;
  287. TestCases[RECV_FILE_HTTP] = 0;
  288. //
  289. // Don't do internet tests if the
  290. // -d or the -w switches aren't set appropriately
  291. //
  292. if (NULL == pFtpRoot)
  293. {
  294. TestCases[SEND_BUFFER_FTP1] = 0;
  295. TestCases[RECV_BUFFER_FTP1] = 0;
  296. TestCases[SEND_FILE_FTP] = 0;
  297. TestCases[RECV_FILE_FTP] = 0;
  298. TestCases[SEND_FILE_FTP1] = 0;
  299. TestCases[RECV_FILE_FTP1] = 0;
  300. }
  301. if (NULL == pWwwRoot)
  302. {
  303. TestCases[SEND_BUFFER_HTTP] = 0;
  304. TestCases[RECV_BUFFER_HTTP] = 0;
  305. TestCases[SEND_FILE_HTTP] = 0;
  306. TestCases[RECV_FILE_HTTP] = 0;
  307. }
  308. }
  309. else // else run specified tests
  310. {
  311. memset(TestCases, 0, TEST_MAX);
  312. for(i = 2; i < 7; i++)
  313. {
  314. if ( (Options[i] < 0) || (Options[i] >= TEST_MAX) ) break;
  315. TestCases[Options[i]] = 1;
  316. }
  317. }
  318. //
  319. // See make sure that there are tests to run
  320. // and set CurrentCase to the first one.
  321. //
  322. CurrentCase = 0;
  323. for(i = 0; i < TEST_MAX; i++)
  324. {
  325. if (TestCases[i])
  326. {
  327. CurrentCase = i;
  328. break;
  329. }
  330. }
  331. if ( (pFileName == 0) && (i == TEST_MAX))
  332. {
  333. printf("No test cases selected!\n");
  334. return 1;
  335. }
  336. if (ChunkSizes[0] == 0)
  337. {
  338. printf("Chunk Size must be non-zero.\n");
  339. return 1;
  340. }
  341. if ( (pFileName == 0) && (TotalSizes[0] == 0))
  342. {
  343. printf("Total Size must be non-zero.\n");
  344. return 1;
  345. }
  346. CurrentIter = Iterations;
  347. if (CurrentIter == 0) CurrentIter = 1;
  348. CurrentChunkIndex = 0;
  349. CurrentTotalIndex = 0;
  350. InitializeCriticalSection(&CritSec);
  351. GoEvent = CreateEvent(0,
  352. TRUE,
  353. FALSE,
  354. 0);
  355. DoneEvent = CreateEvent(0,
  356. TRUE,
  357. FALSE,
  358. 0);
  359. //
  360. // Actually start the server
  361. //
  362. printf("FTP Directory: %s\n", (0 == pFtpRoot ? "<NONE>": pFtpRoot));
  363. printf("WWW Directory: %s\n", (0 == pWwwRoot ? "<NONE>": pWwwRoot));
  364. if (Endpoint)
  365. {
  366. status = RpcServerUseProtseqEp(Protseq, 100, Endpoint, 0);
  367. CHECK_STATUS(status, "RpcServerUseProtseqEp");
  368. }
  369. else
  370. {
  371. char *string_binding;
  372. status = RpcServerUseProtseq(Protseq, 100, 0);
  373. CHECK_STATUS(status, "RpcServerUseProtseqEp");
  374. status = RpcServerInqBindings(&pBindingVector);
  375. CHECK_STATUS(status, "RpcServerInqBindings");
  376. status = RpcEpRegister(DataTranPerf_v1_0_s_ifspec,
  377. pBindingVector,
  378. 0,
  379. 0);
  380. CHECK_STATUS(status, "RpcEpRegister");
  381. status = RpcBindingToStringBinding(pBindingVector->BindingH[0],
  382. &string_binding);
  383. CHECK_STATUS(status, "RpcBindingToStringBinding");
  384. status = RpcStringBindingParse(string_binding,
  385. 0, 0, 0, &Endpoint, 0);
  386. CHECK_STATUS(status, "RpcStringBindingParse");
  387. printf("Listening to %s:[%s]\n\n", Protseq, Endpoint);
  388. }
  389. status = RpcServerRegisterIf(DataTranPerf_v1_0_s_ifspec,0,0);
  390. CHECK_STATUS(status, "RpcServerRegisterIf");
  391. status = RpcServerRegisterAuthInfo(NULL,
  392. RPC_C_AUTHN_WINNT,
  393. NULL,
  394. NULL);
  395. CHECK_STATUS(status, "RpcServerRegisterAuthInfo");
  396. printf("Base Iterations: %d, Clients %d, MinThreads %d\n",
  397. Iterations,
  398. Clients,
  399. MinThreads);
  400. printf("Server listening\n");
  401. status = RpcServerListen(MinThreads, 100, 0);
  402. CHECK_STATUS(status, "RpcServerListen");
  403. printf("This doesn't stop listening..hmm\n");
  404. }
  405. /********************************************************************
  406. * Control APIs that the client(s) call to sync on test cases, iterations
  407. * and to report results.
  408. ********************************************************************/
  409. error_status_t
  410. BeginTest(handle_t b,
  411. long *ClientId)
  412. {
  413. long status = 0;
  414. EnterCriticalSection(&CritSec);
  415. if (ActiveClients < Clients)
  416. {
  417. ActiveClients++;
  418. *ClientId = ActiveClients;
  419. }
  420. else
  421. {
  422. status = PERF_TOO_MANY_CLIENTS;
  423. }
  424. LeaveCriticalSection(&CritSec);
  425. return status;
  426. }
  427. //---------------------------------------------------------
  428. error_status_t
  429. NextTest(handle_t b,
  430. TEST_TYPE *Test,
  431. long *Iters,
  432. long *Length,
  433. long *ChunkSize)
  434. {
  435. long wait = 1;
  436. long done = 0;
  437. int i;
  438. EnterCriticalSection(&CritSec);
  439. *Test = CurrentCase;
  440. *Iters = CurrentIter;
  441. *ChunkSize = ChunkSizes[CurrentChunkIndex];
  442. *Length = TotalSizes[CurrentTotalIndex];
  443. ClientsLeft--;
  444. if (CurrentCase == TEST_MAX)
  445. {
  446. done = 1;
  447. }
  448. if (ClientsLeft == 0)
  449. {
  450. //
  451. // Let all the waiting clients go
  452. //
  453. wait = 0;
  454. ResetEvent(DoneEvent);
  455. SetEvent(GoEvent);
  456. }
  457. LeaveCriticalSection(&CritSec);
  458. if (wait)
  459. {
  460. WaitForSingleObject(GoEvent, INFINITE);
  461. }
  462. if (done)
  463. {
  464. if (ClientsLeft == 0)
  465. {
  466. // I'm the last client, sleep and then reset for
  467. // a new set of clients. Sleep avoids a race (usually).
  468. Sleep(1000);
  469. //
  470. // Reset CurrentCase
  471. //
  472. for(i = 0; i < TEST_MAX; i++)
  473. {
  474. if (TestCases[i])
  475. {
  476. CurrentCase = i;
  477. break;
  478. }
  479. }
  480. CurrentIter = Iterations;
  481. if (CurrentIter == 0) CurrentIter = 1;
  482. ActiveClients = 0;
  483. ClientsLeft = Clients;
  484. ResetEvent(GoEvent);
  485. ResetEvent(DoneEvent);
  486. }
  487. return PERF_TESTS_DONE;
  488. }
  489. return 0;
  490. }
  491. //---------------------------------------------------------
  492. error_status_t
  493. EndTest(handle_t b,
  494. unsigned long mseconds)
  495. {
  496. long status, i;
  497. long wait = 1;
  498. char szTempString[80];
  499. EnterCriticalSection(&CritSec);
  500. Results[ClientsLeft] = mseconds;
  501. ClientsLeft++;
  502. if (ClientsLeft == Clients)
  503. {
  504. // All clients have finished
  505. // Report results
  506. if (pFileName == 0)
  507. {
  508. sprintf(szTempString,
  509. TestNames[CurrentCase],
  510. TotalSizes[CurrentTotalIndex],
  511. ChunkSizes[CurrentChunkIndex]),
  512. printf("| % 3d | %-40s | % 4d |",
  513. CurrentCase,
  514. szTempString,
  515. CurrentIter
  516. );
  517. }
  518. else
  519. {
  520. printf("Liar! The filename option ain't implemented yet");
  521. exit(0);
  522. }
  523. for(i = 0; i < Clients; i++)
  524. printf(" % 7d.%03d |",
  525. Results[i] / CurrentIter,
  526. Results[i] % CurrentIter * 1000 / CurrentIter
  527. );
  528. printf("\n");
  529. //
  530. // Find next case...
  531. //
  532. for(i = CurrentCase + 1; i < TEST_MAX; i++)
  533. if (TestCases[i])
  534. {
  535. CurrentCase = i;
  536. break;
  537. }
  538. if (i == TEST_MAX)
  539. {
  540. if (ChunkSizes[++CurrentChunkIndex] == 0)
  541. {
  542. CurrentChunkIndex = 0;
  543. if (TotalSizes[++CurrentTotalIndex] == 0)
  544. {
  545. //
  546. // This tells NextTest that we're done.
  547. //
  548. CurrentCase = TEST_MAX;
  549. printf("TEST DONE\n");
  550. }
  551. }
  552. if (TEST_MAX != CurrentCase)
  553. {
  554. int i;
  555. //
  556. // Go back to the first case.
  557. //
  558. for(i = 0; i < TEST_MAX; i++)
  559. {
  560. if (TestCases[i])
  561. {
  562. CurrentCase = i;
  563. break;
  564. }
  565. }
  566. }
  567. }
  568. CurrentIter = Iterations;
  569. if (CurrentIter == 0) CurrentIter = 1;
  570. //
  571. // We're setup for the next test (or to finish) let the clients go.
  572. //
  573. wait = 0;
  574. ResetEvent(GoEvent);
  575. SetEvent(DoneEvent);
  576. }
  577. LeaveCriticalSection(&CritSec);
  578. if (wait)
  579. WaitForSingleObject(DoneEvent, INFINITE);
  580. return 0;
  581. }
  582. //---------------------------------------------------------
  583. //
  584. // For fixed endpoint and re-bind test case
  585. //
  586. unsigned char *GetFixedEp(handle_t h)
  587. {
  588. char *r;
  589. r = malloc(strlen(Endpoint) + 1);
  590. strcpy(r, Endpoint);
  591. return (unsigned char *)r;
  592. }
  593. void GetServerName (handle_t b,
  594. unsigned long int BufferSize,
  595. unsigned char *szServer)
  596. {
  597. if (FALSE == GetComputerName (szServer, &BufferSize))
  598. {
  599. *szServer = 0;
  600. }
  601. }
  602. //===================================================================
  603. // File Context Stuff
  604. //===================================================================
  605. typedef struct
  606. {
  607. HANDLE hFile;
  608. TCHAR FileName[MAX_PATH];
  609. } DT_S_FILE_HANDLE;
  610. //---------------------------------------------------------
  611. DT_FILE_HANDLE RemoteOpen (handle_t b, unsigned long ulLength)
  612. /*++
  613. FUNCTION: RemoteOpen
  614. DESCRIPTION: Opens a temporary file and return a handle to client
  615. --*/
  616. {
  617. DT_S_FILE_HANDLE *pFileContext = NULL;
  618. pFileContext = (DT_S_FILE_HANDLE *)MIDL_user_allocate(sizeof(DT_S_FILE_HANDLE));
  619. if (pFileContext == NULL)
  620. {
  621. printf("RemoteOpen: Out of memory!\n");
  622. return (DT_FILE_HANDLE) NULL;
  623. }
  624. //
  625. // If Length is zero, the file is opened for receive from the client.
  626. // So we use the prefix FSR (Server Receive); otherwise we use FSS.
  627. //
  628. CreateTempFile (NULL,
  629. (0 == ulLength ? TEXT("FSR") : TEXT("FSS")),
  630. ulLength,
  631. (LPTSTR) pFileContext->FileName);
  632. pFileContext->hFile = CreateFile ((LPTSTR) pFileContext->FileName,
  633. (ulLength == 0 ? GENERIC_WRITE : GENERIC_READ),
  634. 0,
  635. (LPSECURITY_ATTRIBUTES) NULL,
  636. OPEN_EXISTING,
  637. FILE_ATTRIBUTE_NORMAL,
  638. (HANDLE) NULL);
  639. if (pFileContext->hFile == INVALID_HANDLE_VALUE)
  640. {
  641. printf("RemoteOpen: Cannot create temp file!\n");
  642. MIDL_user_free (pFileContext);
  643. return (DT_FILE_HANDLE) NULL;
  644. }
  645. return ((DT_FILE_HANDLE) pFileContext);
  646. }
  647. //---------------------------------------------------------
  648. DT_FILE_HANDLE RemoteCreateFtpFile (handle_t Binding,
  649. boolean f_StoC,
  650. unsigned long ulLength,
  651. unsigned long ulBufferSize,
  652. unsigned char *szRemotePath)
  653. {
  654. DT_S_FILE_HANDLE *pFileContext = NULL;
  655. unsigned long iTheFileName;
  656. //
  657. // Is the FTP Root directory specified?
  658. //
  659. if (NULL == pFtpRoot)
  660. {
  661. printf("RemoteCreateFtpFile: FTP Root Path not set.\n");
  662. return (DT_FILE_HANDLE) NULL;
  663. }
  664. //
  665. // Allocate memory for the context handle
  666. //
  667. pFileContext = (DT_S_FILE_HANDLE *)MIDL_user_allocate(sizeof(DT_S_FILE_HANDLE));
  668. if (pFileContext == NULL)
  669. {
  670. printf("RemoteCreateFtpFile: Out of memory!\n");
  671. return (DT_FILE_HANDLE) NULL;
  672. }
  673. //
  674. // This file is dealt with by the FTP server, so we don't need a handle to it.
  675. // However, we need the file name so we can delete it later.
  676. //
  677. pFileContext->hFile = INVALID_HANDLE_VALUE;
  678. //
  679. // Create a temp file to be sent to the client
  680. //
  681. if (FALSE == CreateTempFile (pFtpRoot,
  682. (TRUE == f_StoC ? TEXT("FSS") : TEXT("FSR")),
  683. (TRUE == f_StoC ? ulLength : 0),
  684. pFileContext->FileName))
  685. {
  686. MIDL_user_free (pFileContext);
  687. return (DT_FILE_HANDLE) NULL;
  688. }
  689. //
  690. // We want to tell the client the actual filename only - no path.
  691. //
  692. for (iTheFileName = lstrlen (pFileContext->FileName)-1;
  693. iTheFileName>=0;
  694. iTheFileName--)
  695. {
  696. if (pFileContext->FileName[iTheFileName] == (TCHAR)'\\')
  697. {
  698. break;
  699. }
  700. }
  701. if ((ulBufferSize + iTheFileName ) < (unsigned long)lstrlen (pFileContext->FileName))
  702. {
  703. printf("RemoteCreateFtpFile: Buffer Size too small to hold path.\n");
  704. MIDL_user_free (pFileContext);
  705. return ((DT_FILE_HANDLE) NULL);
  706. }
  707. lstrcpy (szRemotePath, &(pFileContext->FileName[iTheFileName]));
  708. return ((DT_FILE_HANDLE) pFileContext);
  709. }
  710. //---------------------------------------------------------
  711. DT_FILE_HANDLE RemoteCreateHttpFile (handle_t Binding,
  712. boolean f_StoC,
  713. unsigned long ulLength,
  714. unsigned long ulBufferSize,
  715. unsigned char *szRemotePath)
  716. {
  717. DT_S_FILE_HANDLE *pFileContext = NULL;
  718. unsigned long iTheFileName;
  719. //
  720. // Is the FTP Root directory specified?
  721. //
  722. if (NULL == pWwwRoot)
  723. {
  724. printf("RemoteCreateHttpFile: WWW Root Path not set.\n");
  725. return (DT_FILE_HANDLE) NULL;
  726. }
  727. //
  728. // Allocate memory for the context handle
  729. //
  730. pFileContext = (DT_S_FILE_HANDLE *)MIDL_user_allocate(sizeof(DT_S_FILE_HANDLE));
  731. if (pFileContext == NULL)
  732. {
  733. printf("RemoteCreateHttpFile: Out of memory!\n");
  734. return (DT_FILE_HANDLE) NULL;
  735. }
  736. //
  737. // This file is dealt with by the HTTP server, so we don't need a handle to it.
  738. // However, we need the file name so we can delete it later.
  739. //
  740. pFileContext->hFile = INVALID_HANDLE_VALUE;
  741. //
  742. // Create a temp file to be sent to the client
  743. //
  744. if (FALSE == CreateTempFile (pWwwRoot,
  745. (TRUE == f_StoC ? TEXT("FSS") : TEXT("FSR")),
  746. (TRUE == f_StoC ? ulLength : 0),
  747. pFileContext->FileName))
  748. {
  749. MIDL_user_free (pFileContext);
  750. return (DT_FILE_HANDLE) NULL;
  751. }
  752. //
  753. // We want to tell the client the actual filename only - no path.
  754. //
  755. for (iTheFileName = lstrlen (pFileContext->FileName)-1;
  756. iTheFileName>=0;
  757. iTheFileName--)
  758. {
  759. if (pFileContext->FileName[iTheFileName] == (TCHAR)'\\')
  760. {
  761. break;
  762. }
  763. }
  764. if ((ulBufferSize + iTheFileName ) < (unsigned long)lstrlen (pFileContext->FileName))
  765. {
  766. printf("RemoteCreateHttpFile: Buffer Size too small to hold path.\n");
  767. MIDL_user_free (pFileContext);
  768. return ((DT_FILE_HANDLE) NULL);
  769. }
  770. lstrcpy (szRemotePath, &(pFileContext->FileName[iTheFileName]));
  771. if ((TCHAR)'\\' == szRemotePath[0])
  772. {
  773. szRemotePath[0] = (TCHAR)'/';
  774. }
  775. return ((DT_FILE_HANDLE) pFileContext);
  776. }
  777. //---------------------------------------------------------
  778. void RemoteResetFile (DT_FILE_HANDLE phContext)
  779. {
  780. assert (NULL != phContext);
  781. if (INVALID_HANDLE_VALUE != ((DT_S_FILE_HANDLE *)phContext)->hFile)
  782. {
  783. SetFilePointer (((DT_S_FILE_HANDLE *)phContext)->hFile,
  784. 0,
  785. NULL,
  786. FILE_BEGIN);
  787. }
  788. }
  789. //---------------------------------------------------------
  790. void __RPC_USER DT_FILE_HANDLE_rundown(DT_FILE_HANDLE phContext)
  791. {
  792. if (phContext)
  793. {
  794. if (((DT_S_FILE_HANDLE *)phContext)->hFile != INVALID_HANDLE_VALUE)
  795. CloseHandle(((DT_S_FILE_HANDLE *)phContext)->hFile);
  796. MIDL_user_free (phContext);
  797. }
  798. }
  799. //---------------------------------------------------------
  800. void RemoteClose (DT_FILE_HANDLE *pp, boolean fDelete)
  801. {
  802. assert ( (NULL != *pp) &&
  803. (NULL != **(DT_S_FILE_HANDLE **)pp)
  804. );
  805. if (INVALID_HANDLE_VALUE != (*(DT_S_FILE_HANDLE **)pp)->hFile)
  806. {
  807. CloseHandle((*(DT_S_FILE_HANDLE **)pp)->hFile);
  808. }
  809. if (TRUE == fDelete)
  810. {
  811. DeleteFile((*(DT_S_FILE_HANDLE **)pp)->FileName);
  812. }
  813. MIDL_user_free(*pp);
  814. *pp = NULL;
  815. }
  816. //===================================================================
  817. // Memory Handle stuff
  818. // - Each thread that uses the pipes tests will need a buffer
  819. // to push or pull data. This is achieved through this memory
  820. // context handle.
  821. //===================================================================
  822. typedef struct
  823. {
  824. unsigned char __RPC_FAR *pPtr;
  825. unsigned long ulLength;
  826. } DT_S_MEM_HANDLE;
  827. //---------------------------------------------------------
  828. DT_MEM_HANDLE RemoteAllocate (handle_t h, unsigned long ulLength)
  829. {
  830. DT_S_MEM_HANDLE *pMemContext = NULL;
  831. pMemContext = (DT_S_MEM_HANDLE *)MIDL_user_allocate(sizeof(DT_S_MEM_HANDLE));
  832. if (pMemContext == NULL)
  833. {
  834. printf("RemoteAllocate: Out of memory!\n");
  835. return (DT_FILE_HANDLE) NULL;
  836. }
  837. pMemContext->pPtr = (unsigned char __RPC_FAR *)MIDL_user_allocate(ulLength);
  838. if (pMemContext->pPtr == NULL)
  839. {
  840. printf("RemoteAllocate: Out of memory!\n");
  841. MIDL_user_free (pMemContext);
  842. return (DT_FILE_HANDLE) NULL;
  843. }
  844. pMemContext->ulLength = ulLength;
  845. return (DT_MEM_HANDLE) pMemContext;
  846. }
  847. //---------------------------------------------------------
  848. void __RPC_USER DT_MEM_HANDLE_rundown(DT_MEM_HANDLE phContext)
  849. {
  850. printf("DT_MEM_HANDLE_rundown Entered\n");
  851. if (phContext)
  852. {
  853. if (((DT_S_MEM_HANDLE *)phContext)->pPtr != NULL)
  854. MIDL_user_free(((DT_S_MEM_HANDLE *)phContext)->pPtr);
  855. MIDL_user_free (phContext);
  856. }
  857. printf("DT_MEM_HANDLE_rundown Exited\n");
  858. }
  859. //---------------------------------------------------------
  860. void RemoteFree (DT_MEM_HANDLE *pMemContext)
  861. {
  862. assert( ((*(DT_S_MEM_HANDLE **)pMemContext) != NULL) &&
  863. ((*(DT_S_MEM_HANDLE **)pMemContext)->pPtr != NULL)
  864. );
  865. //
  866. // Free the block of memory
  867. //
  868. MIDL_user_free ((*(DT_S_MEM_HANDLE **)pMemContext)->pPtr);
  869. (*(DT_S_MEM_HANDLE **)pMemContext)->pPtr = NULL;
  870. //
  871. // Then free the handle itself!
  872. //
  873. MIDL_user_free (*pMemContext);
  874. *pMemContext = (DT_MEM_HANDLE) NULL;
  875. }
  876. //===================================================================
  877. // Regular RPCs
  878. //===================================================================
  879. void C_to_S_Buffer (handle_t h, unsigned long int BufferSize, byte Buffer[])
  880. {
  881. return;
  882. }
  883. //---------------------------------------------------------
  884. void S_to_C_Buffer (handle_t h, unsigned long int BufferSize, byte Buffer[])
  885. {
  886. return;
  887. }
  888. //---------------------------------------------------------
  889. void C_to_S_BufferWithFile (handle_t h,
  890. DT_FILE_HANDLE pContext,
  891. unsigned long int BufferSize,
  892. byte Buffer[])
  893. {
  894. long dwBytesWritten;
  895. WriteFile(((DT_S_FILE_HANDLE *)pContext)->hFile,
  896. Buffer,
  897. BufferSize,
  898. &dwBytesWritten,
  899. NULL);
  900. }
  901. //---------------------------------------------------------
  902. long S_to_C_BufferWithFile (handle_t h,
  903. DT_FILE_HANDLE pContext,
  904. unsigned long int BufferSize,
  905. byte Buffer[])
  906. {
  907. unsigned long dwBytesRead;
  908. ReadFile(((DT_S_FILE_HANDLE *)pContext)->hFile,
  909. Buffer,
  910. BufferSize,
  911. &dwBytesRead,
  912. NULL);
  913. return dwBytesRead;
  914. }
  915. //===================================================================
  916. // RPC Pipes
  917. //===================================================================
  918. void S_to_C_Pipe(handle_t h,
  919. UCHAR_PIPE ThePipe,
  920. unsigned long ulLength,
  921. DT_MEM_HANDLE pMemHandle)
  922. {
  923. unsigned long dwBytesSent;
  924. while (ulLength >= ((DT_S_MEM_HANDLE *)pMemHandle)->ulLength)
  925. {
  926. (ThePipe.push) (ThePipe.state,
  927. ((DT_S_MEM_HANDLE *)pMemHandle)->pPtr,
  928. ((DT_S_MEM_HANDLE *)pMemHandle)->ulLength);
  929. ulLength -= ((DT_S_MEM_HANDLE *)pMemHandle)->ulLength;
  930. }
  931. if (ulLength != 0)
  932. {
  933. (ThePipe.push) (ThePipe.state,
  934. ((DT_S_MEM_HANDLE *)pMemHandle)->pPtr,
  935. ulLength);
  936. }
  937. (ThePipe.push) (ThePipe.state,
  938. ((DT_S_MEM_HANDLE *)pMemHandle)->pPtr,
  939. 0);
  940. }
  941. //---------------------------------------------------------
  942. void C_to_S_Pipe (handle_t h,
  943. UCHAR_PIPE ThePipe,
  944. DT_MEM_HANDLE pMemHandle)
  945. {
  946. unsigned long nBytesReceived;
  947. for(;;)
  948. {
  949. (ThePipe.pull) (ThePipe.state,
  950. ((DT_S_MEM_HANDLE *)pMemHandle)->pPtr,
  951. ((DT_S_MEM_HANDLE *)pMemHandle)->ulLength,
  952. &nBytesReceived);
  953. if (nBytesReceived == 0) break;
  954. }
  955. }
  956. //---------------------------------------------------------
  957. void S_to_C_PipeWithFile (handle_t h,
  958. UCHAR_PIPE ThePipe,
  959. DT_FILE_HANDLE pContext,
  960. DT_MEM_HANDLE pMemHandle)
  961. {
  962. unsigned long dwBytesRead;
  963. for(;;)
  964. {
  965. ReadFile(((DT_S_FILE_HANDLE *)pContext)->hFile,
  966. ((DT_S_MEM_HANDLE *)pMemHandle)->pPtr,
  967. ((DT_S_MEM_HANDLE *)pMemHandle)->ulLength,
  968. &dwBytesRead,
  969. NULL);
  970. (ThePipe.push) (ThePipe.state,
  971. ((DT_S_MEM_HANDLE *)pMemHandle)->pPtr,
  972. dwBytesRead);
  973. if (dwBytesRead == 0) break;
  974. }
  975. }
  976. //---------------------------------------------------------
  977. void C_to_S_PipeWithFile (handle_t h,
  978. UCHAR_PIPE ThePipe,
  979. DT_FILE_HANDLE pContext,
  980. DT_MEM_HANDLE pMemHandle)
  981. {
  982. unsigned long nBytesReceived;
  983. unsigned long dwBytesWritten;
  984. for(;;)
  985. {
  986. (ThePipe.pull) (ThePipe.state,
  987. ((DT_S_MEM_HANDLE *)pMemHandle)->pPtr,
  988. ((DT_S_MEM_HANDLE *)pMemHandle)->ulLength,
  989. &nBytesReceived);
  990. if (nBytesReceived == 0) break;
  991. WriteFile(((DT_S_FILE_HANDLE *)pContext)->hFile,
  992. ((DT_S_MEM_HANDLE *)pMemHandle)->pPtr,
  993. nBytesReceived,
  994. &dwBytesWritten,
  995. NULL);
  996. }
  997. }