CLIENT.C

/**************************************************************************** 
Microsoft RPC
Copyright Microsoft Corp. 1992-1996
object call_as Example

FILE: client.c

USAGE: client

PURPOSE: Client side application of remoted custom interface

FUNCTIONS: main() - binds to server and calls remote procedure

COMMENTS: This version of the Ole2 distributed application that
prints "hello, world" (or other string) on the server
features a non-rpcable custom interface being remoted with
[call_as].

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

#define INC_OLE2
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include "callas.h" // generated by MIDL from callas.idl/.acf

// the class ID of the server exe
const
CLSID CLSID_CallAs =
{0xf9246030,0x9f33,0x11cd,{0xb2,0x3f,0x00,0xaa,0x00,0x33,0x9c,0xce}};


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

set up the following registry keys:

\Registry\Machine\Software\Classes
CLSID
{f9246030-9f33-11cd-b23f-00aa00339cce}
LocalServer32
= server.exe
{a46deb30-9f33-11cd-b23f-00aa00339cce}
InProcServer32
= callas.dll
Interface
{a46deb30-9f33-11cd-b23f-00aa00339cce}
ProxyStubClsid32
= {a46deb30-9f33-11cd-b23f-00aa00339cce}

for the server, the LocalServer32 is the out-of-process server exe
for the proxy, the InProcServer32 is the proxy dll
for the interface, the ProxyStubClsid32 is the class id of the
proxy class factory.

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

void InitializeRegistry(char *pszProxyDll, char *pszServer)
{
// the server exe CLSID
const char *pszServerKey = "{f9246030-9f33-11cd-b23f-00aa00339cce}";

// the interface UUID
const char *pszInterfaceKey = "{a46deb30-9f33-11cd-b23f-00aa00339cce}";

// the class factory CLSID ( the same as the interface UUID )
const char *pszProxyDllKey = "{a46deb30-9f33-11cd-b23f-00aa00339cce}";


LONG error = 0;
HKEY hKeyInterface; // key for ...\Classes\Interface
HKEY hKeyCLSID; // key for ...\Classes\CLSID
HKEY hKey; // current key
DWORD dwDisposition;

//Register the interfaces.

//create ...\Classes\Interface key
error = RegCreateKeyEx(
HKEY_CLASSES_ROOT,
"Interface",
0,
"REG_SZ",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
0,
&hKeyInterface,
&dwDisposition);

// create the ...\Classes\Interface\{ <interface uuid> } key
error = RegCreateKeyEx(
hKeyInterface,
pszInterfaceKey,
0,
"REG_SZ",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
0,
&hKey,
&dwDisposition);

//create ProxyStubClsid32 key under the interface
error = RegCreateKeyEx(
hKey,
"ProxyStubClsid32",
0,
"REG_SZ",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
0,
&hKey,
&dwDisposition);

//Set the class id for the PSFactoryBuffer for the interface
error = RegSetValueEx(
hKey,
"",
0,
REG_SZ,
pszProxyDllKey,
strlen(pszProxyDllKey) + 1);


//Register the classes.

//create the CLSID key
error = RegCreateKeyEx(
HKEY_CLASSES_ROOT,
"CLSID",
0,
"REG_SZ",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
0,
&hKeyCLSID,
&dwDisposition);

//create key for the server
error = RegCreateKeyEx(
hKeyCLSID,
pszServerKey,
0,
"REG_SZ",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
0,
&hKey,
&dwDisposition);

//create LocalServer32 key.
error = RegCreateKeyEx(
hKey,
"LocalServer32",
0,
"REG_SZ",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
0,
&hKey,
&dwDisposition);

//Set the server name.
error = RegSetValueEx(
hKey,
"",
0,
REG_SZ,
pszServer,
strlen(pszServer) + 1);

error = RegFlushKey(
hKey );


//create key for the proxy dll
error = RegCreateKeyEx(
hKeyCLSID,
pszProxyDllKey,
0,
"REG_SZ",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
0,
&hKey,
&dwDisposition);

//create InProcServer32 key for the proxy dll
error = RegCreateKeyEx(
hKey,
"InProcServer32",
0,
"REG_SZ",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
0,
&hKey,
&dwDisposition);

//register the proxy DLL
error = RegSetValueEx(
hKey,
"",
0,
REG_SZ,
pszProxyDll,
strlen(pszProxyDll) + 1);

error = RegFlushKey(
hKey );

// printf("waiting for registry to update OLE\n");
Sleep(1000);
}

void Test()
{
IClassFactory *pClassFactory =0;
IUnknown *punk = 0;
IHelloCallAs *pCallAs = 0;
HRESULT hr;

hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("CoInitialize failed with %lx\n", hr);
return;
}

hr = CoGetClassObject(&CLSID_CallAs, CLSCTX_LOCAL_SERVER, 0, &IID_IClassFactory, &pClassFactory);
if(FAILED(hr))
printf("CoGetClassObject failed with %lx\n", hr);
else
{
assert(pClassFactory);
hr = pClassFactory->lpVtbl->CreateInstance(pClassFactory, 0, &IID_IUnknown, &punk);
if(FAILED(hr))
printf("IClassFactory::CreateInstance failed with %lx\n", hr);
else
{
assert(punk);
hr = punk->lpVtbl->QueryInterface(punk, &IID_IHelloCallAs, &pCallAs);
if(FAILED(hr))
printf("IUnknown::QueryInterface failed with %lx\n", hr);
else
{
assert(pCallAs);
hr = pCallAs->lpVtbl->HelloProc(pCallAs, "Hello World!");
if(FAILED(hr))
printf("IHelloCallAs::HelloProc failed with %lx\n", hr);
else
printf("IHelloCallAs::HelloProc succeeded");

pCallAs->lpVtbl->Release(pCallAs);
pCallAs = 0;
}
punk->lpVtbl->Release(punk);
punk = 0;
}
pClassFactory->lpVtbl->Release(pClassFactory);
pClassFactory = 0;
}
CoUninitialize();
}

void TestDll()
{
// the dll name of the proxy dll
const char *pszProxyDllName = "callas.dll";

char szDrive[_MAX_DRIVE];
char szDirectory[_MAX_DIR];
char szFileName[_MAX_FNAME];

char szClient[_MAX_PATH];
char szProxyDll[_MAX_PATH];
char szServer[_MAX_PATH];

GetModuleFileName(0, szClient, _MAX_PATH);
_splitpath(szClient, szDrive, szDirectory, szFileName, NULL);

//Get the full path name of the server.
sprintf(szServer, "%s%sserver.exe", szDrive, szDirectory);

//Get the full path name of the proxy dll.
sprintf(szProxyDll, "%s%s%s", szDrive, szDirectory, pszProxyDllName);

printf("Testing Dll\n");
InitializeRegistry(szProxyDll, szServer);

Test();
}


void __cdecl main(int argc, char *argv[])
{
TestDll();
}