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 / yield / yieldc.c < prev    next >
C/C++ Source or Header  |  1996-06-12  |  27KB  |  764 lines

  1.  
  2. /****************************************************************************
  3.                    Microsoft RPC Version 2.0
  4.            Copyright Microsoft Corp. 1992, 1993, 1994- 1996
  5.                        yield Example
  6.  
  7.     FILE:       yieldp.c
  8.  
  9.     PURPOSE:    RPC sample Windows client
  10.                 Based on Win 3.x SDK Generic template for Windows applications
  11.  
  12.     FUNCTIONS:  WinMain()         - same as Windows generic example
  13.                 InitApplication() - same as Windows generic example
  14.                 InitInstance()    - same as Windows generic example
  15.                 MainWndProc()     - processes messages
  16.  
  17.                 About()     - processes messages for "About" dialog box
  18.                 BindInfo()  - processes messages for "Bind" dialog box
  19.                 WaitInfo()  - processes messages for "Wait" dialog box
  20.                 YieldInfo() - processes messages for "Yield" dialog box
  21.  
  22.                 Bind()               - calls the RPC API functions
  23.                 midl_user_allocate() - memory allocation function needed by RPC
  24.                 midl_user_free()     - memory free function needed by RPC
  25.  
  26.     COMMENTS:   This sample application demonstrates the yield capability
  27.                 of the Microsoft RPC for Microsoft Windows 3.x using the
  28.                 RpcWinSetYieldInfo API function.
  29.  
  30.                 By yielding, you can prevent your distributed application
  31.                 from blocking during lengthy remote procedure calls.
  32.  
  33.                 This sample is based on the Win 3.x generic example. To focus
  34.                 attention on the RPC-related aspects of this application,
  35.                 many comments from the Windows-only version are removed.
  36.  
  37. ****************************************************************************/
  38.  
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <windows.h>
  43. #include <windowsx.h>
  44. #include "yield.h"     // header file generated by MIDL compiler
  45. #include "yieldc.h"    // client-specific header file
  46.  
  47. /* global data */
  48.  
  49. unsigned char   pszProtocolSequence[MAXPROTSEQ+1];
  50. unsigned char   pszNetworkAddress[NETLEN+1];
  51. unsigned char   pszEndpoint[PATHLEN+1];
  52. unsigned char * pszUuid           = NULL;
  53. unsigned char * pszOptions        = NULL;
  54. unsigned char * pszStringBinding  = NULL;
  55.  
  56. int fBound = FALSE;    // flag indicates whether client is bound to server
  57. int fCancel = FALSE;   // flag indicates whether the user has chosen CANCEL
  58.  
  59. unsigned int cWaitSec; // parameter to remote procedure Sleep()
  60.  
  61. int   fCustomYield;    // TRUE = custom yield, FALSE = standard yield
  62. DWORD dwOtherInfo;     // depends on the value of fCustomYield
  63.  
  64. HANDLE  hInst;         // current instance
  65. HCURSOR hHourGlass;    // during calls to RPC API functions
  66. HWND    hWndMain;      // main handle
  67.  
  68.  
  69. /****************************************************************************
  70.  
  71.     FUNCTION: WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
  72.  
  73.     PURPOSE:  Calls initialization function, processes message loop
  74.  
  75.     COMMENTS: Windows recognizes this function by name as the initial
  76.               entry point for the program.  This function calls the
  77.               application initialization routine, if no other instance
  78.               of the program is running, and always calls the instance
  79.               initialization routine.  It then executes a message
  80.               retrieval and dispatch loop that is the top-level control
  81.               structure for the remainder of execution.  The loop is
  82.               terminated when a WM_QUIT message is received, at which
  83.               time this function exits the application instance by
  84.               returning the value passed by PostQuitMessage().
  85.  
  86.               If this function must abort before entering the message
  87.               loop, it returns the conventional value NULL.
  88.  
  89. ****************************************************************************/
  90.  
  91. int WINAPI WinMain(HINSTANCE hInstance,      // current instance
  92.                    HINSTANCE hPrevInstance,  // previous instance
  93.                    LPSTR     lpCmdLine,      // command line
  94.                    int       nCmdShow)       // show-window type
  95. {
  96.     MSG msg;
  97.  
  98.     UNREFERENCED_PARAMETER(lpCmdLine);
  99.  
  100.     if (! hPrevInstance)                   // no other instances of app running
  101.         if (! InitApplication(hInstance))  // initialize shared things
  102.             return(FALSE);                 // exit if unable to initialize
  103.  
  104.     /* Perform initializations that apply to a specific instance */
  105.     if (! InitInstance(hInstance, nCmdShow))
  106.         return(FALSE);
  107.  
  108.     /* Acquire and dispatch messages until a WM_QUIT message is received */
  109.     while (GetMessage(&msg,        // message structure
  110.                       (HWND)NULL,  // handle of window receiving the message
  111.                       0,           // lowest message to examine
  112.                       0))          // highest message to examine
  113.     {
  114.         TranslateMessage(&msg);    // translate virtual key codes
  115.         DispatchMessage(&msg);     // dispatche message to window
  116.     }
  117.  
  118.     return(msg.wParam);  // return the value from PostQuitMessage
  119. }
  120.  
  121.  
  122. /****************************************************************************
  123.  
  124.     FUNCTION: InitApplication(HANDLE)
  125.  
  126.     PURPOSE:  Initializes window data and registers window class
  127.  
  128.     COMMENTS: This function is called at initialization time only if
  129.               no other instances of the application are running.  This
  130.               function performs initialization tasks that can be done
  131.               once for any number of running instances.
  132.  
  133.               In this case, we initialize a window class by filling out
  134.               a data structure of type WNDCLASS and calling the Windows
  135.               RegisterClass() function.  Since all instances of this
  136.               application use the same window class, we only need to do
  137.               this when the first instance is initialized.
  138.  
  139. ****************************************************************************/
  140.  
  141. BOOL InitApplication(HANDLE hInstance)    // current instance
  142. {
  143.     WNDCLASS wc;
  144.  
  145.     /* Fill in the window class structure with parameters that   */
  146.     /* describe the main window                                  */
  147.     wc.style         = 0;
  148.     wc.lpfnWndProc   = (WNDPROC) MainWndProc;
  149.     wc.cbClsExtra    = 0;
  150.     wc.cbWndExtra    = 0;
  151.     wc.hInstance     = hInstance;
  152.     wc.hIcon         = LoadIcon(hInstance, "YieldIcon");
  153.     wc.hCursor       = LoadCursor((HANDLE) NULL, IDC_ARROW);
  154.     wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  155.     wc.lpszMenuName  = "GenericMenu";
  156.     wc.lpszClassName = "GenericWClass";
  157.  
  158.     /* Register the window class and return success/failure code */
  159.     return(RegisterClass(&wc));
  160. }
  161.  
  162.  
  163. /****************************************************************************
  164.  
  165.     FUNCTION:  InitInstance(HANDLE, int)
  166.  
  167.     PURPOSE:   Saves instance handle and creates main window
  168.  
  169.     COMMENTS:  This function is called at initialization time for every
  170.                instance of this application.  This function performs
  171.                initialization tasks that cannot be shared by multiple
  172.                instances.
  173.  
  174.                In this case, we save the instance handle in a global
  175.                variable and create and display the main program window.
  176.  
  177. ****************************************************************************/
  178.  
  179. BOOL InitInstance(HANDLE  hInstance,    // current instance
  180.                   int     nCmdShow)     // param for first ShowWindow() call
  181. {
  182.     HWND hWnd;
  183.  
  184.  
  185.     /* Save the instance handle in global variable, which will be used */
  186.     /* in many subsequence calls from this application to Windows      */
  187.     hInst = hInstance;
  188.     hHourGlass = LoadCursor((HANDLE) NULL, IDC_WAIT);
  189.  
  190.     /* Create a main window for this application instance */
  191.     hWnd = CreateWindow("GenericWClass",
  192.                         "RPC Sample Application",
  193.                         WS_OVERLAPPEDWINDOW,
  194.                         CW_USEDEFAULT,
  195.                         CW_USEDEFAULT,
  196.                         CW_USEDEFAULT,
  197.                         CW_USEDEFAULT,
  198.                         (HWND) NULL,
  199.                         (HMENU) NULL,
  200.                         hInstance,
  201.                         (LPVOID) NULL
  202.                         );
  203.  
  204.     /* If the window cannot be created, return "failure" */
  205.     if (!hWnd)
  206.         return(FALSE);
  207.  
  208.     /* Initialize RPC binding data */
  209.     strcpy(pszProtocolSequence, DEFAULT_PROT_SEQ);
  210.     strcpy(pszEndpoint, DEFAULT_ENDPOINT);
  211.     pszNetworkAddress[0] = '\0';
  212.  
  213.     /* Bind client to server */
  214.     fBound = FALSE;
  215.  
  216.     /* Initialize the parameter to the remote procedure Sleep() */
  217.     cWaitSec = DEFAULT_WAIT;
  218.  
  219.     /* Initialize the parameters to RpcWinSetYieldInfo() */
  220.     fCustomYield = FALSE;         // FALSE = std yield
  221.     dwOtherInfo = (DWORD) NULL;   // NULL = RPC-supplied dialog box
  222.  
  223.     RpcWinSetYieldInfo(hWnd,                  // handle
  224.                        fCustomYield,          // standard or custom yield?
  225.                        WM_RPC_YIELD_MESSAGE,  // 0 = no message is posted
  226.                        dwOtherInfo);          // depends on fCustomYield value
  227.  
  228.     /* Make the window visible, update its client area, and return "success" */
  229.     ShowWindow(hWnd, nCmdShow);
  230.     UpdateWindow(hWnd);
  231.  
  232.     return(TRUE);
  233. }
  234.  
  235.  
  236. /****************************************************************************
  237.  
  238.     FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)
  239.  
  240.     PURPOSE:  Processes messages
  241.  
  242.     MESSAGES: WM_COMMAND  - application menu (About dialog box)
  243.               WM_DESTROY  - destroy window
  244.  
  245.     COMMENTS: Based on the Windows generic sample.
  246.               Several new menu items are added to demonstrate the
  247.               RpcWinSetYieldInfo function.
  248.  
  249.               The "Bind" menu is associated with the "GetBindInfo"
  250.               dialog box function.  GetBindInfo allows the user to
  251.               set the parameters for the RpcStringBindingCompose and
  252.               RpcBindingFromStringBinding functions.  A flag, fBound,
  253.               keeps track of whether the client application is bound
  254.               to a remote server.  If this flag indicates that the
  255.               client application is not bound to the server, it calls
  256.               the "Bind" utility function to call the
  257.               RPC API functions that establish the binding.
  258.  
  259.               The "Yield" menu is associated with the "GetYieldInfo"
  260.               dialog box function. GetYieldInfo allows the user to
  261.               select the yielding model:  standard yield with an
  262.               RPC run-time library-supplied dialog box; standard
  263.               yield with a user-supplied dialog box; or custom yield.
  264.               These methods are described in detail in the documentation
  265.               for the RpcWinSetYieldInfo function.
  266.  
  267. ****************************************************************************/
  268.  
  269. long APIENTRY MainWndProc(HWND hWnd,       // window handle
  270.                           UINT message,    // type of message
  271.                           WPARAM wParam,   // additional information
  272.                           LPARAM lParam    // additional information
  273.                           )
  274. {
  275.     DLGPROC lpProc;    // pointer to the dialog box function
  276.  
  277.     /* copy the window handle for CustomYield() */
  278.     hWndMain = hWnd;
  279.  
  280.     switch (message) {
  281.  
  282.     case WM_CREATE:
  283.         /* Win 3.x is client-only; force user to specify server */
  284.         PostMessage(hWnd, WM_COMMAND, IDM_BIND, 0L);
  285.         break;
  286.  
  287.     case WM_COMMAND:
  288.         switch (wParam) {
  289.  
  290.         case IDM_ABOUT:
  291.             lpProc = MakeProcInstance(About, hInst);
  292.             DialogBox(hInst,
  293.                       "AboutBox",
  294.                       hWnd,
  295.                       lpProc);
  296.             FreeProcInstance(lpProc);
  297.             break;
  298.  
  299.         case IDM_BIND:
  300.             lpProc = MakeProcInstance(GetBindInfo, hInst);
  301.             DialogBox(hInst,
  302.                       "BindBox",
  303.                       hWnd,
  304.                       lpProc);
  305.             FreeProcInstance(lpProc);
  306.             break;
  307.  
  308.         case IDM_WAIT:
  309.             lpProc = MakeProcInstance(GetWaitInfo, hInst);
  310.             DialogBox(hInst,
  311.                       "WaitBox",
  312.                       hWnd,
  313.                       lpProc);
  314.             FreeProcInstance(lpProc);
  315.             break;
  316.  
  317.         case IDM_YIELD:
  318.             lpProc = MakeProcInstance(GetYieldInfo, hInst);
  319.             DialogBox(hInst,
  320.                       "YieldBox",
  321.                       hWnd,
  322.                       lpProc);
  323.             FreeProcInstance(lpProc);
  324.             break;
  325.  
  326.         case IDM_EXIT:
  327.             DestroyWindow(hWnd);
  328.             if (fBound == TRUE) {
  329.                 RpcTryExcept {
  330.                     Shutdown();     // shut down the server
  331.                 }
  332.                 RpcExcept(1) {
  333.                     MessageBox(hWnd,
  334.                                EXCEPT_MSG,
  335.                                "Remote Procedure Call",
  336.                                MB_ICONINFORMATION);
  337.                 }
  338.                 RpcEndExcept
  339.             }
  340.             break;
  341.  
  342.         default:
  343.             return(DefWindowProc(hWnd, message, wParam, lParam));
  344.  
  345.         }
  346.         break;
  347.  
  348.     case WM_RPC_YIELD_MESSAGE:   // signals beginning or end of yield period
  349.         if (wParam == 0)
  350.             SetWindowText(hWnd, YIELD_END_MSG);
  351.         else if (wParam == 1)
  352.             SetWindowText(hWnd, YIELD_START_MSG);
  353.         break;
  354.  
  355.     case WM_DESTROY:
  356.         PostQuitMessage(0);
  357.         break;
  358.  
  359.     default:  // passes it on if unprocessed
  360.         return(DefWindowProc(hWnd, message, wParam, lParam));
  361.  
  362.     }
  363.  
  364.     return(0L);
  365. }
  366.  
  367.  
  368. /****************************************************************************
  369.  
  370.     FUNCTION: About(HWND, unsigned, WORD, LONG)
  371.  
  372.     PURPOSE:  "About" dialog box
  373.  
  374.     COMMENTS:
  375.  
  376. ****************************************************************************/
  377.  
  378. BOOL APIENTRY About(HWND hDlg,
  379.                     UINT message,
  380.                     UINT wParam,
  381.                     LONG lParam)
  382. {
  383.     UNREFERENCED_PARAMETER(lParam);
  384.  
  385.     switch (message) {
  386.  
  387.     case WM_INITDIALOG:
  388.         return(TRUE);
  389.  
  390.     case WM_COMMAND:
  391.         if (wParam == IDOK || wParam == IDCANCEL) {
  392.             EndDialog(hDlg, TRUE);
  393.             return(TRUE);
  394.         }
  395.         break;
  396.  
  397.     }
  398.  
  399.     return(FALSE);
  400. }
  401.  
  402.  
  403. /****************************************************************************
  404.  
  405.     FUNCTION: GetBindInfo(HWND, unsigned, WORD, LONG)
  406.  
  407.     PURPOSE:  Collect components of string binding;
  408.               protocol sequence, network address, endpoint
  409.  
  410.     COMMENTS:
  411.  
  412. ****************************************************************************/
  413.  
  414. BOOL APIENTRY GetBindInfo(HWND hDlg,
  415.                           UINT message,
  416.                           UINT wParam,
  417.                           LONG lParam)
  418. {
  419.     HCURSOR hOld;
  420.  
  421.     UNREFERENCED_PARAMETER(lParam);
  422.  
  423.     switch (message) {
  424.  
  425.     case WM_INITDIALOG:  // fill in dialog's edit boxes
  426.         SetDlgItemText(hDlg, IDD_ENDPOINT, pszEndpoint);
  427.         SetDlgItemText(hDlg, IDD_PROT_SEQ, pszProtocolSequence);
  428.         SetDlgItemText(hDlg, IDD_NET_ADDR, pszNetworkAddress);
  429.         return(TRUE);
  430.  
  431.     case WM_COMMAND:
  432.         switch(wParam) {
  433.  
  434.         case IDCANCEL:
  435.             EndDialog(hDlg, FALSE);
  436.             return(TRUE);
  437.  
  438.         case IDOK:
  439.             GetDlgItemText(hDlg, IDD_PROT_SEQ, pszProtocolSequence, MAXPROTSEQ);
  440.             GetDlgItemText(hDlg, IDD_ENDPOINT, pszEndpoint, PATHLEN);
  441.             GetDlgItemText(hDlg, IDD_NET_ADDR, pszNetworkAddress, NETLEN);
  442.  
  443.             hOld = SetCursor(hHourGlass);
  444.             if (Bind(hDlg) != RPC_S_OK) {  // bind to server
  445.                 EndDialog(hDlg, FALSE);
  446.                 return(FALSE);
  447.             }
  448.  
  449.             SetCursor(hOld);
  450.             EndDialog(hDlg, TRUE);
  451.             return(TRUE);
  452.        }
  453.     }
  454.  
  455.     return(FALSE);
  456. }
  457.  
  458.  
  459. /****************************************************************************
  460.  
  461.     FUNCTION: GetWaitInfo(HWND, unsigned, WORD, LONG)
  462.  
  463.     PURPOSE:  Prompt user for the parameter to the remote call,
  464.               then make the remote procedure call.
  465.  
  466.     COMMENTS:
  467.  
  468. ****************************************************************************/
  469.  
  470. BOOL APIENTRY GetWaitInfo(HWND hDlg,     // window handle of the dialog box
  471.                           UINT message,  // type of message
  472.                           UINT wParam,   // message-specific information
  473.                           LONG lParam)
  474. {
  475.     int fError;
  476.  
  477.     UNREFERENCED_PARAMETER(lParam);
  478.  
  479.     switch (message) {
  480.  
  481.     case WM_INITDIALOG:
  482.         SetDlgItemInt(hDlg, IDD_WAITTIME, cWaitSec, FALSE);
  483.         return(TRUE);
  484.  
  485.     case WM_COMMAND:
  486.         switch(wParam) {
  487.  
  488.         case IDCANCEL:
  489.             EndDialog(hDlg, FALSE);
  490.             fCancel = TRUE;
  491.             return(TRUE);
  492.  
  493.         case IDOK:
  494.             cWaitSec = GetDlgItemInt(hDlg, IDD_WAITTIME, &fError, FALSE);
  495.             if (cWaitSec <= 0)            // check for valid entry
  496.                 cWaitSec = DEFAULT_WAIT;  // set an appropriate value
  497.  
  498.             RpcTryExcept {
  499.                 YieldProc(cWaitSec);      // make the remote procedure call
  500.             }
  501.             RpcExcept(1) {
  502.                 unsigned long ulCode;
  503.                 char pszFail[MSGLEN];
  504.  
  505.                 ulCode = RpcExceptionCode();
  506.                 if (ulCode != RPC_S_CALL_FAILED) {
  507.                     sprintf(pszFail, "%s (0x%x)\n", EXCEPT_MSG, ulCode);
  508.                     MessageBox(hDlg,
  509.                                pszFail,
  510.                                "Remote Procedure Call",
  511.                                MB_ICONINFORMATION);
  512.                 }
  513.             }
  514.             RpcEndExcept
  515.  
  516.             EndDialog(hDlg, TRUE);
  517.             return(TRUE);
  518.         }
  519.     }
  520.  
  521.     return(FALSE);
  522. }
  523.  
  524.  
  525. /****************************************************************************
  526.  
  527.     FUNCTION: CustomYield(void)
  528.  
  529.     PURPOSE:  Message handler during custom yield
  530.  
  531.     MESSAGES: WM_RPC_YIELD_MESSAGE - end of yield message
  532.               WM_COMMAND           - Input received
  533.  
  534.     COMMENTS: The callback function must retrieve messages from the
  535.               message queue.
  536.  
  537.               The function must return TRUE when the RPC operation
  538.               has completed. The function must return FALSE when the
  539.               user cancels the RPC operation.
  540.  
  541. ****************************************************************************/
  542.  
  543. BOOL FAR PASCAL __export CustomYield(void)
  544. {
  545.     MSG msg;
  546.  
  547.     fCancel = FALSE;
  548.  
  549.     while (TRUE) {  // message processing
  550.         GetMessage(&msg, (HWND)NULL, 0, 0);
  551.  
  552.         if (msg.message == WM_RPC_YIELD_MESSAGE)
  553.             return(TRUE);  // RPC operation is complete
  554.  
  555.         if (fCancel == TRUE)
  556.             return(FALSE);
  557.  
  558.         TranslateMessage(&msg);
  559.         DispatchMessage(&msg);
  560.     }
  561.  
  562.     return(TRUE);
  563. }
  564.  
  565.  
  566. /****************************************************************************
  567.  
  568.     FUNCTION: GetYieldInfo(HWND, unsigned, WORD, LONG)
  569.  
  570.     PURPOSE:  Check radio buttons to see which yield method
  571.               was selected by the user, then set the parameters
  572.               to RpcWinSetYieldInfo and call RpcWinSetYieldInfo.
  573.  
  574.     COMMENTS:
  575.  
  576. ****************************************************************************/
  577.  
  578. BOOL APIENTRY GetYieldInfo(HWND hDlg,     // window handle of the dialog box
  579.                            UINT message,  // type of message
  580.                            UINT wParam,   // message-specific information
  581.                            LONG lParam)
  582. {
  583.     int fCheck;
  584.  
  585.     UNREFERENCED_PARAMETER(lParam);
  586.  
  587.     switch (message) {
  588.  
  589.     case WM_INITDIALOG:  // message: initialize dialog box
  590.         if (fCustomYield)
  591.             CheckRadioButton(hDlg, IDD_STD_RPC, IDD_CUSTOM, IDD_CUSTOM);
  592.         else if (dwOtherInfo != (DWORD) NULL)
  593.             CheckRadioButton(hDlg, IDD_STD_RPC, IDD_CUSTOM, IDD_STD_USER);
  594.         else
  595.             CheckRadioButton(hDlg, IDD_STD_RPC, IDD_CUSTOM, IDD_STD_RPC);
  596.         return(TRUE);
  597.  
  598.     case WM_COMMAND:     // message: received a command
  599.         switch(wParam) {
  600.  
  601.             case IDCANCEL:   // System menu close command?
  602.                 EndDialog(hDlg, FALSE);
  603.                 return(TRUE);
  604.  
  605.             case IDOK:
  606.                 /* which radio button is checked: Custom yield? */
  607.                 fCheck = (int) SendDlgItemMessage(hDlg,
  608.                                                   IDD_CUSTOM,
  609.                                                   BM_GETCHECK,
  610.                                                   0,
  611.                                                   0);
  612.                 if (fCheck == TRUE) {
  613.                     fCustomYield = TRUE;
  614.                     dwOtherInfo = (DWORD) MakeProcInstance(CustomYield, hInst);
  615.                 }
  616.                 else {
  617.                     fCustomYield = FALSE;
  618.  
  619.                     /* Standard yield, user-supplied dialog? */
  620.                     fCheck = (int) SendDlgItemMessage(hDlg,
  621.                                                       IDD_STD_USER,
  622.                                                       BM_GETCHECK,
  623.                                                       0,
  624.                                                       0);
  625.                     if (fCheck == TRUE) {
  626.                         HRSRC hrsrc;
  627.  
  628.                         hrsrc = FindResource(hInst,
  629.                                              "USERYIELDBOX",
  630.                                              RT_DIALOG);
  631.                         dwOtherInfo = LoadResource(hInst, hrsrc);
  632.                     }
  633.                     else {
  634.                         /* Assume standard-yield, rpc-supplied dialog box */
  635.                         dwOtherInfo = (DWORD) NULL;
  636.                     }
  637.                 }
  638.  
  639.                 RpcWinSetYieldInfo(hWndMain,
  640.                                    fCustomYield,
  641.                                    WM_RPC_YIELD_MESSAGE,
  642.                                    dwOtherInfo);
  643.  
  644.                 EndDialog(hDlg, TRUE);
  645.                 return(TRUE);
  646.         }
  647.     }
  648.  
  649.     return(FALSE);
  650. }
  651.  
  652.  
  653. /****************************************************************************
  654.  
  655.     FUNCTION: midl_user_allocate(size_t)
  656.  
  657.     PURPOSE:  Allocate memory as needed by the RPC runtime library
  658.  
  659.     COMMENTS: The stubs or runtime libraries may need to allocate memory.
  660.               By convention, they call a user-specified function named
  661.               midl_user_allocate.  In this application, no memory
  662.               management is needed, so a dummy function is provided.
  663.  
  664. ****************************************************************************/
  665.  
  666. void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
  667. {
  668.     UNREFERENCED_PARAMETER(len);
  669.     return(NULL);  // no memory management required
  670. }
  671.  
  672. /****************************************************************************
  673.  
  674.     FUNCTION: midl_user_free(void *)
  675.  
  676.     PURPOSE:  Free memory as needed by the RPC runtime library
  677.  
  678.     COMMENTS: The stubs or runtime libraries may need to free memory.
  679.               By convention, they call a user-specified function named
  680.               midl_user_free.  In this application, no memory allocation
  681.               is needed so a dummy function is provided.
  682.  
  683. ****************************************************************************/
  684.  
  685. void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
  686. {
  687.     UNREFERENCED_PARAMETER(ptr);
  688.     return;    // no memory management required
  689. }
  690.  
  691.  
  692. /****************************************************************************
  693.  
  694.     FUNCTION: Bind(HWND)
  695.  
  696.     PURPOSE:  Make RPC API calls to bind to the server application
  697.  
  698.     COMMENTS: The binding calls are made from InitInstance() and whenever
  699.               the user changes the protocol sequence, network address, or
  700.               endpoint. If the bind operation is successful, the global
  701.               flag fBound is set to TRUE.
  702.  
  703.               The global flag fBound is used to determine whether to call
  704.               the RPC API function RpcBindingFree.
  705.  
  706. ****************************************************************************/
  707.  
  708. RPC_STATUS Bind(HWND hWnd)
  709. {
  710.     RPC_STATUS status;
  711.     char pszFail[MSGLEN];
  712.  
  713.     if (fBound == TRUE) {  // unbind only if bound
  714.         status = RpcStringFree(&pszStringBinding);  // remote calls done; unbind
  715.         if (status) {
  716.             MessageBox(hWnd, "RpcStringFree failed", "RPC Error", MB_ICONSTOP);
  717.             return(status);
  718.         }
  719.  
  720.         status = RpcBindingFree(&hYield);  // remote calls done; unbind
  721.         if (status) {
  722.             MessageBox(hWnd, "RpcBindingFree failed", "RPC Error", MB_ICONSTOP);
  723.             return(status);
  724.         }
  725.  
  726.         fBound = FALSE;  // unbind successful; reset flag
  727.     }
  728.  
  729.     status = RpcStringBindingCompose(pszUuid,
  730.                                      pszProtocolSequence,
  731.                                      pszNetworkAddress,
  732.                                      pszEndpoint,
  733.                                      pszOptions,
  734.                                      &pszStringBinding);
  735.     if (status) {
  736.         sprintf(pszFail, "RpcStringBindingCompose failed: (0x%x)\nNetwork Address = %s\n",
  737.                 status, pszNetworkAddress);
  738.         MessageBox(hWnd,
  739.                    pszFail,
  740.                    "RPC Runtime Error",
  741.                    MB_ICONEXCLAMATION);
  742.         return(status);
  743.     }
  744.  
  745.     status = RpcBindingFromStringBinding(pszStringBinding,
  746.                                          &hYield);
  747.     if (status) {
  748.         sprintf(pszFail, "RpcBindingFromStringBinding failed: (0x%x)\nString = %s\n",
  749.                 status, pszStringBinding);
  750.         MessageBox(hWnd,
  751.                    pszFail,
  752.                    "RPC Runtime Error",
  753.                    MB_ICONEXCLAMATION);
  754.         return(status);
  755.     }
  756.  
  757.     fBound = TRUE;  // bind successful; reset flag
  758.  
  759.     return(status);
  760. }
  761.  
  762.  
  763. /**** end yieldc.c ****/
  764.