home *** CD-ROM | disk | FTP | other *** search
- // ===========================================================================
- // File: S S E R V E R . 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 server-portion of the SIMPLE Network OLE sample. This
- // application implements the CLSID_SimpleObject class as a LocalServer.
- // Instances of this class support a limited form of the IStream interface --
- // calls to IStream::Read and IStream::Write will "succeed" (they do nothing),
- // and calls on any other methods fail with E_NOTIMPL.
- //
- // The purpose of this sample is to demonstrate what is minimally required
- // to implement an object that can be used by clients (both those on the same
- // machine using OLE and those using Network OLE across the network).
- //
- // Instructions:
- //
- // To use this sample:
- // * build it using the NMAKE command. NMAKE will create SSERVER.EXE and
- // SCLIENT.EXE.
- // * edit the SSERVER.REG file to make the LocalServer32 key point to the
- // location of SSERVER.EXE, and run the INSTALL.BAT command (it simply
- // performs REGEDIT SSERVER.REG)
- // * run SSERVER.EXE. it should display the message "Waiting..."
- // * run SCLIENT.EXE on the same machine using no command-line arguments,
- // or from another machine using the machine-name (UNC or DNS) as the sole
- // command-line argument. it will connect to the server, perform some read
- // and write calls, and disconnect. both SSERVER.EXE and SCLIENT.EXE will
- // automatically terminate. both applications will display some status text.
- // * you can also run SCLIENT.EXE from a different machine without having first
- // run SSERVER.EXE on the machine. in this case, SSERVER.EXE will be launched
- // by OLE in the background and you will be able to watch the output of
- // SCLIENT.EXE but the output of SSERVER.EXE will be hidden.
- // * to examine the automatic launch-security features of Network OLE, try
- // using the '...\CLSID\{...}\LaunchPermission = Y' key commented out in
- // the SSERVER.REG file and reinstalling it. by setting different read-access
- // privileges on this key (using the Security/Permissions... dialog in the
- // REGEDT32 registry tool built into the system) you can allow other
- // users to run the SCLIENT.EXE program from their accounts.
- //
- // Copyright 1996 Microsoft Corporation. All Rights Reserved.
- // ===========================================================================
-
- // %%Includes: ---------------------------------------------------------------
- #define INC_OLE2
- #define STRICT
- #include <stdio.h>
- #include <windows.h>
- #include <initguid.h>
-
- // %%GUIDs: ------------------------------------------------------------------
- DEFINE_GUID(CLSID_SimpleObject, 0x5e9ddec7, 0x5767, 0x11cf, 0xbe, 0xab, 0x0, 0xaa, 0x0, 0x6c, 0x36, 0x6);
-
- // %%Globals: ----------------------------------------------------------------
- HANDLE hevtDone;
-
- // %%Classes: ----------------------------------------------------------------
- // simple class-factory: only knows how to create CSimpleObject instances
- class CClassFactory : public IClassFactory {
- public:
- // IUnknown
- STDMETHODIMP QueryInterface (REFIID riid, void** ppv);
- STDMETHODIMP_(ULONG) AddRef(void) { return 1; };
- STDMETHODIMP_(ULONG) Release(void) { return 1; }
-
- // IClassFactory
- STDMETHODIMP CreateInstance (LPUNKNOWN punkOuter, REFIID iid, void **ppv);
- STDMETHODIMP LockServer (BOOL fLock) { return E_FAIL; };
- };
-
- // simple object supporting a dummy IStream
- class CSimpleObject : public IStream {
- public:
- // IUnknown
- STDMETHODIMP QueryInterface (REFIID iid, void **ppv);
- STDMETHODIMP_(ULONG) AddRef(void) { return InterlockedIncrement(&m_cRef); };
- STDMETHODIMP_(ULONG) Release(void) { if (InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; } return 1; }
-
- // IStream
- STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead);
- STDMETHODIMP Write(VOID const *pv, ULONG cb, ULONG *pcbWritten);
- STDMETHODIMP Seek(LARGE_INTEGER dbMove, DWORD dwOrigin, ULARGE_INTEGER *pbNewPosition)
- { return E_FAIL; }
- STDMETHODIMP SetSize(ULARGE_INTEGER cbNewSize)
- { return E_FAIL; }
- STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
- { return E_FAIL; }
- STDMETHODIMP Commit(DWORD grfCommitFlags)
- { return E_FAIL; }
- STDMETHODIMP Revert(void)
- { return E_FAIL; }
- STDMETHODIMP LockRegion(ULARGE_INTEGER bOffset, ULARGE_INTEGER cb, DWORD dwLockType)
- { return E_FAIL; }
- STDMETHODIMP UnlockRegion(ULARGE_INTEGER bOffset, ULARGE_INTEGER cb, DWORD dwLockType)
- { return E_FAIL; }
- STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag)
- { return E_FAIL; }
- STDMETHODIMP Clone(IStream **ppstm)
- { return E_FAIL; }
-
- // constructors/destructors
- CSimpleObject() { m_cRef = 1; }
- ~CSimpleObject() { SetEvent(hevtDone); }
-
- private:
- LONG m_cRef;
- };
-
- // %%Globals: ----------------------------------------------------------------
- CClassFactory g_ClassFactory;
-
- // ---------------------------------------------------------------------------
- // %%Function: Message
- //
- // Formats and displays a message to the console.
- // ---------------------------------------------------------------------------
- void
- Message(LPTSTR szPrefix, HRESULT hr)
- {
- LPTSTR szMessage;
-
- if (hr == S_OK)
- {
- wprintf(szPrefix);
- wprintf(TEXT("\n"));
- 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: CSimpleObject::QueryInterface
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CSimpleObject::QueryInterface(REFIID riid, void** ppv)
- {
- if (ppv == NULL)
- return E_INVALIDARG;
- if (riid == IID_IUnknown || riid == IID_IStream)
- {
- *ppv = (IUnknown *) this;
- AddRef();
- return S_OK;
- }
- *ppv = NULL;
- return E_NOINTERFACE;
- } // CSimpleObject::QueryInterface
-
- // ---------------------------------------------------------------------------
- // %%Function: CSimpleObject::Read
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CSimpleObject::Read(void *pv, ULONG cb, ULONG *pcbRead)
- {
- Message(TEXT("Server: IStream:Read"), S_OK);
- if (!pv && cb != 0)
- return E_INVALIDARG;
-
- // fill the buffer with FF's. we could read it from somewhere.
- if (cb != 0)
- memset(pv, 0xFF, cb);
-
- if (pcbRead)
- *pcbRead = cb;
- return S_OK;
- } // CSimpleObject::Read
-
- // ---------------------------------------------------------------------------
- // %%Function: CSimpleObject::Write
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CSimpleObject::Write(VOID const *pv, ULONG cb, ULONG *pcbWritten)
- {
- Message(TEXT("Server: IStream:Write"), S_OK);
- if (!pv && cb != 0)
- return E_INVALIDARG;
- // ignore the data, but we could examine it or put it somewhere
- if (pcbWritten)
- *pcbWritten = cb;
- return S_OK;
- } // CSimpleObject::Write
-
- // ---------------------------------------------------------------------------
- // %%Function: CClassFactory::QueryInterface
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CClassFactory::QueryInterface(REFIID riid, void** ppv)
- {
- if (ppv == NULL)
- return E_INVALIDARG;
- if (riid == IID_IClassFactory || riid == IID_IUnknown)
- {
- *ppv = (IClassFactory *) this;
- AddRef();
- return S_OK;
- }
- *ppv = NULL;
- return E_NOINTERFACE;
- } // CClassFactory::QueryInterface
-
- // ---------------------------------------------------------------------------
- // %%Function: CClassFactory::CreateInstance
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CClassFactory::CreateInstance(LPUNKNOWN punkOuter, REFIID riid, void** ppv)
- {
- LPUNKNOWN punk;
- HRESULT hr;
-
- *ppv = NULL;
-
- if (punkOuter != NULL)
- return CLASS_E_NOAGGREGATION;
-
- Message(TEXT("Server: IClassFactory:CreateInstance"), S_OK);
-
- punk = new CSimpleObject;
-
- if (punk == NULL)
- return E_OUTOFMEMORY;
-
- hr = punk->QueryInterface(riid, ppv);
- punk->Release();
- return hr;
- } // CClassFactory::CreateInstance
-
- // ---------------------------------------------------------------------------
- // %%Function: main
- // ---------------------------------------------------------------------------
- void __cdecl
- main()
- {
- HRESULT hr;
- DWORD dwRegister;
-
- // create the thread which is signaled when the instance is deleted
- hevtDone = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (hevtDone == NULL)
- {
- hr = HRESULT_FROM_WIN32(GetLastError());
- Message(TEXT("Server: CreateEvent"), hr);
- exit(hr);
- }
-
- // initialize COM for free-threading
- hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
- if (FAILED(hr))
- {
- Message(TEXT("Server: CoInitializeEx"), hr);
- exit(hr);
- }
-
- // register the class-object with OLE
- hr = CoRegisterClassObject(CLSID_SimpleObject, &g_ClassFactory,
- CLSCTX_SERVER, REGCLS_SINGLEUSE, &dwRegister);
- if (FAILED(hr))
- {
- Message(TEXT("Server: CoRegisterClassObject"), hr);
- exit(hr);
- }
-
- Message(TEXT("Server: Waiting"), S_OK);
-
- // wait until an object is created and deleted.
- WaitForSingleObject(hevtDone, INFINITE);
-
- CloseHandle(hevtDone);
-
- CoUninitialize();
- Message(TEXT("Server: Done"), S_OK);
- } // main
-
- // EOF =======================================================================
-
-