home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / rpc / pipes / pipec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-23  |  13.1 KB  |  353 lines

  1. /*************************************************************************
  2.                     Copyright Microsoft Corp. 1992-1996
  3.                         Remote Machine pipe sample
  4.   
  5.     FILE        :   pipec.c
  6.  
  7.     USAGE       :   client  <local file> <new file> [options]
  8.                         -s Scramble file
  9.                         -u Unscramble the file
  10.                         -n network_address
  11.                         -p protocol_sequence
  12.                         -e endpoint
  13.                         -o options
  14.  
  15.     PURPOSE     :   Client side of the RPC distributed application pipes.
  16.   
  17.     COMMENTS    :   This program shows the client side an application that
  18.                     transfers a file from the client to the server, using 
  19.                     pipes. When the file is received at the server it 
  20.                     "encodes" the data by incrementing all the characters, 
  21.                     and sends the "encoded" file back to the client.
  22.  
  23.                     Since this program uses the implicit binding method, 
  24.                     some of the binding handling must be done at the client 
  25.                     side
  26. *************************************************************************/
  27. #include "pipe.h"                   // Generated by the MIDL compiler
  28. #include "common.h"                 // Common definitions 
  29.  
  30. #define CLIENT_BUFFER_SIZE  500     // Can send or recieve 500 elements 
  31.  
  32. // Client side global variables
  33. pipe_state  in_out_pipe_state;      // Pipe state on the client side
  34. _TUCHAR     pcClientBuffer[CLIENT_BUFFER_SIZE];  // Buffer used in PipeAlloc
  35.  
  36.  
  37. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  38. /*  Procedure   :   void Usage(_TUCHAR *)                               */
  39. /*  Desc        :   This procedure prints out an error message if the   */
  40. /*                  command line arguments are wrong                    */
  41. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  42. void Usage(_TUCHAR * pszProgramName)
  43. {
  44.     _tprintf(TEXT("USAGE : %s <local_file> <new_file> [-option]\n"), 
  45.         pszProgramName);
  46.     _tprintf(TEXT("Options : -s\tTo encode the file\n"));
  47.     _tprintf(TEXT("          -u\tTo Decode the file\n"));
  48.     _tprintf(TEXT("          -n\t<Network Address>\n"));
  49.     _tprintf(TEXT("          -p\t<Protocol Sequence>\n"));  
  50.     _tprintf(TEXT("          -e\t<Endpoint>\n"));  
  51.     _tprintf(TEXT("          -o\t<Options>\n"));  
  52.     exit(EXECUTION_FAILED);
  53. }
  54.  
  55.  
  56. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  57. /*  Procedure   :   PipeAlloc                                           */
  58. /*  Desc        :   This procedure allocates a chunck of memory and     */
  59. /*                  returns a pointer to it.                            */
  60. /*                  In this sample the Alloc routine returns a pointer  */
  61. /*                  to the same global allocated memory every time.     */
  62. /*                  This can be done since after each Pull/Push, data   */
  63. /*                  is read/written to file.                            */
  64. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  65. void PipeAlloc(
  66.     char            *pcStateInfo,       // The state structure
  67.     unsigned long   nReqSize,           // Req. size of buffer in bytes
  68.     _TUCHAR         **pcAllocatedBuffer,// Pointer to the allocated buffer
  69.     unsigned long   *pnAllocatedSize)   // Size of allocated buf. in bytes
  70. {
  71.     // Since the memory is already allocated, just return a pointer to it
  72.     if(nReqSize > (CLIENT_BUFFER_SIZE * sizeof(_TUCHAR)))
  73.     {
  74.         *pnAllocatedSize = CLIENT_BUFFER_SIZE * sizeof(_TUCHAR);
  75.     }
  76.     else
  77.     {
  78.         *pnAllocatedSize = nReqSize;
  79.     }
  80.     *pcAllocatedBuffer = pcClientBuffer;
  81. }
  82.  
  83.  
  84. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  85. /*  Procedure   :   PipePull                                            */
  86. /*  Desc        :   This procedure is called by the stub when its ready */
  87. /*                  to send a chunck of the pipe to the server.         */
  88. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  89. void PipePull(
  90.     char            *pcStateInfo,   // The state struct on client side
  91.     _TUCHAR         *pcBuffer,      // Pointer to the buffer 
  92.     unsigned long   nMaxBufferSize, // Size of buffer in elements
  93.     unsigned long   *pnSizeToSend)  // Number of elements put in buffer
  94. {
  95.     // Declare a state variable 
  96.     pipe_state    *psState = (pipe_state *) pcStateInfo;
  97.  
  98.     // Open the local file, if it is not already opened 
  99.     if(psState->hOld == NULL)
  100.     {
  101.         if(NULL == (psState->hOld = 
  102.             _tfopen(psState->pszOldName, TEXT("rt"))))
  103.         {
  104.             _tprintf(TEXT("Could not open the file %s\n"),
  105.                 psState->pszOldName);
  106.             exit(EXECUTION_FAILED);
  107.         }
  108.     }
  109.  
  110.     // Read max_buffer_size into the buffer
  111.     *pnSizeToSend = fread(
  112.         pcBuffer, 
  113.         sizeof(_TUCHAR), 
  114.         nMaxBufferSize,
  115.         psState->hOld);
  116.  
  117.     if(*pnSizeToSend == 0)      // When end of the data is reached    
  118.     {                           // cleanup the application
  119.         fclose(psState->hOld);
  120.         psState->hOld = NULL;
  121.     }
  122. }
  123.  
  124.  
  125. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  126. /*  Procedure   :   PipePush                                            */
  127. /*  Desc        :   This procedure is called by the stub when a chunck  */
  128. /*                  of data is received from the server.                */
  129. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  130. void PipePush(
  131.     char            *nStateInfo,        // State structure on client side
  132.     _TUCHAR         *pcBuffer,          // Ptr to the buffer with the data
  133.     unsigned long   nNumberOfElements)  // Number of elements in the buffer
  134. {
  135.     // Declare a state variable 
  136.     pipe_state    *psState = (pipe_state *) nStateInfo;
  137.  
  138.     // Open the New file, if it is not already opened 
  139.     if(psState->hNew == NULL)
  140.     {
  141.         if(NULL == (psState->hNew = 
  142.             _tfopen(psState->pszNewName, TEXT("w"))))
  143.         {
  144.             _tprintf( TEXT("Unable to create the file %s\n"), 
  145.                     psState->pszNewName);
  146.             exit(EXECUTION_FAILED);
  147.         }
  148.     }
  149.  
  150.  
  151.     // When number of elements received is 0, this is the end of the pipe
  152.     if(nNumberOfElements == 0)
  153.     {
  154.         // Clean up by closing the opened file 
  155.         fclose (psState->hNew);
  156.         psState->hNew = NULL;
  157.     }
  158.     else
  159.     {
  160.         // Write the buffer to the file 
  161.         fwrite(pcBuffer, sizeof(_TUCHAR), nNumberOfElements, psState->hNew);
  162.     }
  163. }
  164.  
  165.  
  166. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  167. /*  Client side main program                                            */
  168. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  169. int _CRTAPI1 main(int argc, char *argv[])
  170. {
  171.     RPC_STATUS      nStatus;        // Status returned from RPC-calls
  172.     CHAR_PIPE_TYPE  in_out_pipe;    // Pipe structure used for the pipe
  173.     TCHAR
  174.         *pszOldFileName,        // Name of the input file    
  175.         *pszNewFileName;        // Name of the output file    
  176.     unsigned long
  177.         nAction = SCRAMBLE,     // Scramble / Unscramble file
  178.         nIdx,                   // Counter in loops
  179.         nNumArgs;               // The number of args from the command line
  180.     
  181.     // These variables are used for the implicit binding
  182.     _TUCHAR    *pszUuid            = NULL;
  183.     _TUCHAR    *pszProtocolSequence= PROTOCOL_SEQUENCE;
  184.     _TUCHAR    *pszNetworkAddress    = NULL;    
  185.     _TUCHAR    *pszEndpoint        = END_POINT;
  186.     _TUCHAR    *pszOptions            = NULL;
  187.     _TUCHAR    *pszStringBinding    = NULL;
  188.     
  189.  
  190.     // Get a common handle on the command line arguments for both 
  191.     // UNICODE and ASCII
  192. #ifdef _UNICODE
  193.     LPWSTR    *szArglist= CommandLineToArgvW(GetCommandLine(), &nNumArgs);
  194.     if (NULL == szArglist)
  195.     {
  196.         _tprintf(TEXT("SERVER.C : CommandLineToArgW failed"));
  197.         exit(EXECUTION_FAILED);
  198.     }
  199. #else
  200.     char **szArglist    = argv;
  201.     nNumArgs = argc;
  202. #endif
  203.  
  204.     // Check to see that the call was correct
  205.     if (nNumArgs < 3)
  206.     {
  207.         Usage(szArglist[0]);
  208.     }
  209.     
  210.     // Allow the user to override settings with commandline switches    
  211.     for (nIdx = 3; nIdx < nNumArgs; nIdx++) 
  212.     {
  213.         if ((_tcscmp(szArglist[nIdx], TEXT("-n")) == 0) ||   
  214.             (_tcscmp(szArglist[nIdx], TEXT("-N")) == 0))
  215.         {
  216.             pszNetworkAddress = szArglist[++nIdx];
  217.         }
  218.         else if((_tcscmp(szArglist[nIdx], TEXT("-p")) == 0) || 
  219.             (_tcscmp(szArglist[nIdx], TEXT("-P")) == 0))
  220.         {
  221.             pszProtocolSequence = szArglist[++nIdx];
  222.         }
  223.         else if((_tcscmp(szArglist[nIdx], TEXT("-e")) == 0) || 
  224.                 (_tcscmp(szArglist[nIdx], TEXT("-e")) == 0))
  225.         {
  226.             pszEndpoint = szArglist[++nIdx];
  227.         }
  228.         else if((_tcscmp(szArglist[nIdx], TEXT("-o")) == 0) || 
  229.                (_tcscmp(szArglist[nIdx], TEXT("-O")) == 0))
  230.         {
  231.             pszOptions = szArglist[++nIdx];
  232.         }
  233.         else if((_tcscmp(szArglist[nIdx], TEXT("-s")) == 0) || 
  234.                 (_tcscmp(szArglist[nIdx], TEXT("-S")) == 0))
  235.         {
  236.             nAction = SCRAMBLE;    
  237.         }
  238.         else if((_tcscmp(szArglist[nIdx], TEXT("-u")) == 0) || 
  239.                 (_tcscmp(szArglist[nIdx], TEXT("-U")) == 0))
  240.         {
  241.             nAction = UNSCRAMBLE;
  242.         }
  243.         else  
  244.         {
  245.             Usage(szArglist[0]);
  246.         }
  247.     }
  248.     
  249.     // Allocate space for the filenames
  250.     if(NULL == (pszOldFileName    = (TCHAR *) midl_user_allocate(
  251.         sizeof(TCHAR) * (_tcsclen(szArglist[1]) + 1))))
  252.     {
  253.         _tprintf(TEXT("Memory allocation error\n"));
  254.         exit(EXECUTION_FAILED);
  255.     }
  256.     if(NULL == (pszNewFileName    = (TCHAR *) midl_user_allocate(
  257.         sizeof(TCHAR) * (_tcsclen(szArglist[2]) + 1))))
  258.     {
  259.         _tprintf(TEXT("Memory allocation error\n"));
  260.         exit(EXECUTION_FAILED);
  261.     }
  262.     
  263.     // Initialize the state variables for the in pipe 
  264.     _tcscpy(pszOldFileName, szArglist[1]);
  265.     _tcscpy(pszNewFileName, szArglist[2]);
  266.  
  267.     // Since we are doing implicit binding, we need to initialize the 
  268.     // global varaible global_pipe_sample_handle from the client.
  269.     // Use a function to concatenate the elements of the string         
  270.     // binding into the proper sequence                                 
  271.     nStatus = RpcStringBindingCompose( 
  272.         pszUuid,                            
  273.         pszProtocolSequence,
  274.         pszNetworkAddress,
  275.         pszEndpoint,
  276.         pszOptions,
  277.         &pszStringBinding); 
  278.     EXIT_IF_FAIL(nStatus, "RpcStringBindingCompose");
  279.  
  280.     // Set the binding handle that will be used to bind to the server
  281.     nStatus = RpcBindingFromStringBinding(   
  282.         pszStringBinding,     
  283.         &global_pipe_sample_handle);        // The global handle
  284.     EXIT_IF_FAIL(nStatus, "RpcBindingFromStringBinding");
  285.  
  286.     
  287.     /* Initialize pipestructure */
  288.     in_out_pipe_state.hOld = NULL;
  289.     in_out_pipe_state.hNew = NULL;
  290.     in_out_pipe_state.pszOldName = pszOldFileName;
  291.     in_out_pipe_state.pszNewName = pszNewFileName;    
  292.  
  293.     in_out_pipe.state    = (char *) &in_out_pipe_state;
  294.     in_out_pipe.alloc    = PipeAlloc;
  295.     in_out_pipe.pull    = PipePull;
  296.     in_out_pipe.push    = PipePush;
  297.  
  298.     RpcTryExcept
  299.     {
  300.         // Call the remote procedure to send the file to remote machine
  301.         _tprintf(TEXT("Calling the remote procedure ScrambleFile()\n"));
  302.         ScrambleFile(nAction, &in_out_pipe);
  303.         _tprintf(TEXT("Call to ScrambleFile() returned\n"));
  304.     }
  305.     RpcExcept(DO_EXCEPTION)
  306.     {
  307.         _tprintf(TEXT("Run-time exception %08X = %d in %s\n"), 
  308.                 RpcExceptionCode(), RpcExceptionCode(), TEXT(__FILE__));
  309.         exit(EXECUTION_FAILED);
  310.     }
  311.     RpcEndExcept
  312.  
  313.  
  314.     // Deallocate the memory used for the names in the state variable
  315.     midl_user_free(pszOldFileName);
  316.     midl_user_free(pszNewFileName);
  317.  
  318.     // Deallocate the memory used for the ARGLIST if using UNICODE
  319. #ifdef _UNICODE
  320.     if (NULL != szArglist)
  321.         free(szArglist);
  322. #endif
  323.  
  324.     // Shut down the server 
  325.     ShutDown();
  326.  
  327.     return (EXECUTION_OK);
  328. }
  329.  
  330.  
  331. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  332. /* Procedure    :   midl_user_allocate() and midl_user_free()           */
  333. /* Desc.        :   These procedure are declared in the header file     */
  334. /*                  generated by the midl compiler. These procedures    */
  335. /*                  should be used for all memory allocation and        */
  336. /*                  deallocation.                                       */
  337. /*                  These procedures are also called by the stub code to*/
  338. /*                  allocate and free memory.                           */
  339. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  340. void __RPC_FAR * __RPC_API midl_user_allocate(size_t nLen)
  341. {
  342.     return (malloc(nLen));
  343. }
  344.  
  345. void __RPC_API midl_user_free(void __RPC_FAR * lpvPointer)
  346. {
  347.     if(NULL == lpvPointer)
  348.     {
  349.         free (lpvPointer);
  350.     }
  351. }
  352.  
  353.