Windows NT Systems Programming

[ Home | Syllabus |Course Notes]


Remote Procedure Calls (continued).


Mandelbrot Sets

MIDL File

 

[
  uuid (87654321-4321-1234-4321-987654321CBA),
  version(1.0),
  endpoint ("ncacn_np:[\\pipe\\ccrpc]")
]
interface calcclr
{
  typedef struct
  {
    double real;
    double imag;
  } complex;

  short CalcColor([in] complex k);
}
// And the ACF file

 

[
  implicit_handle(handle_t calcclrHandle)
]
interface calcclr
{
}

Server

// mandels.cpp

#include <windows.h>
#include <iostream.h>
#include <rpc.h>
#include "ccrpc.h"
#include "memstub"

INT main(VOID)
{
  // use the protocols specified in 
  // the IDL file for this interface
  if (RpcServerUseAllProtseqsIf(1, 
    calcclr_v1_0_s_ifspec,
    NULL))
  // register the interface
  if (RpcServerRegisterIf(calcclr_v1_0_s_ifspec,
    NULL, NULL))

  // listen for and service RPC requests
  if (RpcServerListen(1, 5, FALSE))

  return(0);
}

Client

// mandelc.cpp

const double left = -1.0;
const double right = 1.0;
const double top = -1.0;
const double bottom = 1.0;

DWORD colors[64];

typedef struct
{
	WORD height;
	WORD width;
} mandelParams;

// Define the application object class
class CManApp : public CWinApp
{
public:
	virtual BOOL InitInstance();
};

// Define the edit window class
class CManWindow : public CFrameWnd
{
private:
	HANDLE threadHandle;
	BOOL running;
	BOOL initialized;
	mandelParams params;
public:
	CManWindow();
	void RunMandel();
	void SetPix(int x, int y, WORD iter);
	afx_msg void OnPaint();
	afx_msg void OnStartStop();
	afx_msg void OnExit();
	DECLARE_MESSAGE_MAP()
};

// Create an instance of the application object
CManApp manApp;

// member function used to set pixel colors
// in the window
void CManWindow::SetPix(int x, int y, WORD iter)
{
	CClientDC dc(this);
	dc.SetPixel(x, y, colors[iter]);
}

// the thread function which does the drawing // WHY in a thread?
DWORD MandelThread(mandelParams *params)
{
	double xstep, ystep;
	double x, y;
	int i,j;
	WORD iter;
	complex k;

	ystep = (double) (bottom - top) / 
		params->height;
	xstep = (double) (right - left) / 
		params->width;
	
	for (y=top, j=0; y <= bottom; y += ystep, j++)
	{
		for (x=left, i=0; x<=right; x += xstep, i++)
		{
			k.real = x;
			k.imag = y;
			RpcTryExcept
			{
				iter=CalcColor(k); // RPC
			}
			RpcExcept(1)
			{
				MessageBox(NULL,
					"Unable to call CalcColor( ).\n\Click OK and then Exit.",
					"ERROR", MB_SETFOREGROUND | 
						MB_OK | MB_ICONSTOP);
				ExitThread(1);
			}
			RpcEndExcept;

			((CManWindow *)manApp.m_pMainWnd)->
				SetPix(i, j, iter);
		}
	}
	return(0);
}

// member function used to instigate the
// drawing thread
void CManWindow::RunMandel()
{
	DWORD threadID;
	CRect r;

	GetClientRect(&r);
	params.height=r.Height();
	params.width=r.Width();

	threadHandle=CreateThread(NULL, 0,
		(LPTHREAD_START_ROUTINE) MandelThread,
		&params, 0, &threadID);

	running=TRUE;
}

// The message map
BEGIN_MESSAGE_MAP(CManWindow, CFrameWnd)
	ON_WM_PAINT()
	ON_COMMAND(IDM_STARTSTOP, OnStartStop)
	ON_COMMAND(IDM_EXIT, OnExit)
END_MESSAGE_MAP()

// Handler for the Start/Stop menu option
void CManWindow::OnStartStop()
{
	if(running)
		SuspendThread(threadHandle);
	else
		ResumeThread(threadHandle);

	running=!running;
}

// Handler for WM_PAINT messages
void CManWindow::OnPaint()
{
	ValidateRect(NULL);
	if (!initialized)
	{
		initialized=TRUE;
		RunMandel();
	}
	else
	if (running)
	{
		// stop the existing thread
		TerminateThread(threadHandle, 0);
		CloseHandle(threadHandle);
		// clear the window
		CClientDC dc(this);
		CRect r;
		GetClientRect(&r);
		dc.PatBlt(0, 0, r.Width(), r.Height(),
		WHITENESS);
		// start over again
		RunMandel();
	}
}

// Handler for the Exit menu option
void CManWindow::OnExit()
{
	SuspendThread(threadHandle);
	CloseHandle(threadHandle);
	RpcBindingFree(&calcclrHandle);
	DestroyWindow();
}

// CManWindow constructor
CManWindow::CManWindow()
{
	WORD x;
	BYTE red=0, green=0, blue=0;
	UCHAR *stringBinding;
	CHAR serverName[MAX_PATH];

	BOOL test = Create( NULL, "RPC Mandel Example",
		WS_OVERLAPPEDWINDOW,
		CRect(0,0,150,150), NULL, "MainMenu" );
	// Set up a set of colors
	for (x=0; x<64; x++)
	{
		colors[x] = RGB(red, green, blue);
		if (!(red += 64)) 
			if (!(green += 64)) 
		blue += 64;
	}
	colors[63] = RGB(255,255,255);

	if (strlen(manApp.m_lpCmdLine))
		strcpy(serverName, manApp.m_lpCmdLine);
	else
		strcpy(serverName, "\\\\.");

	RpcStringBindingCompose(NULL,
		(UCHAR *) "ncacn_np", (UCHAR *) serverName,
		(UCHAR *) "\\pipe\\ccrpc", NULL,
		&stringBinding);

	RpcBindingFromStringBinding(stringBinding,
		&calcclrHandle);

	RpcStringFree(&stringBinding);

	initialized=FALSE;
}

// Initialize the CManApp m_pMainWnd data member
BOOL CManApp::InitInstance()
{
	m_pMainWnd = new CManWindow();
	m_pMainWnd -> ShowWindow( m_nCmdShow );
	m_pMainWnd -> UpdateWindow();

	return TRUE;
}

rainbow.gif (2243 bytes)


Memstub

 

void __RPC_FAR * __RPC_API
	midl_user_allocate(size_t len)
{
	return(new(unsigned char [len]));
}

void __RPC_API midl_user_free(void __RPC_FAR * ptr)
{
	delete(ptr);
}

Improved Version

 

[
  uuid (87654329-4321-1234-4321-987654321CBA),
  version(1.0),
  endpoint ("ncacn_np:[\\pipe\\ccrpc2]")
]
interface calcline
{
  typedef struct
  {
    double real;
    double imag;
  } complex;

  void CalcLine([in] double left, 
	[in] double right,
	[in] double y, [in] long width,
	[out, size_is(width)] short line[]);
}

Running Second Version

(code is here)


Copyright chris wild 1997.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: November 03, 1997.