[in] BOOL bAllowAnonymousAccess,
[out] IChatSession **ppcs);
HRESULT DeleteSession([in, string] const OLECHAR *pwszName);
}
cpp_quote(«DEFINE_GUID(CLSID_ChatSession,0x5223a053,0x2441,»)
cpp_quote(«0x11d1,0xaf,0x4f,0x0,0x60,0x97,0x6a,0xa8,0x86);»)
/////////////////////////////////////////////////////
//
// client.cpp
//
// Copyright 1997, Don Box/Addison Wesley
//
// This code accompanies the book "The Component
// Object Model" from Addison Wesley. Blah blah blah
//
//
#define _WIN32_WINNT 0x403
#include
#include
#include
#include
#include «../include/COMChat.h»
#include «../include/COMChat_i.c»
void Error(HRESULT hr, const char *psz)
{
printf(«%s failed and returned 0x%x\n», psz, hr);
}
// utility function to print command line syntax
int Usage(void)
{
const char *psz =
«usage: client.exe
« where:\n»
« action = /sessions|/chat:session|/delete:session\n»
« user = /user:domain\\user /password:pw |»
«/anonymous |
« host = /host:hostname |
printf(psz);
return -1;
}
// utility function for printing a list of strings
void PrintAllStrings(IEnumString *pes)
{
enum { CHUNKSIZE = 64 };
OLECHAR *rgpwsz[CHUNKSIZE];
ULONG cFetched;
HRESULT hr;
do
{
hr = pes->Next(CHUNKSIZE, rgpwsz, &cFetched);
if (SUCCEEDED(hr))
{
for (ULONG i = 0; i < cFetched; i++)
if (rgpwsz[i])
{
wprintf(L"%s\n", rgpwsz[i]);
CoTaskMemFree(rgpwsz[i]);
}
}
} while (hr == S_OK);
}
// utility function to print initial state of
// a chat session
void PrintToDate(IChatSession *pcs)
{
IEnumString *pes = 0;
HRESULT hr = pcs->GetStatements(&pes);
if (SUCCEEDED(hr))
{
PrintAllStrings(pes);
pes->Release();
}
}
// this class implements the callback interface
// that receives chat notifications. It simply
// prints the event to the console
class EventSink : public IChatSessionEvents
{
public:
STDMETHODIMP QueryInterface(REFIID riid, void**ppv)
{
if (riid == IID_IUnknown)
*ppv = static_cast
else if (riid == IID_IChatSessionEvents)
*ppv = static_cast
else
return (*ppv = 0), E_NOINTERFACE;
reinterpret_cast
return S_OK;
}
STDMETHODIMP_(ULONG) AddRef(void)
{
return 2;
}
STDMETHODIMP_(ULONG) Release(void)
{
return 1;
}
STDMETHODIMP OnNewStatement(const OLECHAR *pwszUser,
const OLECHAR *pwszStmt)
{
wprintf(L"%-14s: %s\n", pwszUser, pwszStmt);
return S_OK;
}
STDMETHODIMP OnNewUser(const OLECHAR *pwszUser)
{
wprintf(L"\n\n>>> Say Hello to %s\n\n", pwszUser);
return S_OK;
}
STDMETHODIMP OnUserLeft(const OLECHAR *pwszUser)
{
wprintf(L"\n\n>>> Say Bye to %s\n\n", pwszUser);
return S_OK;
}
};
// type of operations this client can perform
enum ACTION
{
ACTION_NONE,
ACTION_CHAT,
ACTION_DELETE_SESSION,
ACTION_LIST_SESSION_NAMES,
};
// run chat command
void Chat(const OLECHAR *pwszSession,
IChatSessionManager *pcsm, // manager
COAUTHIDENTITY *pcai, // user
bool bAnonymous) // anonymous
{
// create or get the named session
IChatSession *pcs = 0;
HRESULT hr = pcsm->FindSession(pwszSession, FALSE,
TRUE, &pcs);
if (SUCCEEDED(hr))
{
// adjust security blanket for session interface
if (!bAnonymous)
hr = CoSetProxyBlanket(pcs, RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE, 0,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IDENTIFY,
pcai, EOAC_NONE);
// catch up on past messages
PrintToDate(pcs);
// hook up event sink to receive new messages
EventSink es;
DWORD dwReg;
hr = pcs->Advise(&es, &dwReg);
if (SUCCEEDED(hr))
{
// run UI loop to get statements from console and send them
OLECHAR wszStmt[4096];
while (_getws(wszStmt))
{
hr = pcs->Say(wszStmt);
if (FAILED(hr))
Error(hr, «Say»);
}
// tear down connection for event sink
pcs->Unadvise(dwReg);
}
else
Error(hr, «Advise»);
// release chat session
pcs->Release();
}
else
Error(hr, «FindSession»);
}
// run delete command
void Delete(const OLECHAR *pwszSession,
IChatSessionManager *pcsm)
{
HRESULT hr = pcsm->DeleteSession(pwszSession);
if (FAILED(hr))
Error(hr, «DeleteSession»);
}
// run list command
void List(IChatSessionManager *pcsm)
{
IEnumString *pes = 0;
HRESULT hr = pcsm->GetSessionNames(&pes);
if (SUCCEEDED(hr))
{
printf(«Active Sessions:\n»);
PrintAllStrings(pes);
pes->Release();
}
}
int main(int argc, char **argv)
{
// declare client control state
bool bAnonymous = false;
static OLECHAR wszSessionName[1024];
static OLECHAR wszDomainName[1024];
static OLECHAR wszUserName[1024];
static OLECHAR wszPassword[1024];
static OLECHAR wszHostName[1024];
COSERVERINFO csi = { 0, wszHostName, 0, 0 };
COSERVERINFO *pcsi = 0;
COAUTHIDENTITY cai = {
wszUserName,
0,
wszDomainName,
0,
wszPassword,
0,
SEC_WINNT_AUTH_IDENTITY_UNICODE
};
static COAUTHIDENTITY *pcai = 0;
static ACTION action = ACTION_NONE;
// parse command line
for (int i = 1; i < argc; i++)
{
if (strcmp(argv[i], «/anonymous») == 0)
bAnonymous = true;
else if (strstr(argv[i], «/delete:») == argv[i])
{
if (action != ACTION_NONE)
return Usage();
action = ACTION_DELETE_SESSION;
mbstowcs(wszSessionName, argv[i] + 8, 1024);
}
else if (strstr(argv[i], «/chat:») == argv[i])
{
if (action != ACTION_NONE)
return Usage();
action = ACTION_CHAT;
mbstowcs(wszSessionName, argv[i] + 6, 1024);
}
else if (strcmp(argv[i], «/sessions») == 0)
{
if (action != ACTION_NONE)
return Usage();
action = ACTION_LIST_SESSION_NAMES;
}