|
|
1.1 ! root 1: ! 2: /**************************************************************************** ! 3: Microsoft RPC Version 1.0 ! 4: Copyright Microsoft Corp. 1992 ! 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[UNCLEN+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, UNCLEN); ! 442: ! 443: /* pszNetworkAddress must start with two backslashes */ ! 444: if (pszNetworkAddress[0] != '\0' && ! 445: strncmp(pszNetworkAddress, "\\\\", 2)) { ! 446: ! 447: unsigned char oldNetAddr[UNCLEN+1]; ! 448: ! 449: strcpy(oldNetAddr, pszNetworkAddress); ! 450: sprintf(pszNetworkAddress, "\\\\%s", oldNetAddr); ! 451: } ! 452: ! 453: hOld = SetCursor(hHourGlass); ! 454: if (Bind(hDlg) != RPC_S_OK) { // bind to server ! 455: EndDialog(hDlg, FALSE); ! 456: return(FALSE); ! 457: } ! 458: ! 459: SetCursor(hOld); ! 460: EndDialog(hDlg, TRUE); ! 461: return(TRUE); ! 462: } ! 463: } ! 464: ! 465: return(FALSE); ! 466: } ! 467: ! 468: ! 469: /**************************************************************************** ! 470: ! 471: FUNCTION: GetWaitInfo(HWND, unsigned, WORD, LONG) ! 472: ! 473: PURPOSE: Prompt user for the parameter to the remote call, ! 474: then make the remote procedure call. ! 475: ! 476: COMMENTS: ! 477: ! 478: ****************************************************************************/ ! 479: ! 480: BOOL APIENTRY GetWaitInfo(HWND hDlg, // window handle of the dialog box ! 481: UINT message, // type of message ! 482: UINT wParam, // message-specific information ! 483: LONG lParam) ! 484: { ! 485: int fError; ! 486: ! 487: UNREFERENCED_PARAMETER(lParam); ! 488: ! 489: switch (message) { ! 490: ! 491: case WM_INITDIALOG: ! 492: SetDlgItemInt(hDlg, IDD_WAITTIME, cWaitSec, FALSE); ! 493: return(TRUE); ! 494: ! 495: case WM_COMMAND: ! 496: switch(wParam) { ! 497: ! 498: case IDCANCEL: ! 499: EndDialog(hDlg, FALSE); ! 500: fCancel = TRUE; ! 501: return(TRUE); ! 502: ! 503: case IDOK: ! 504: cWaitSec = GetDlgItemInt(hDlg, IDD_WAITTIME, &fError, FALSE); ! 505: if (cWaitSec <= 0) // check for valid entry ! 506: cWaitSec = DEFAULT_WAIT; // set an appropriate value ! 507: ! 508: RpcTryExcept { ! 509: YieldProc(cWaitSec); // make the remote procedure call ! 510: } ! 511: RpcExcept(1) { ! 512: unsigned long ulCode; ! 513: char pszFail[MSGLEN]; ! 514: ! 515: ulCode = RpcExceptionCode(); ! 516: if (ulCode != RPC_S_CALL_FAILED) { ! 517: sprintf(pszFail, "%s (0x%x)\n", EXCEPT_MSG, ulCode); ! 518: MessageBox(hDlg, ! 519: pszFail, ! 520: "Remote Procedure Call", ! 521: MB_ICONINFORMATION); ! 522: } ! 523: } ! 524: RpcEndExcept ! 525: ! 526: EndDialog(hDlg, TRUE); ! 527: return(TRUE); ! 528: } ! 529: } ! 530: ! 531: return(FALSE); ! 532: } ! 533: ! 534: ! 535: /**************************************************************************** ! 536: ! 537: FUNCTION: CustomYield(void) ! 538: ! 539: PURPOSE: Message handler during custom yield ! 540: ! 541: MESSAGES: WM_RPC_YIELD_MESSAGE - end of yield message ! 542: WM_COMMAND - Input received ! 543: ! 544: COMMENTS: The callback function must retrieve messages from the ! 545: message queue. ! 546: ! 547: The function must return TRUE when the RPC operation ! 548: has completed. The function must return FALSE when the ! 549: user cancels the RPC operation. ! 550: ! 551: ****************************************************************************/ ! 552: ! 553: BOOL FAR PASCAL __export CustomYield(void) ! 554: { ! 555: MSG msg; ! 556: ! 557: fCancel = FALSE; ! 558: ! 559: while (TRUE) { // message processing ! 560: GetMessage(&msg, (HWND)NULL, 0, 0); ! 561: ! 562: if (msg.message == WM_RPC_YIELD_MESSAGE) ! 563: return(TRUE); // RPC operation is complete ! 564: ! 565: if (fCancel == TRUE) ! 566: return(FALSE); ! 567: ! 568: TranslateMessage(&msg); ! 569: DispatchMessage(&msg); ! 570: } ! 571: ! 572: return(TRUE); ! 573: } ! 574: ! 575: ! 576: /**************************************************************************** ! 577: ! 578: FUNCTION: GetYieldInfo(HWND, unsigned, WORD, LONG) ! 579: ! 580: PURPOSE: Check radio buttons to see which yield method ! 581: was selected by the user, then set the parameters ! 582: to RpcWinSetYieldInfo and call RpcWinSetYieldInfo. ! 583: ! 584: COMMENTS: ! 585: ! 586: ****************************************************************************/ ! 587: ! 588: BOOL APIENTRY GetYieldInfo(HWND hDlg, // window handle of the dialog box ! 589: UINT message, // type of message ! 590: UINT wParam, // message-specific information ! 591: LONG lParam) ! 592: { ! 593: int fCheck; ! 594: ! 595: UNREFERENCED_PARAMETER(lParam); ! 596: ! 597: switch (message) { ! 598: ! 599: case WM_INITDIALOG: // message: initialize dialog box ! 600: if (fCustomYield) ! 601: CheckRadioButton(hDlg, IDD_STD_RPC, IDD_CUSTOM, IDD_CUSTOM); ! 602: else if (dwOtherInfo != (DWORD) NULL) ! 603: CheckRadioButton(hDlg, IDD_STD_RPC, IDD_CUSTOM, IDD_STD_USER); ! 604: else ! 605: CheckRadioButton(hDlg, IDD_STD_RPC, IDD_CUSTOM, IDD_STD_RPC); ! 606: return(TRUE); ! 607: ! 608: case WM_COMMAND: // message: received a command ! 609: switch(wParam) { ! 610: ! 611: case IDCANCEL: // System menu close command? ! 612: EndDialog(hDlg, FALSE); ! 613: return(TRUE); ! 614: ! 615: case IDOK: ! 616: /* which radio button is checked: Custom yield? */ ! 617: fCheck = (int) SendDlgItemMessage(hDlg, ! 618: IDD_CUSTOM, ! 619: BM_GETCHECK, ! 620: 0, ! 621: 0); ! 622: if (fCheck == TRUE) { ! 623: fCustomYield = TRUE; ! 624: dwOtherInfo = (DWORD) MakeProcInstance(CustomYield, hInst); ! 625: } ! 626: else { ! 627: fCustomYield = FALSE; ! 628: ! 629: /* Standard yield, user-supplied dialog? */ ! 630: fCheck = (int) SendDlgItemMessage(hDlg, ! 631: IDD_STD_USER, ! 632: BM_GETCHECK, ! 633: 0, ! 634: 0); ! 635: if (fCheck == TRUE) { ! 636: HRSRC hrsrc; ! 637: ! 638: hrsrc = FindResource(hInst, ! 639: "USERYIELDBOX", ! 640: RT_DIALOG); ! 641: dwOtherInfo = LoadResource(hInst, hrsrc); ! 642: } ! 643: else { ! 644: /* Assume standard-yield, rpc-supplied dialog box */ ! 645: dwOtherInfo = (DWORD) NULL; ! 646: } ! 647: } ! 648: ! 649: RpcWinSetYieldInfo(hWndMain, ! 650: fCustomYield, ! 651: WM_RPC_YIELD_MESSAGE, ! 652: dwOtherInfo); ! 653: ! 654: EndDialog(hDlg, TRUE); ! 655: return(TRUE); ! 656: } ! 657: } ! 658: ! 659: return(FALSE); ! 660: } ! 661: ! 662: ! 663: /**************************************************************************** ! 664: ! 665: FUNCTION: midl_user_allocate(size_t) ! 666: ! 667: PURPOSE: Allocate memory as needed by the RPC runtime library ! 668: ! 669: COMMENTS: The stubs or runtime libraries may need to allocate memory. ! 670: By convention, they call a user-specified function named ! 671: midl_user_allocate. In this application, no memory ! 672: management is needed, so a dummy function is provided. ! 673: ! 674: ****************************************************************************/ ! 675: ! 676: void __RPC_FAR * __RPC_API midl_user_allocate(size_t len) ! 677: { ! 678: UNREFERENCED_PARAMETER(len); ! 679: return(NULL); // no memory management required ! 680: } ! 681: ! 682: /**************************************************************************** ! 683: ! 684: FUNCTION: midl_user_free(void *) ! 685: ! 686: PURPOSE: Free memory as needed by the RPC runtime library ! 687: ! 688: COMMENTS: The stubs or runtime libraries may need to free memory. ! 689: By convention, they call a user-specified function named ! 690: midl_user_free. In this application, no memory allocation ! 691: is needed so a dummy function is provided. ! 692: ! 693: ****************************************************************************/ ! 694: ! 695: void __RPC_API midl_user_free(void __RPC_FAR * ptr) ! 696: { ! 697: UNREFERENCED_PARAMETER(ptr); ! 698: return; // no memory management required ! 699: } ! 700: ! 701: ! 702: /**************************************************************************** ! 703: ! 704: FUNCTION: Bind(HWND) ! 705: ! 706: PURPOSE: Make RPC API calls to bind to the server application ! 707: ! 708: COMMENTS: The binding calls are made from InitInstance() and whenever ! 709: the user changes the protocol sequence, network address, or ! 710: endpoint. If the bind operation is successful, the global ! 711: flag fBound is set to TRUE. ! 712: ! 713: The global flag fBound is used to determine whether to call ! 714: the RPC API function RpcBindingFree. ! 715: ! 716: ****************************************************************************/ ! 717: ! 718: RPC_STATUS Bind(HWND hWnd) ! 719: { ! 720: RPC_STATUS status; ! 721: char pszFail[MSGLEN]; ! 722: ! 723: if (fBound == TRUE) { // unbind only if bound ! 724: status = RpcStringFree(&pszStringBinding); // remote calls done; unbind ! 725: if (status) { ! 726: MessageBox(hWnd, "RpcStringFree failed", "RPC Error", MB_ICONSTOP); ! 727: return(status); ! 728: } ! 729: ! 730: status = RpcBindingFree(&hYield); // remote calls done; unbind ! 731: if (status) { ! 732: MessageBox(hWnd, "RpcBindingFree failed", "RPC Error", MB_ICONSTOP); ! 733: return(status); ! 734: } ! 735: ! 736: fBound = FALSE; // unbind successful; reset flag ! 737: } ! 738: ! 739: status = RpcStringBindingCompose(pszUuid, ! 740: pszProtocolSequence, ! 741: pszNetworkAddress, ! 742: pszEndpoint, ! 743: pszOptions, ! 744: &pszStringBinding); ! 745: if (status) { ! 746: sprintf(pszFail, "RpcStringBindingCompose failed: (0x%x)\nNetwork Address = %s\n", ! 747: status, pszNetworkAddress); ! 748: MessageBox(hWnd, ! 749: pszFail, ! 750: "RPC Runtime Error", ! 751: MB_ICONEXCLAMATION); ! 752: return(status); ! 753: } ! 754: ! 755: status = RpcBindingFromStringBinding(pszStringBinding, ! 756: &hYield); ! 757: if (status) { ! 758: sprintf(pszFail, "RpcBindingFromStringBinding failed: (0x%x)\nString = %s\n", ! 759: status, pszStringBinding); ! 760: MessageBox(hWnd, ! 761: pszFail, ! 762: "RPC Runtime Error", ! 763: MB_ICONEXCLAMATION); ! 764: return(status); ! 765: } ! 766: ! 767: fBound = TRUE; // bind successful; reset flag ! 768: ! 769: return(status); ! 770: } ! 771: ! 772: ! 773: /**** end yieldc.c ****/
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.