YIELDC.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:26k
源码类别:
Windows编程
开发平台:
Visual C++
- /****************************************************************************
- Microsoft RPC Version 2.0
- Copyright Microsoft Corp. 1992, 1993, 1994- 1996
- yield Example
- FILE: yieldp.c
- PURPOSE: RPC sample Windows client
- Based on Win 3.x SDK Generic template for Windows applications
- FUNCTIONS: WinMain() - same as Windows generic example
- InitApplication() - same as Windows generic example
- InitInstance() - same as Windows generic example
- MainWndProc() - processes messages
- About() - processes messages for "About" dialog box
- BindInfo() - processes messages for "Bind" dialog box
- WaitInfo() - processes messages for "Wait" dialog box
- YieldInfo() - processes messages for "Yield" dialog box
- Bind() - calls the RPC API functions
- midl_user_allocate() - memory allocation function needed by RPC
- midl_user_free() - memory free function needed by RPC
- COMMENTS: This sample application demonstrates the yield capability
- of the Microsoft RPC for Microsoft Windows 3.x using the
- RpcWinSetYieldInfo API function.
- By yielding, you can prevent your distributed application
- from blocking during lengthy remote procedure calls.
- This sample is based on the Win 3.x generic example. To focus
- attention on the RPC-related aspects of this application,
- many comments from the Windows-only version are removed.
- ****************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <windows.h>
- #include <windowsx.h>
- #include "yield.h" // header file generated by MIDL compiler
- #include "yieldc.h" // client-specific header file
- /* global data */
- unsigned char pszProtocolSequence[MAXPROTSEQ+1];
- unsigned char pszNetworkAddress[NETLEN+1];
- unsigned char pszEndpoint[PATHLEN+1];
- unsigned char * pszUuid = NULL;
- unsigned char * pszOptions = NULL;
- unsigned char * pszStringBinding = NULL;
- int fBound = FALSE; // flag indicates whether client is bound to server
- int fCancel = FALSE; // flag indicates whether the user has chosen CANCEL
- unsigned int cWaitSec; // parameter to remote procedure Sleep()
- int fCustomYield; // TRUE = custom yield, FALSE = standard yield
- DWORD dwOtherInfo; // depends on the value of fCustomYield
- HANDLE hInst; // current instance
- HCURSOR hHourGlass; // during calls to RPC API functions
- HWND hWndMain; // main handle
- /****************************************************************************
- FUNCTION: WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
- PURPOSE: Calls initialization function, processes message loop
- COMMENTS: Windows recognizes this function by name as the initial
- entry point for the program. This function calls the
- application initialization routine, if no other instance
- of the program is running, and always calls the instance
- initialization routine. It then executes a message
- retrieval and dispatch loop that is the top-level control
- structure for the remainder of execution. The loop is
- terminated when a WM_QUIT message is received, at which
- time this function exits the application instance by
- returning the value passed by PostQuitMessage().
- If this function must abort before entering the message
- loop, it returns the conventional value NULL.
- ****************************************************************************/
- int WINAPI WinMain(HINSTANCE hInstance, // current instance
- HINSTANCE hPrevInstance, // previous instance
- LPSTR lpCmdLine, // command line
- int nCmdShow) // show-window type
- {
- MSG msg;
- UNREFERENCED_PARAMETER(lpCmdLine);
- if (! hPrevInstance) // no other instances of app running
- if (! InitApplication(hInstance)) // initialize shared things
- return(FALSE); // exit if unable to initialize
- /* Perform initializations that apply to a specific instance */
- if (! InitInstance(hInstance, nCmdShow))
- return(FALSE);
- /* Acquire and dispatch messages until a WM_QUIT message is received */
- while (GetMessage(&msg, // message structure
- (HWND)NULL, // handle of window receiving the message
- 0, // lowest message to examine
- 0)) // highest message to examine
- {
- TranslateMessage(&msg); // translate virtual key codes
- DispatchMessage(&msg); // dispatche message to window
- }
- return(msg.wParam); // return the value from PostQuitMessage
- }
- /****************************************************************************
- FUNCTION: InitApplication(HANDLE)
- PURPOSE: Initializes window data and registers window class
- COMMENTS: This function is called at initialization time only if
- no other instances of the application are running. This
- function performs initialization tasks that can be done
- once for any number of running instances.
- In this case, we initialize a window class by filling out
- a data structure of type WNDCLASS and calling the Windows
- RegisterClass() function. Since all instances of this
- application use the same window class, we only need to do
- this when the first instance is initialized.
- ****************************************************************************/
- BOOL InitApplication(HANDLE hInstance) // current instance
- {
- WNDCLASS wc;
- /* Fill in the window class structure with parameters that */
- /* describe the main window */
- wc.style = 0;
- wc.lpfnWndProc = (WNDPROC) MainWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon(hInstance, "YieldIcon");
- wc.hCursor = LoadCursor((HANDLE) NULL, IDC_ARROW);
- wc.hbrBackground = GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = "GenericMenu";
- wc.lpszClassName = "GenericWClass";
- /* Register the window class and return success/failure code */
- return(RegisterClass(&wc));
- }
- /****************************************************************************
- FUNCTION: InitInstance(HANDLE, int)
- PURPOSE: Saves instance handle and creates main window
- COMMENTS: This function is called at initialization time for every
- instance of this application. This function performs
- initialization tasks that cannot be shared by multiple
- instances.
- In this case, we save the instance handle in a global
- variable and create and display the main program window.
- ****************************************************************************/
- BOOL InitInstance(HANDLE hInstance, // current instance
- int nCmdShow) // param for first ShowWindow() call
- {
- HWND hWnd;
- /* Save the instance handle in global variable, which will be used */
- /* in many subsequence calls from this application to Windows */
- hInst = hInstance;
- hHourGlass = LoadCursor((HANDLE) NULL, IDC_WAIT);
- /* Create a main window for this application instance */
- hWnd = CreateWindow("GenericWClass",
- "RPC Sample Application",
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- (HWND) NULL,
- (HMENU) NULL,
- hInstance,
- (LPVOID) NULL
- );
- /* If the window cannot be created, return "failure" */
- if (!hWnd)
- return(FALSE);
- /* Initialize RPC binding data */
- strcpy(pszProtocolSequence, DEFAULT_PROT_SEQ);
- strcpy(pszEndpoint, DEFAULT_ENDPOINT);
- pszNetworkAddress[0] = ' ';
- /* Bind client to server */
- fBound = FALSE;
- /* Initialize the parameter to the remote procedure Sleep() */
- cWaitSec = DEFAULT_WAIT;
- /* Initialize the parameters to RpcWinSetYieldInfo() */
- fCustomYield = FALSE; // FALSE = std yield
- dwOtherInfo = (DWORD) NULL; // NULL = RPC-supplied dialog box
- RpcWinSetYieldInfo(hWnd, // handle
- fCustomYield, // standard or custom yield?
- WM_RPC_YIELD_MESSAGE, // 0 = no message is posted
- dwOtherInfo); // depends on fCustomYield value
- /* Make the window visible, update its client area, and return "success" */
- ShowWindow(hWnd, nCmdShow);
- UpdateWindow(hWnd);
- return(TRUE);
- }
- /****************************************************************************
- FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)
- PURPOSE: Processes messages
- MESSAGES: WM_COMMAND - application menu (About dialog box)
- WM_DESTROY - destroy window
- COMMENTS: Based on the Windows generic sample.
- Several new menu items are added to demonstrate the
- RpcWinSetYieldInfo function.
- The "Bind" menu is associated with the "GetBindInfo"
- dialog box function. GetBindInfo allows the user to
- set the parameters for the RpcStringBindingCompose and
- RpcBindingFromStringBinding functions. A flag, fBound,
- keeps track of whether the client application is bound
- to a remote server. If this flag indicates that the
- client application is not bound to the server, it calls
- the "Bind" utility function to call the
- RPC API functions that establish the binding.
- The "Yield" menu is associated with the "GetYieldInfo"
- dialog box function. GetYieldInfo allows the user to
- select the yielding model: standard yield with an
- RPC run-time library-supplied dialog box; standard
- yield with a user-supplied dialog box; or custom yield.
- These methods are described in detail in the documentation
- for the RpcWinSetYieldInfo function.
- ****************************************************************************/
- long APIENTRY MainWndProc(HWND hWnd, // window handle
- UINT message, // type of message
- WPARAM wParam, // additional information
- LPARAM lParam // additional information
- )
- {
- DLGPROC lpProc; // pointer to the dialog box function
- /* copy the window handle for CustomYield() */
- hWndMain = hWnd;
- switch (message) {
- case WM_CREATE:
- /* Win 3.x is client-only; force user to specify server */
- PostMessage(hWnd, WM_COMMAND, IDM_BIND, 0L);
- break;
- case WM_COMMAND:
- switch (wParam) {
- case IDM_ABOUT:
- lpProc = MakeProcInstance(About, hInst);
- DialogBox(hInst,
- "AboutBox",
- hWnd,
- lpProc);
- FreeProcInstance(lpProc);
- break;
- case IDM_BIND:
- lpProc = MakeProcInstance(GetBindInfo, hInst);
- DialogBox(hInst,
- "BindBox",
- hWnd,
- lpProc);
- FreeProcInstance(lpProc);
- break;
- case IDM_WAIT:
- lpProc = MakeProcInstance(GetWaitInfo, hInst);
- DialogBox(hInst,
- "WaitBox",
- hWnd,
- lpProc);
- FreeProcInstance(lpProc);
- break;
- case IDM_YIELD:
- lpProc = MakeProcInstance(GetYieldInfo, hInst);
- DialogBox(hInst,
- "YieldBox",
- hWnd,
- lpProc);
- FreeProcInstance(lpProc);
- break;
- case IDM_EXIT:
- DestroyWindow(hWnd);
- if (fBound == TRUE) {
- RpcTryExcept {
- Shutdown(); // shut down the server
- }
- RpcExcept(1) {
- MessageBox(hWnd,
- EXCEPT_MSG,
- "Remote Procedure Call",
- MB_ICONINFORMATION);
- }
- RpcEndExcept
- }
- break;
- default:
- return(DefWindowProc(hWnd, message, wParam, lParam));
- }
- break;
- case WM_RPC_YIELD_MESSAGE: // signals beginning or end of yield period
- if (wParam == 0)
- SetWindowText(hWnd, YIELD_END_MSG);
- else if (wParam == 1)
- SetWindowText(hWnd, YIELD_START_MSG);
- break;
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
- default: // passes it on if unprocessed
- return(DefWindowProc(hWnd, message, wParam, lParam));
- }
- return(0L);
- }
- /****************************************************************************
- FUNCTION: About(HWND, unsigned, WORD, LONG)
- PURPOSE: "About" dialog box
- COMMENTS:
- ****************************************************************************/
- BOOL APIENTRY About(HWND hDlg,
- UINT message,
- UINT wParam,
- LONG lParam)
- {
- UNREFERENCED_PARAMETER(lParam);
- switch (message) {
- case WM_INITDIALOG:
- return(TRUE);
- case WM_COMMAND:
- if (wParam == IDOK || wParam == IDCANCEL) {
- EndDialog(hDlg, TRUE);
- return(TRUE);
- }
- break;
- }
- return(FALSE);
- }
- /****************************************************************************
- FUNCTION: GetBindInfo(HWND, unsigned, WORD, LONG)
- PURPOSE: Collect components of string binding;
- protocol sequence, network address, endpoint
- COMMENTS:
- ****************************************************************************/
- BOOL APIENTRY GetBindInfo(HWND hDlg,
- UINT message,
- UINT wParam,
- LONG lParam)
- {
- HCURSOR hOld;
- UNREFERENCED_PARAMETER(lParam);
- switch (message) {
- case WM_INITDIALOG: // fill in dialog's edit boxes
- SetDlgItemText(hDlg, IDD_ENDPOINT, pszEndpoint);
- SetDlgItemText(hDlg, IDD_PROT_SEQ, pszProtocolSequence);
- SetDlgItemText(hDlg, IDD_NET_ADDR, pszNetworkAddress);
- return(TRUE);
- case WM_COMMAND:
- switch(wParam) {
- case IDCANCEL:
- EndDialog(hDlg, FALSE);
- return(TRUE);
- case IDOK:
- GetDlgItemText(hDlg, IDD_PROT_SEQ, pszProtocolSequence, MAXPROTSEQ);
- GetDlgItemText(hDlg, IDD_ENDPOINT, pszEndpoint, PATHLEN);
- GetDlgItemText(hDlg, IDD_NET_ADDR, pszNetworkAddress, NETLEN);
- hOld = SetCursor(hHourGlass);
- if (Bind(hDlg) != RPC_S_OK) { // bind to server
- EndDialog(hDlg, FALSE);
- return(FALSE);
- }
- SetCursor(hOld);
- EndDialog(hDlg, TRUE);
- return(TRUE);
- }
- }
- return(FALSE);
- }
- /****************************************************************************
- FUNCTION: GetWaitInfo(HWND, unsigned, WORD, LONG)
- PURPOSE: Prompt user for the parameter to the remote call,
- then make the remote procedure call.
- COMMENTS:
- ****************************************************************************/
- BOOL APIENTRY GetWaitInfo(HWND hDlg, // window handle of the dialog box
- UINT message, // type of message
- UINT wParam, // message-specific information
- LONG lParam)
- {
- int fError;
- UNREFERENCED_PARAMETER(lParam);
- switch (message) {
- case WM_INITDIALOG:
- SetDlgItemInt(hDlg, IDD_WAITTIME, cWaitSec, FALSE);
- return(TRUE);
- case WM_COMMAND:
- switch(wParam) {
- case IDCANCEL:
- EndDialog(hDlg, FALSE);
- fCancel = TRUE;
- return(TRUE);
- case IDOK:
- cWaitSec = GetDlgItemInt(hDlg, IDD_WAITTIME, &fError, FALSE);
- if (cWaitSec <= 0) // check for valid entry
- cWaitSec = DEFAULT_WAIT; // set an appropriate value
- RpcTryExcept {
- YieldProc(cWaitSec); // make the remote procedure call
- }
- RpcExcept(1) {
- unsigned long ulCode;
- char pszFail[MSGLEN];
- ulCode = RpcExceptionCode();
- if (ulCode != RPC_S_CALL_FAILED) {
- sprintf(pszFail, "%s (0x%x)n", EXCEPT_MSG, ulCode);
- MessageBox(hDlg,
- pszFail,
- "Remote Procedure Call",
- MB_ICONINFORMATION);
- }
- }
- RpcEndExcept
- EndDialog(hDlg, TRUE);
- return(TRUE);
- }
- }
- return(FALSE);
- }
- /****************************************************************************
- FUNCTION: CustomYield(void)
- PURPOSE: Message handler during custom yield
- MESSAGES: WM_RPC_YIELD_MESSAGE - end of yield message
- WM_COMMAND - Input received
- COMMENTS: The callback function must retrieve messages from the
- message queue.
- The function must return TRUE when the RPC operation
- has completed. The function must return FALSE when the
- user cancels the RPC operation.
- ****************************************************************************/
- BOOL FAR PASCAL __export CustomYield(void)
- {
- MSG msg;
- fCancel = FALSE;
- while (TRUE) { // message processing
- GetMessage(&msg, (HWND)NULL, 0, 0);
- if (msg.message == WM_RPC_YIELD_MESSAGE)
- return(TRUE); // RPC operation is complete
- if (fCancel == TRUE)
- return(FALSE);
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return(TRUE);
- }
- /****************************************************************************
- FUNCTION: GetYieldInfo(HWND, unsigned, WORD, LONG)
- PURPOSE: Check radio buttons to see which yield method
- was selected by the user, then set the parameters
- to RpcWinSetYieldInfo and call RpcWinSetYieldInfo.
- COMMENTS:
- ****************************************************************************/
- BOOL APIENTRY GetYieldInfo(HWND hDlg, // window handle of the dialog box
- UINT message, // type of message
- UINT wParam, // message-specific information
- LONG lParam)
- {
- int fCheck;
- UNREFERENCED_PARAMETER(lParam);
- switch (message) {
- case WM_INITDIALOG: // message: initialize dialog box
- if (fCustomYield)
- CheckRadioButton(hDlg, IDD_STD_RPC, IDD_CUSTOM, IDD_CUSTOM);
- else if (dwOtherInfo != (DWORD) NULL)
- CheckRadioButton(hDlg, IDD_STD_RPC, IDD_CUSTOM, IDD_STD_USER);
- else
- CheckRadioButton(hDlg, IDD_STD_RPC, IDD_CUSTOM, IDD_STD_RPC);
- return(TRUE);
- case WM_COMMAND: // message: received a command
- switch(wParam) {
- case IDCANCEL: // System menu close command?
- EndDialog(hDlg, FALSE);
- return(TRUE);
- case IDOK:
- /* which radio button is checked: Custom yield? */
- fCheck = (int) SendDlgItemMessage(hDlg,
- IDD_CUSTOM,
- BM_GETCHECK,
- 0,
- 0);
- if (fCheck == TRUE) {
- fCustomYield = TRUE;
- dwOtherInfo = (DWORD) MakeProcInstance(CustomYield, hInst);
- }
- else {
- fCustomYield = FALSE;
- /* Standard yield, user-supplied dialog? */
- fCheck = (int) SendDlgItemMessage(hDlg,
- IDD_STD_USER,
- BM_GETCHECK,
- 0,
- 0);
- if (fCheck == TRUE) {
- HRSRC hrsrc;
- hrsrc = FindResource(hInst,
- "USERYIELDBOX",
- RT_DIALOG);
- dwOtherInfo = LoadResource(hInst, hrsrc);
- }
- else {
- /* Assume standard-yield, rpc-supplied dialog box */
- dwOtherInfo = (DWORD) NULL;
- }
- }
- RpcWinSetYieldInfo(hWndMain,
- fCustomYield,
- WM_RPC_YIELD_MESSAGE,
- dwOtherInfo);
- EndDialog(hDlg, TRUE);
- return(TRUE);
- }
- }
- return(FALSE);
- }
- /****************************************************************************
- FUNCTION: midl_user_allocate(size_t)
- PURPOSE: Allocate memory as needed by the RPC runtime library
- COMMENTS: The stubs or runtime libraries may need to allocate memory.
- By convention, they call a user-specified function named
- midl_user_allocate. In this application, no memory
- management is needed, so a dummy function is provided.
- ****************************************************************************/
- void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
- {
- UNREFERENCED_PARAMETER(len);
- return(NULL); // no memory management required
- }
- /****************************************************************************
- FUNCTION: midl_user_free(void *)
- PURPOSE: Free memory as needed by the RPC runtime library
- COMMENTS: The stubs or runtime libraries may need to free memory.
- By convention, they call a user-specified function named
- midl_user_free. In this application, no memory allocation
- is needed so a dummy function is provided.
- ****************************************************************************/
- void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
- {
- UNREFERENCED_PARAMETER(ptr);
- return; // no memory management required
- }
- /****************************************************************************
- FUNCTION: Bind(HWND)
- PURPOSE: Make RPC API calls to bind to the server application
- COMMENTS: The binding calls are made from InitInstance() and whenever
- the user changes the protocol sequence, network address, or
- endpoint. If the bind operation is successful, the global
- flag fBound is set to TRUE.
- The global flag fBound is used to determine whether to call
- the RPC API function RpcBindingFree.
- ****************************************************************************/
- RPC_STATUS Bind(HWND hWnd)
- {
- RPC_STATUS status;
- char pszFail[MSGLEN];
- if (fBound == TRUE) { // unbind only if bound
- status = RpcStringFree(&pszStringBinding); // remote calls done; unbind
- if (status) {
- MessageBox(hWnd, "RpcStringFree failed", "RPC Error", MB_ICONSTOP);
- return(status);
- }
- status = RpcBindingFree(&hYield); // remote calls done; unbind
- if (status) {
- MessageBox(hWnd, "RpcBindingFree failed", "RPC Error", MB_ICONSTOP);
- return(status);
- }
- fBound = FALSE; // unbind successful; reset flag
- }
- status = RpcStringBindingCompose(pszUuid,
- pszProtocolSequence,
- pszNetworkAddress,
- pszEndpoint,
- pszOptions,
- &pszStringBinding);
- if (status) {
- sprintf(pszFail, "RpcStringBindingCompose failed: (0x%x)nNetwork Address = %sn",
- status, pszNetworkAddress);
- MessageBox(hWnd,
- pszFail,
- "RPC Runtime Error",
- MB_ICONEXCLAMATION);
- return(status);
- }
- status = RpcBindingFromStringBinding(pszStringBinding,
- &hYield);
- if (status) {
- sprintf(pszFail, "RpcBindingFromStringBinding failed: (0x%x)nString = %sn",
- status, pszStringBinding);
- MessageBox(hWnd,
- pszFail,
- "RPC Runtime Error",
- MB_ICONEXCLAMATION);
- return(status);
- }
- fBound = TRUE; // bind successful; reset flag
- return(status);
- }
- /**** end yieldc.c ****/