WHELLOC.C

/**************************************************************************** 
Microsoft RPC Version 2.0
Copyright Microsoft Corp. 1992, 1993, 1994- 1996
whello Example

FILE: whelloc.c

PURPOSE: RPC sample Windows client
Based on Win 3.x SDK Generic template for Windows applications

FUNCTIONS: WinMain() - call initialization function,
process message loop
InitApplication() - initializ window data and register window
InitInstance() - save instance handle and create main window
MainWndProc() - process messages

About() - process messages for "About" dialog box
Server() - process messages for "Server" dialog box
Endpoint() - process messages for "Endpoint" dialog box
Send() - process messages for "Send" dialog box;
sends on OK

midl_user_allocate() - memory allocation function needed by RPC
midl_user_free() - memory free function needed by RPC

COMMENTS: Windows version of the "Hello, world" example.

Windows can have several copies of your application
running at the same time. The variable hInst keeps
track of which instance the application is so that
processing will be to the correct window.

****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <windowsx.h> // select between win16 or win32
#include <string.h>
#include "whello.h" // header file generated by MIDL compiler
#include "whelloc.h" // client-specific header file

/* global data */

unsigned char pszProtocolSequence[MAXPROTSEQ];
unsigned char pszNetworkAddress[UNCLEN+1];
unsigned char pszEndpoint[PATHLEN+1];
unsigned char * pszUuid = NULL;
unsigned char * pszOptions = NULL;
unsigned char * pszStringBinding = NULL;
unsigned char pszString[MSGLEN];

int fBound = FALSE; // flag indicates whether client bound to server

HANDLE hInst; // current instance
HCURSOR hHourGlass; // during calls to RPC API functions


/****************************************************************************

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 (open/icon)
{
MSG msg;

UNREFERENCED_PARAMETER(lpCmdLine);

if (!hPrevInstance) // Other instances of app running?
if (!InitApplication(hInstance)) // Initialize shared things
return(FALSE); // Exits 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); // Translates virtual key codes
DispatchMessage(&msg); // Dispatches message to window
}

return(msg.wParam); // Returns 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 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, "HelloIcon");
wc.hCursor = LoadCursor(0, 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 static
variable and create and display the main program window.

****************************************************************************/

BOOL InitInstance(HANDLE hInstance, // Current instance identifier.
int nCmdShow) // Param for first ShowWindow() call.
{
HWND hWnd; // Main window handle.

/* Save the instance handle in static variable, which will be used in */
/* many subsequence calls from this application to Windows. */
hInst = hInstance;
hHourGlass = LoadCursor(0, IDC_WAIT);

/* Create a main window for this application instance. */
hWnd = CreateWindow("GenericWClass", // See RegisterClass() call.
"RPC Sample Application", // Text for window title bar.
WS_OVERLAPPEDWINDOW, // Window style.
CW_USEDEFAULT, // Default horizontal position.
CW_USEDEFAULT, // Default vertical position.
CW_USEDEFAULT, // Default width.
CW_USEDEFAULT, // Default height.
(HWND) NULL, // Overlapped windows have no parent.
(HMENU) NULL, // Use the window class menu.
hInstance, // This instance owns this window.
(LPVOID) NULL // Pointer not needed.
);

/* If window could not be created, return "failure" */
if (!hWnd)
return(FALSE);

/* Initialize RPC binding data */
strcpy(pszProtocolSequence, DEFAULT_PROT_SEQ);
strcpy(pszEndpoint, DEFAULT_ENDPOINT);
pszNetworkAddress[0] = '\0';
strcpy(pszString, DEFAULT_MESSAGE);

/* Make the window visible; update its client area; and return "success" */
ShowWindow(hWnd, nCmdShow); // Show the window
UpdateWindow(hWnd); // Send WM_PAINT message

return(TRUE); // Return the value from PostQuitMessage
}


/****************************************************************************

FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)

PURPOSE: Processes messages

MESSAGES: WM_COMMAND - application menu (About dialog box)
WM_DESTROY - destroy window

COMMENTS: To process the IDM_ABOUT message, call MakeProcInstance()
to get the current instance address of the About() function.
Then call Dialog box which will create the box according to
the information in your generic.rc file and turn control
over to the About() function. When it returns, free the
intance address.

****************************************************************************/

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

switch (message) {

case WM_CREATE:

#ifdef WIN16
RpcWinSetYieldInfo (hWnd, FALSE, 0, 0L); // To make TCP/IP happy
#else
PostMessage(hWnd, WM_COMMAND, IDM_BIND, 0L); // bind to server
#endif
break;

case WM_COMMAND: // message: command from application menu
switch (wParam) {

case IDM_BIND:
if (Bind(hWnd) != RPC_S_OK)
PostMessage(hWnd, WM_DESTROY, 0, 0L);
break;

case IDM_ABOUT:
lpProc = MakeProcInstance(About, hInst);
DialogBox(hInst, // current instance
"AboutBox", // resource to use
hWnd, // parent handle
lpProc); // About() instance address
FreeProcInstance(lpProc);
break;

case IDM_PROTSEQ:
lpProc = MakeProcInstance(Protseq, hInst);
DialogBox(hInst, // current instance
"ProtseqBox", // resource to use
hWnd, // parent handle
lpProc); // Server instance address
FreeProcInstance(lpProc);
break;

case IDM_SERVER:
lpProc = MakeProcInstance(Server, hInst);
DialogBox(hInst, // current instance
"ServerBox", // resource to use
hWnd, // parent handle
lpProc); // Server instance address
FreeProcInstance(lpProc);
break;

case IDM_ENDPOINT:
lpProc = MakeProcInstance(Endpoint, hInst);
DialogBox(hInst, // current instance
"EndpointBox",// resource to use
hWnd, // parent handle
lpProc); // Server instance address
FreeProcInstance(lpProc);
break;

case IDM_SEND:
lpProc = MakeProcInstance(Send, hInst);
DialogBox(hInst, // current instance
"SendBox", // resource to use
hWnd, // parent handle
lpProc); // Server instance address
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: // Let Windows process it
return(DefWindowProc(hWnd, message, wParam, lParam));

}
break;

case WM_DESTROY: // message: window being destroyed
PostQuitMessage(0);
break;

default: // Passes it on if unprocessed
return(DefWindowProc(hWnd, message, wParam, lParam));

}

return(0);
}


/****************************************************************************

FUNCTION: Protseq(HWND, unsigned, WORD, LONG)

PURPOSE: Processes messages for "Protseq" dialog box

MESSAGES: WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received

COMMENTS: No initialization is needed for this particular dialog box,
but TRUE must be returned to Windows.

Wait for user to click on "Ok" button, then close the dialog box.

****************************************************************************/
BOOL APIENTRY Protseq(HWND hDlg, // window handle of the dialog box
UINT message, // type of message
UINT wParam, // message-specific information
LONG lParam)
{

UNREFERENCED_PARAMETER(lParam);

switch (message) {

case WM_INITDIALOG: // message: initialize dialog box
SetDlgItemText((HANDLE)hDlg, IDD_PROTSEQNAME, pszProtocolSequence);
return(TRUE);

case WM_COMMAND: // message: received a command
switch(wParam) {

case IDCANCEL: // System menu close command?
EndDialog(hDlg, FALSE);
return(TRUE);

case IDOK: // "OK" box selected?
GetDlgItemText(hDlg, IDD_PROTSEQNAME, pszProtocolSequence, MAXPROTSEQ);

if (Bind(hDlg) != RPC_S_OK) {
EndDialog(hDlg, FALSE);
return(FALSE);
}

EndDialog(hDlg, TRUE);
return(TRUE);

}

}

return(FALSE); // Didn't process a message
}


/****************************************************************************

FUNCTION: Server(HWND, unsigned, WORD, LONG)

PURPOSE: Processes messages for "Server" dialog box

MESSAGES: WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received

COMMENTS: No initialization is needed for this particular dialog box,
but TRUE must be returned to Windows.

Wait for user to click on "Ok" button, then close the dialog box.

****************************************************************************/

BOOL APIENTRY Server(HWND hDlg, // window handle of the dialog box
UINT message, // type of message
UINT wParam, // message-specific information
LONG lParam)
{
HCURSOR hOld;

UNREFERENCED_PARAMETER(lParam);

switch (message) {

case WM_INITDIALOG: // message: initialize dialog box
SetDlgItemText((HANDLE)hDlg, IDD_SERVERNAME, pszNetworkAddress);
return(TRUE);

case WM_COMMAND: // message: received a command
switch(wParam) {

case IDCANCEL: // System menu close command?
EndDialog(hDlg, FALSE);
return(TRUE);

case IDOK: // "OK" box selected?
GetDlgItemText(hDlg, IDD_SERVERNAME, pszNetworkAddress, UNCLEN);

hOld = SetCursor(hHourGlass);
if (Bind(hDlg) != RPC_S_OK) {
EndDialog(hDlg, FALSE);
return(FALSE);
}

SetCursor(hOld);
EndDialog(hDlg, TRUE);
return(TRUE);

}

}

return(FALSE); // Didn't process a message
}


/****************************************************************************

FUNCTION: About(HWND, unsigned, WORD, LONG)

PURPOSE: Processes messages for "About" dialog box

MESSAGES: WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received

COMMENTS: No initialization is needed for this particular dialog box,
but TRUE must be returned to Windows.

Wait for user to click on "Ok" button, then close the dialog box.

****************************************************************************/

BOOL APIENTRY About(HWND hDlg, // window handle of the dialog box
UINT message, // type of message
UINT wParam, // message-specific information
LONG lParam)
{
UNREFERENCED_PARAMETER(lParam);

switch (message) {

case WM_INITDIALOG: // message: initialize dialog box
return(TRUE);

case WM_COMMAND: // message: received a command
if (wParam == IDOK || wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return(TRUE);
}
break;

}

return(FALSE); // Didn't process a message
}


/****************************************************************************

FUNCTION: Endpoint(HWND, unsigned, WORD, LONG)

PURPOSE: Processes messages for "Endpoint" dialog box

MESSAGES: WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received

COMMENTS: No initialization is needed for this particular dialog box,
but TRUE must be returned to Windows.

Wait for user to click on "Ok" button, then close the dialog box.

****************************************************************************/

BOOL APIENTRY Endpoint(HWND hDlg, // window handle of the dialog box
UINT message, // type of message
UINT wParam, // message-specific information
LONG lParam)
{
HCURSOR hOld;

UNREFERENCED_PARAMETER(lParam);

switch (message) {

case WM_INITDIALOG: // message: initialize dialog box
SetDlgItemText(hDlg, IDD_ENDPOINTNAME, pszEndpoint);
return(TRUE);

case WM_COMMAND: // message: received a command
switch(wParam) {

case IDCANCEL:
EndDialog(hDlg, FALSE);
return(TRUE);

case IDOK:
GetDlgItemText(hDlg, IDD_ENDPOINTNAME, pszEndpoint, PATHLEN);

hOld = SetCursor(hHourGlass);
if (Bind(hDlg) != RPC_S_OK) {
EndDialog(hDlg, FALSE);
return(FALSE);
}

SetCursor(hOld);
EndDialog(hDlg, TRUE);
return(TRUE);

}

}

return(FALSE); // Didn't process a message
}


/****************************************************************************

FUNCTION: Send(HWND, unsigned, WORD, LONG)

PURPOSE: Processes messages for "Send" dialog box

MESSAGES: WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received

COMMENTS: No initialization is needed for this particular dialog box,
but TRUE must be returned to Windows.

Wait for user to click on "Ok" button, then close the dialog box.

****************************************************************************/

BOOL APIENTRY Send(HWND hDlg, // window handle of the dialog box
UINT message, // type of message
UINT wParam, // message-specific information
LONG lParam)
{
UNREFERENCED_PARAMETER(lParam);

switch (message) {

case WM_INITDIALOG: // message: initialize dialog box
SetDlgItemText(hDlg, IDD_MESSAGE, pszString);
return(TRUE);

case WM_COMMAND: // message: received a command
switch(wParam) {

case IDCANCEL:
EndDialog(hDlg, FALSE);
return(TRUE);

case IDOK:
GetDlgItemText(hDlg, IDD_MESSAGE, pszString, MSGLEN);

RpcTryExcept {
HelloProc(pszString); // make call with user message
}
RpcExcept(1) {
char pszFail[MSGLEN];

sprintf(pszFail, "%s (0x%x)\n", EXCEPT_MSG, RpcExceptionCode());
MessageBox(hDlg,
pszFail,
"Remote Procedure Call",
MB_ICONINFORMATION);
}
RpcEndExcept

EndDialog(hDlg, TRUE);
return(TRUE);

}

}

return(FALSE); // Didn't process a message
}


/****************************************************************************

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_API 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_API 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 server name 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);
if (status) {
MessageBox(hWnd, "RpcStringFree failed", "RPC Error", MB_ICONSTOP);
return(status);
}

status = RpcBindingFree(&hWHello);
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 = %s\n",
status, pszNetworkAddress);
MessageBox(hWnd,
pszFail,
"RPC Runtime Error",
MB_ICONEXCLAMATION);
return(status);
}

status = RpcBindingFromStringBinding(pszStringBinding,
&hWHello);
if (status) {
sprintf(pszFail, "RpcBindingFromStringBinding failed: (0x%x)\nString = %s\n",
status, pszStringBinding);
MessageBox(hWnd,
pszFail,
"RPC Runtime Error",
MB_ICONEXCLAMATION);
return(status);
}

fBound = TRUE; // bind successful; reset flag

return(status);
}

/**** end whelloc.c ****/