SCLIENT.CPP

// =========================================================================== 
// File: S C L I E N T . C P P
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Description:
//
// This is the client-portion of the SIMPLE Distributed COM sample. This
// application uses the CLSID_SimpleObject class implemented by the SSERVER.CPP
// module. Pass the machine-name to instantiate the object on, or pass no
// arguments to instantiate the object on the same machine. See the comments
// in SSERVER.CPP for further details.
//
// The purpose of this sample is to demonstrate what is minimally required
// to use a COM object, whether it runs on the same machine or on a different
// machine.
//
// Instructions:
//
// To use this sample:
// * build it using the NMAKE command. NMAKE will create SSERVER.EXE and
// SCLIENT.EXE.
// * install the SSERVER.EXE on the current machine or on a remote machine
// according to the installation instructions found in SSERVER.CPP.
// * run SCLIENT.EXE. use no command-line arguments to instantiate the object
// on the current machine. use a single command-line argument of the remote
// machine-name (UNC or DNS) to instantiate the object on a remote machine.
// * SCLIENT.EXE displays some simple information about the calls it is
// making on the object.
//
// Copyright 1996 Microsoft Corporation. All Rights Reserved.
// ===========================================================================

// %%Includes: ---------------------------------------------------------------
#define INC_OLE2
#include <stdio.h>
#include <windows.h>
#include <initguid.h>
#include <tchar.h>
#include <conio.h>

// %%GUIDs: ------------------------------------------------------------------
DEFINE_GUID(CLSID_SimpleObject, 0x5e9ddec7, 0x5767, 0x11cf, 0xbe, 0xab, 0x0, 0xaa, 0x0, 0x6c, 0x36, 0x6);

// %%Constants: --------------------------------------------------------------
const ULONG cbDefault = 4096; // default # of bytes to Read/Write

// ---------------------------------------------------------------------------
// %%Function: Message
//
// Formats and displays a message to the console.
// ---------------------------------------------------------------------------
void
Message(LPTSTR szPrefix, HRESULT hr)
{
LPTSTR szMessage;

if (hr == S_OK)
{
wprintf(szPrefix);
return;
}

if (HRESULT_FACILITY(hr) == FACILITY_WINDOWS)
hr = HRESULT_CODE(hr);

FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language
(LPTSTR)&szMessage,
0,
NULL);

wprintf(TEXT("%s: %s(%lx)\n"), szPrefix, szMessage, hr);

LocalFree(szMessage);
} // Message

// ---------------------------------------------------------------------------
// %%Function: OutputTime
// ---------------------------------------------------------------------------
void
OutputTime(LARGE_INTEGER* pliStart, LARGE_INTEGER* pliFinish)
{
LARGE_INTEGER liFreq;

QueryPerformanceFrequency(&liFreq);
wprintf(TEXT("%0.4f seconds\n"),
(float)(pliFinish->LowPart - pliStart->LowPart)/(float)liFreq.LowPart);
} // OutputTime

// ---------------------------------------------------------------------------
// %%Function: main
// ---------------------------------------------------------------------------
void __cdecl
main(int argc, CHAR **argv)
{
HRESULT hr;
MULTI_QI mq;
COSERVERINFO csi, *pcsi=NULL;
WCHAR wsz [MAX_PATH];
ULONG cb = cbDefault;
LARGE_INTEGER liStart, liFinish;

// allow a machine-name as the command-line argument
if (argc > 1)
{
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, argv[1], -1,
wsz, MAX_PATH);
memset(&csi, 0, sizeof(COSERVERINFO));
csi.pwszName = wsz;
pcsi = &csi;
}

// allow a byte-size to be passed on the command-line
if (argc > 2)
cb = atol(argv[2]);

// initialize COM for free-threaded use
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr))
{
Message(TEXT("Client: CoInitializeEx"), hr);
exit(hr);
}

// create a remote instance of the object on the argv[1] machine
Message(TEXT("Client: Creating Instance..."), S_OK);
mq.pIID = &IID_IStream;
mq.pItf = NULL;
mq.hr = S_OK;
QueryPerformanceCounter(&liStart);
hr = CoCreateInstanceEx(CLSID_SimpleObject, NULL, CLSCTX_SERVER, pcsi, 1, &mq);
QueryPerformanceCounter(&liFinish);
OutputTime(&liStart, &liFinish);

if (FAILED(hr))
Message(TEXT("Client: CoCreateInstanceEx"), hr);
else
{
LPSTREAM pstm = (IStream*)mq.pItf;
LPVOID pv;

// "read" some data from the object
Message(TEXT("Client: Reading data..."), S_OK);
pv = CoTaskMemAlloc(cb);
QueryPerformanceCounter(&liStart);
hr = pstm->Read(pv, cb, NULL);
QueryPerformanceCounter(&liFinish);
OutputTime(&liStart, &liFinish);
if (FAILED(hr))
Message(TEXT("Client: IStream::Read"), hr);

// "write" some data to the object
Message(TEXT("Client: Writing data..."), S_OK);
QueryPerformanceCounter(&liStart);
hr = pstm->Write(pv, cb, NULL);
QueryPerformanceCounter(&liFinish);
OutputTime(&liStart, &liFinish);
if (FAILED(hr))
Message(TEXT("Client: IStream::Write"), hr);

// let go of the object
pstm->Release();
}

CoUninitialize();
Message(TEXT("Client: Done"), S_OK);
} // main

// EOF =======================================================================