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 / rpcsvc / server.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  13.5 KB  |  630 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1995-1997  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE:   server.c
  9. //
  10. //  PURPOSE:  Implements the body of the RPC service sample.
  11. //
  12. //  FUNCTIONS:
  13. //            Called by service.c:
  14. //            ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv);
  15. //            ServiceStop( );
  16. //
  17. //            Called by RPC:
  18. //            error_status_t Ping(handle_t)
  19. //
  20. //  COMMENTS: The ServerStart and ServerStop functions implemented here are
  21. //            prototyped in service.h.  The other functions are RPC manager
  22. //            functions prototypes in rpcsvc.h.
  23. //              
  24. //
  25. //  AUTHOR: Craig Link - Microsoft Developer Support
  26. //          Mario Goertzel - RPC Development
  27. //
  28.  
  29.  
  30. #include <windows.h>
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <process.h>
  34. #include <tchar.h>
  35. #include <rpc.h>
  36. #include "service.h"
  37. #include "rpcsvc.h"
  38.  
  39. //
  40. // RPC configuration.
  41. //
  42.  
  43. // This service listens to all the protseqs listed in this array.
  44. // This should be read from the service's configuration in the
  45. // registery.
  46.  
  47. TCHAR *ProtocolArray[] = { TEXT("ncalrpc"),
  48.                            TEXT("ncacn_ip_tcp"),
  49.                            TEXT("ncacn_np"),
  50.                            TEXT("ncadg_ip_udp")
  51.                          };
  52.  
  53. // Used in RpcServerUseProtseq, for some protseqs
  54. // this is used as a hint for buffer size.
  55. ULONG ProtocolBuffer = 3;
  56.  
  57. // Use in RpcServerListen().  More threads will increase performance,
  58. // but use more memory.
  59. ULONG MinimumThreads = 3;
  60.  
  61. //
  62. //  FUNCTION: ServiceStart
  63. //
  64. //  PURPOSE: Actual code of the service
  65. //           that does the work.
  66. //
  67. //  PARAMETERS:
  68. //    dwArgc   - number of command line arguments
  69. //    lpszArgv - array of command line arguments
  70. //
  71. //  RETURN VALUE:
  72. //    none
  73. //
  74. //  COMMENTS:
  75. //    Starts the service listening for RPC requests.
  76. //
  77. VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)
  78. {
  79.     UINT i;
  80.     RPC_BINDING_VECTOR *pbindingVector = 0;
  81.     RPC_STATUS status;
  82.     BOOL fListening = FALSE;
  83.  
  84.     ///////////////////////////////////////////////////
  85.     //
  86.     // Service initialization
  87.     //
  88.  
  89.     //
  90.     // Use protocol sequences (protseqs) specified in ProtocolArray.
  91.     //
  92.  
  93.     for(i = 0; i < sizeof(ProtocolArray)/sizeof(TCHAR *); i++)
  94.         {
  95.  
  96.         // Report the status to the service control manager.
  97.         if (!ReportStatusToSCMgr(
  98.             SERVICE_START_PENDING, // service state
  99.             NO_ERROR,              // exit code
  100.             3000))                 // wait hint
  101.             return;
  102.  
  103.  
  104.         status = RpcServerUseProtseq(ProtocolArray[i],
  105.                                      ProtocolBuffer,
  106.                                      0);
  107.  
  108.         if (status == RPC_S_OK)
  109.             {
  110.             fListening = TRUE;
  111.             }
  112.         }
  113.  
  114.     if (!fListening)
  115.         {
  116.         // Unable to listen to any protocol!
  117.         //
  118.         AddToMessageLog(TEXT("RpcServerUseProtseq() failed\n"));
  119.         return;
  120.         }
  121.  
  122.     // Report the status to the service control manager.
  123.     //
  124.     if (!ReportStatusToSCMgr(
  125.         SERVICE_START_PENDING, // service state
  126.         NO_ERROR,              // exit code
  127.         3000))                 // wait hint
  128.         return;
  129.  
  130.     // Register the services interface(s).
  131.     //
  132.  
  133.     status = RpcServerRegisterIf(RpcServiceSample_v1_0_s_ifspec,   // from rpcsvc.h
  134.                                  0,
  135.                                  0);
  136.  
  137.  
  138.     if (status != RPC_S_OK)
  139.         return;
  140.  
  141.     // Report the status to the service control manager.
  142.     //
  143.     if (!ReportStatusToSCMgr(
  144.         SERVICE_START_PENDING, // service state
  145.         NO_ERROR,              // exit code
  146.         3000))                 // wait hint
  147.         return;
  148.  
  149.  
  150.     // Register interface(s) and binding(s) (endpoints) with
  151.     // the endpoint mapper.
  152.     //
  153.  
  154.     status = RpcServerInqBindings(&pbindingVector);
  155.  
  156.     if (status != RPC_S_OK)
  157.         {
  158.         return;
  159.         }
  160.  
  161.     status = RpcEpRegister(RpcServiceSample_v1_0_s_ifspec,   // from rpcsvc.h
  162.                            pbindingVector,
  163.                            0,
  164.                            0);
  165.  
  166.     if (status != RPC_S_OK)
  167.         {
  168.         return;
  169.         }
  170.  
  171.     // Report the status to the service control manager.
  172.     //
  173.     if (!ReportStatusToSCMgr(
  174.         SERVICE_START_PENDING, // service state
  175.         NO_ERROR,              // exit code
  176.         3000))                 // wait hint
  177.         return;
  178.  
  179.     // Enable NT LM Security Support Provider (NtLmSsp service)
  180.     //
  181.     status = RpcServerRegisterAuthInfo(0,
  182.                                        RPC_C_AUTHN_WINNT,
  183.                                        0,
  184.                                        0
  185.                                        );
  186.     if (status != RPC_S_OK)
  187.         {
  188.         return;
  189.         }
  190.  
  191.     // Report the status to the service control manager.
  192.     //
  193.     if (!ReportStatusToSCMgr(
  194.         SERVICE_START_PENDING, // service state
  195.         NO_ERROR,              // exit code
  196.         3000))                 // wait hint
  197.         return;
  198.  
  199.  
  200.     // Start accepting client calls.
  201.     //
  202.     status = RpcServerListen(MinimumThreads,
  203.                              RPC_C_LISTEN_MAX_CALLS_DEFAULT,  // rpcdce.h
  204.                              TRUE);                           // don't block.
  205.  
  206.     if (status != RPC_S_OK)
  207.         {
  208.         return;
  209.         }
  210.  
  211.     // Report the status to the service control manager.
  212.     //
  213.     if (!ReportStatusToSCMgr(
  214.         SERVICE_RUNNING,       // service state
  215.         NO_ERROR,              // exit code
  216.         0))                    // wait hint
  217.         return;
  218.  
  219.     //
  220.     // End of initialization
  221.     //
  222.     ////////////////////////////////////////////////////////////
  223.  
  224.     ////////////////////////////////////////////////////////////
  225.     //
  226.     // Cleanup
  227.     //
  228.  
  229.     // RpcMgmtWaitServerListen() will block until the server has
  230.     // stopped listening.  If this service had something better to
  231.     // do with this thread, it would delay this call until
  232.     // ServiceStop() had been called. (Set an event in ServiceStop()).
  233.     //
  234.     status = RpcMgmtWaitServerListen();
  235.  
  236.     // ASSERT(status == RPC_S_OK)
  237.  
  238.     // Remove entries from the endpoint mapper database.
  239.     //
  240.     RpcEpUnregister(RpcServiceSample_v1_0_s_ifspec,   // from rpcsvc.h
  241.                     pbindingVector,
  242.                     0);
  243.  
  244.     // Delete the binding vector
  245.     //
  246.     RpcBindingVectorFree(&pbindingVector);
  247.  
  248.     //
  249.     ////////////////////////////////////////////////////////////
  250.     return;
  251. }
  252.  
  253.  
  254. //
  255. //  FUNCTION: ServiceStop
  256. //
  257. //  PURPOSE: Stops the service
  258. //
  259. //  PARAMETERS:
  260. //    none
  261. //
  262. //  RETURN VALUE:
  263. //    none
  264. //
  265. //  COMMENTS:
  266. //    If a ServiceStop procedure is going to
  267. //    take longer than 3 seconds to execute,
  268. //    it should spawn a thread to execute the
  269. //    stop code, and return.  Otherwise, the
  270. //    ServiceControlManager will believe that
  271. //    the service has stopped responding.
  272. //    
  273. VOID ServiceStop()
  274. {
  275.     // Stop's the server, wakes the main thread.
  276.  
  277.     RpcMgmtStopServerListening(0);
  278. }
  279.  
  280.  
  281. //
  282. //  FUNCTION: Ping
  283. //
  284. //  PURPOSE: Implements the Ping() operation.
  285. //
  286. //  PARAMETERS:
  287. //    none
  288. //
  289. //  RETURN VALUE:
  290. //    none
  291. //
  292. //  COMMENTS:
  293. //    Ping() operation defined in rpcsvc.idl.
  294. //    Used by clients to test the connection.
  295. //
  296.  
  297. error_status_t
  298. Ping(
  299.     handle_t h
  300.     )
  301. {
  302.     return(0);
  303. }
  304.  
  305. //
  306. //  FUNCTIONS: BufferIn1, BufferIn2, BufferIn3
  307. //
  308. //  PURPOSE: Implements three different methods
  309. //           for sending data to the server.
  310. //
  311. //  PARAMETERS:
  312. //    see rpcsvc.idl
  313. //
  314. //  RETURN VALUE:
  315. //    error_status_t - 0;
  316. //
  317.  
  318. error_status_t
  319. BufferIn1(
  320.          handle_t h,
  321.          byte Buffer[],
  322.          unsigned long Length,
  323.          unsigned long Size
  324.          )
  325. {
  326.     return(0);
  327. }
  328.  
  329. error_status_t
  330. BufferIn2(
  331.          handle_t h,
  332.          byte Buffer[],
  333.          unsigned long Length
  334.          )
  335. {
  336.     return(0);
  337. }
  338.  
  339. error_status_t
  340. BufferIn3(
  341.          handle_t h,
  342.          byte Buffer[],
  343.          unsigned long Length
  344.          )
  345. {
  346.     return(0);
  347. }
  348.  
  349. //
  350. //  FUNCTIONS: BufferOut1, BufferOut2, BufferOut3, BufferOut4
  351. //
  352. //  PURPOSE: Implements four different methods
  353. //           for reading data from the server.
  354. //
  355. //  PARAMETERS:
  356. //    see rpcsvc.idl
  357. //
  358. //  RETURN VALUE:
  359. //    error_status_t - 0;
  360. //
  361.  
  362. error_status_t
  363. BufferOut1(
  364.          handle_t h,
  365.          byte Buffer[],
  366.          unsigned long *pLength
  367.          )
  368. {
  369.     *pLength = BUFFER_SIZE;
  370.     return(0);
  371. }
  372.  
  373. error_status_t
  374. BufferOut2(
  375.           handle_t h,
  376.           byte Buffer[],
  377.           unsigned long Size,
  378.           unsigned long *pLength
  379.           )
  380. {
  381.     *pLength = BUFFER_SIZE;
  382.     return(0);
  383. }
  384.  
  385. error_status_t
  386. BufferOut3(
  387.           handle_t h,
  388.           BUFFER *pBuffer
  389.           )
  390. {
  391.     pBuffer->BufferLength = BUFFER_SIZE;
  392.     pBuffer->Buffer = MIDL_user_allocate(BUFFER_SIZE);
  393.  
  394.     if (pBuffer->Buffer == 0)
  395.         {
  396.         return(RPC_S_OUT_OF_MEMORY);
  397.         }
  398.     return(0);
  399. }
  400.  
  401. error_status_t
  402. BufferOut4(
  403.           handle_t h,
  404.           byte Buffer[],
  405.           unsigned long *pLength
  406.           )
  407. {
  408.     *pLength = BUFFER_SIZE;
  409.     return(0);
  410. }
  411.  
  412. //
  413. //  FUNCTIONS: StructsIn1, StructsIn2, StructsIn3
  414. //
  415. //  PURPOSE: Implements server side of the struct/enum operations.
  416. //
  417. //  PARAMETERS:
  418. //    see rpcsvc.idl
  419. //
  420. //  RETURN VALUE:
  421. //    error_status_t - 0;
  422. //
  423. //
  424. error_status_t
  425. StructsIn1(
  426.           handle_t h,
  427.           struct BAD1 array[50]
  428.           )
  429. {
  430.     return(0);
  431. }
  432.  
  433. error_status_t
  434. StructsIn2(
  435.           handle_t h,
  436.           struct BAD2 array[50]
  437.           )
  438. {
  439.     return(0);
  440. }
  441.  
  442. error_status_t
  443. StructsIn3(
  444.           handle_t h,
  445.           struct GOOD array[50]
  446.           )
  447. {
  448.     return(0);
  449. }
  450.  
  451. //
  452. //  FUNCTIONS: ListIn, ListOut1, ListOut2
  453. //
  454. //  PURPOSE: Implements server side of linked list functions.
  455. //
  456. //
  457. //  PARAMETERS:
  458. //    see rpcsvc.idl
  459. //
  460. //  RETURN VALUE:
  461. //    error_status_t - 0;
  462. //
  463. //  NOTES:
  464. //    Since ListOut2 uses [enable_allocate] it
  465. //    must allocate all memory for parameters
  466. //    with RpcSsAllocate().
  467. //
  468.  
  469. error_status_t
  470. ListIn(
  471.       handle_t h,
  472.       PLIST pList
  473.       )
  474. {
  475.     return(0);
  476. }
  477.  
  478. error_status_t
  479. ListOut1(
  480.         handle_t h,
  481.         LIST *pList
  482.         )
  483. {
  484.     int i;
  485.     for(i = 0; i < LIST_SIZE; i++)
  486.         {
  487.         pList->data = i;
  488.         pList->pNext = MIDL_user_allocate(sizeof(LIST));
  489.         if (pList->pNext == 0)
  490.             {
  491.             return(RPC_S_OUT_OF_MEMORY);
  492.             }
  493.         pList = pList->pNext;
  494.         }
  495.  
  496.     pList->data = i;
  497.     pList->pNext = 0;
  498.  
  499.     return(0);
  500. }
  501.  
  502. error_status_t
  503. ListOut2(
  504.         handle_t h,
  505.         LIST *pList
  506.         )
  507. {
  508.     int i;
  509.     for(i = 0; i < LIST_SIZE; i++)
  510.         {
  511.         pList->data = i;
  512.         pList->pNext = RpcSsAllocate(sizeof(LIST));
  513.         // RpcSsAllocate raises an exception when it
  514.         // fails.  Use RpcSmAllocate is this is
  515.         // undesirable.
  516.         pList = pList->pNext;
  517.         }
  518.  
  519.     pList->data = i;
  520.     pList->pNext = 0;
  521.  
  522.     return(0);
  523. }
  524.  
  525. //
  526. //  FUNCTIONS: UnionCall1, UnionCall2
  527. //
  528. //  PURPOSE: Implements server side of the Union functions.
  529. //
  530. //  PARAMETERS:
  531. //    see rpcsvc.idl
  532. //
  533. //  RETURN VALUE:
  534. //    error_status_t - 0;
  535. //
  536. //
  537. error_status_t
  538. UnionCall1(
  539.           handle_t h,
  540.           unsigned long Length,
  541.           BAD_UNION aUnion[]
  542.           )
  543. {
  544.     return(0);
  545. }
  546.  
  547. error_status_t
  548. UnionCall2(
  549.           handle_t h,
  550.           GOOD_UNION *pUnion
  551.           )
  552. {
  553.     return(0);
  554. }
  555.  
  556. //
  557. //  FUNCTION: CheckSecurity
  558. //
  559. //  PURPOSE: Demonstrates the RPC security APIs.
  560. //
  561. //  PARAMETERS:
  562. //    h - binding to client which made the call.
  563. //
  564. //  RETURN VALUE:
  565. //    0 - no error
  566. //
  567. error_status_t
  568. CheckSecurity(
  569.              handle_t h
  570.              )
  571. {
  572.     RPC_STATUS status;
  573.  
  574.     // At this point the thread is running in the server
  575.     // security context.  There is guarantee that the client
  576.     // even used a secure connection.
  577.  
  578.     status = RpcImpersonateClient(h);
  579.  
  580.     if (status != RPC_S_OK)
  581.         {
  582.         return(RPC_S_ACCESS_DENIED);
  583.         }
  584.  
  585.     // This thread is now running in the clients security context.
  586.  
  587.     //
  588.     // The server should now open a file, mutex, event or its own data
  589.     // structure which has an ACL associated with it to check that the
  590.     // client has the right to access the server's protected data.
  591.     //
  592.  
  593.     status = RpcRevertToSelf();
  594.  
  595.     // ASSERT(status == RPC_S_OK);
  596.  
  597.     // This thread is now running in the server's security context.
  598.  
  599.     return(0);
  600. }
  601.  
  602.  
  603. //
  604. //  FUNCTIONS: MIDL_user_allocate and MIDL_user_free
  605. //
  606. //  PURPOSE: Used by stubs to allocate and free memory
  607. //           in standard RPC calls. Not used when
  608. //           [enable_allocate] is specified in the .acf.
  609. //
  610. //
  611. //  PARAMETERS:
  612. //    See documentations.
  613. //
  614. //  RETURN VALUE:
  615. //    Exceptions on error.  This is not required,
  616. //    you can use -error allocation on the midl.exe
  617. //    command line instead.
  618. //
  619. //
  620. void * __RPC_USER MIDL_user_allocate(size_t size)
  621. {
  622.     return(HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, size));
  623. }
  624.  
  625. void __RPC_USER MIDL_user_free( void *pointer)
  626. {
  627.     HeapFree(GetProcessHeap(), 0, pointer);
  628. }
  629.  
  630.