home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / dcom / simple / sserver.cpp < prev    next >
C/C++ Source or Header  |  1996-04-03  |  11KB  |  296 lines

  1. // ===========================================================================
  2. // File: S S E R V E R . C P P
  3. // 
  4. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  5. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  6. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  7. // PARTICULAR PURPOSE.
  8. // 
  9. // Description:
  10. // 
  11. //  This is the server-portion of the SIMPLE Network OLE sample. This
  12. // application implements the CLSID_SimpleObject class as a LocalServer.
  13. // Instances of this class support a limited form of the IStream interface --
  14. // calls to IStream::Read and IStream::Write will "succeed" (they do nothing),
  15. // and calls on any other methods fail with E_NOTIMPL.
  16. // 
  17. //  The purpose of this sample is to demonstrate what is minimally required
  18. // to implement an object that can be used by clients (both those on the same
  19. // machine using OLE and those using Network OLE across the network).
  20. // 
  21. // Instructions:
  22. // 
  23. //  To use this sample:
  24. //   * build it using the NMAKE command. NMAKE will create SSERVER.EXE and
  25. //     SCLIENT.EXE.
  26. //   * edit the SSERVER.REG file to make the LocalServer32 key point to the
  27. //     location of SSERVER.EXE, and run the INSTALL.BAT command (it simply
  28. //     performs REGEDIT SSERVER.REG)
  29. //   * run SSERVER.EXE. it should display the message "Waiting..."
  30. //   * run SCLIENT.EXE on the same machine using no command-line arguments,
  31. //     or from another machine using the machine-name (UNC or DNS) as the sole
  32. //     command-line argument. it will connect to the server, perform some read
  33. //     and write calls, and disconnect. both SSERVER.EXE and SCLIENT.EXE will
  34. //     automatically terminate. both applications will display some status text.
  35. //   * you can also run SCLIENT.EXE from a different machine without having first
  36. //     run SSERVER.EXE on the machine. in this case, SSERVER.EXE will be launched
  37. //     by OLE in the background and you will be able to watch the output of
  38. //     SCLIENT.EXE but the output of SSERVER.EXE will be hidden.
  39. //   * to examine the automatic launch-security features of Network OLE, try
  40. //     using the '...\CLSID\{...}\LaunchPermission = Y' key commented out in 
  41. //     the SSERVER.REG file and reinstalling it. by setting different read-access
  42. //     privileges on this key (using the Security/Permissions... dialog in the
  43. //     REGEDT32 registry tool built into the system) you can allow other
  44. //     users to run the SCLIENT.EXE program from their accounts.
  45. // 
  46. // Copyright 1996 Microsoft Corporation.  All Rights Reserved.
  47. // ===========================================================================
  48.  
  49. // %%Includes: ---------------------------------------------------------------
  50. #define INC_OLE2
  51. #define STRICT
  52. #include <stdio.h>
  53. #include <windows.h>
  54. #include <initguid.h>
  55.  
  56. // %%GUIDs: ------------------------------------------------------------------
  57. DEFINE_GUID(CLSID_SimpleObject, 0x5e9ddec7, 0x5767, 0x11cf, 0xbe, 0xab, 0x0, 0xaa, 0x0, 0x6c, 0x36, 0x6);
  58.  
  59. // %%Globals: ----------------------------------------------------------------
  60. HANDLE          hevtDone;
  61.  
  62. // %%Classes: ----------------------------------------------------------------
  63. // simple class-factory: only knows how to create CSimpleObject instances
  64. class CClassFactory : public IClassFactory {
  65.   public:
  66.     // IUnknown
  67.     STDMETHODIMP    QueryInterface (REFIID riid, void** ppv);
  68.     STDMETHODIMP_(ULONG) AddRef(void)  { return 1; };
  69.     STDMETHODIMP_(ULONG) Release(void) { return 1; }
  70.  
  71.     // IClassFactory
  72.     STDMETHODIMP    CreateInstance (LPUNKNOWN punkOuter, REFIID iid, void **ppv);
  73.     STDMETHODIMP    LockServer (BOOL fLock) { return E_FAIL; };
  74.     };
  75.  
  76. // simple object supporting a dummy IStream
  77. class CSimpleObject : public IStream {
  78.   public:
  79.     // IUnknown
  80.     STDMETHODIMP    QueryInterface (REFIID iid, void **ppv);
  81.     STDMETHODIMP_(ULONG) AddRef(void)  { return InterlockedIncrement(&m_cRef); };
  82.     STDMETHODIMP_(ULONG) Release(void) { if (InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; } return 1; }
  83.  
  84.     // IStream
  85.     STDMETHODIMP    Read(void *pv, ULONG cb, ULONG *pcbRead);
  86.     STDMETHODIMP    Write(VOID const *pv, ULONG cb, ULONG *pcbWritten);
  87.     STDMETHODIMP    Seek(LARGE_INTEGER dbMove, DWORD dwOrigin, ULARGE_INTEGER *pbNewPosition)
  88.         { return E_FAIL; }
  89.     STDMETHODIMP    SetSize(ULARGE_INTEGER cbNewSize)
  90.         { return E_FAIL; }
  91.     STDMETHODIMP    CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
  92.         { return E_FAIL; }
  93.     STDMETHODIMP    Commit(DWORD grfCommitFlags)
  94.         { return E_FAIL; }
  95.     STDMETHODIMP    Revert(void)
  96.         { return E_FAIL; }
  97.     STDMETHODIMP    LockRegion(ULARGE_INTEGER bOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  98.         { return E_FAIL; }
  99.     STDMETHODIMP    UnlockRegion(ULARGE_INTEGER bOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  100.         { return E_FAIL; }
  101.     STDMETHODIMP    Stat(STATSTG *pstatstg, DWORD grfStatFlag)
  102.         { return E_FAIL; }
  103.     STDMETHODIMP    Clone(IStream **ppstm)
  104.         { return E_FAIL; }
  105.  
  106.     // constructors/destructors
  107.     CSimpleObject()     { m_cRef = 1; }
  108.     ~CSimpleObject()    { SetEvent(hevtDone); }
  109.  
  110.   private:
  111.     LONG        m_cRef;
  112.     };
  113.  
  114. // %%Globals: ----------------------------------------------------------------
  115. CClassFactory   g_ClassFactory;
  116.  
  117. // ---------------------------------------------------------------------------
  118. // %%Function: Message
  119. // 
  120. //  Formats and displays a message to the console.
  121. // ---------------------------------------------------------------------------
  122.  void
  123. Message(LPTSTR szPrefix, HRESULT hr)
  124. {
  125.     LPTSTR   szMessage;
  126.  
  127.     if (hr == S_OK)
  128.         {
  129.         wprintf(szPrefix);
  130.         wprintf(TEXT("\n"));
  131.         return;
  132.         }
  133.  
  134.     if (HRESULT_FACILITY(hr) == FACILITY_WINDOWS)
  135.         hr = HRESULT_CODE(hr);
  136.  
  137.     FormatMessage(
  138.         FORMAT_MESSAGE_ALLOCATE_BUFFER |
  139.         FORMAT_MESSAGE_FROM_SYSTEM,
  140.         NULL,
  141.         hr,
  142.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language
  143.         (LPTSTR)&szMessage,
  144.         0,
  145.         NULL );
  146.  
  147.     wprintf(TEXT("%s: %s(%lx)\n"), szPrefix, szMessage, hr);
  148.     
  149.     LocalFree(szMessage);
  150. }  // Message
  151.  
  152. // ---------------------------------------------------------------------------
  153. // %%Function: CSimpleObject::QueryInterface
  154. // ---------------------------------------------------------------------------
  155.  STDMETHODIMP
  156. CSimpleObject::QueryInterface(REFIID riid, void** ppv)
  157. {
  158.     if (ppv == NULL)
  159.         return E_INVALIDARG;
  160.     if (riid == IID_IUnknown || riid == IID_IStream)
  161.         {
  162.         *ppv = (IUnknown *) this;
  163.         AddRef();
  164.         return S_OK;
  165.         }
  166.     *ppv = NULL;
  167.     return E_NOINTERFACE;
  168. }  // CSimpleObject::QueryInterface
  169.  
  170. // ---------------------------------------------------------------------------
  171. // %%Function: CSimpleObject::Read
  172. // ---------------------------------------------------------------------------
  173.  STDMETHODIMP
  174. CSimpleObject::Read(void *pv, ULONG cb, ULONG *pcbRead)
  175. {
  176.     Message(TEXT("Server: IStream:Read"), S_OK);
  177.     if (!pv && cb != 0)
  178.         return E_INVALIDARG;
  179.  
  180.     // fill the buffer with FF's. we could read it from somewhere.
  181.     if (cb != 0)
  182.         memset(pv, 0xFF, cb);
  183.  
  184.     if (pcbRead)
  185.         *pcbRead = cb;
  186.     return S_OK;
  187. }  // CSimpleObject::Read
  188.  
  189. // ---------------------------------------------------------------------------
  190. // %%Function: CSimpleObject::Write
  191. // ---------------------------------------------------------------------------
  192.  STDMETHODIMP
  193. CSimpleObject::Write(VOID const *pv, ULONG cb, ULONG *pcbWritten)
  194. {
  195.     Message(TEXT("Server: IStream:Write"), S_OK);
  196.     if (!pv && cb != 0)
  197.         return E_INVALIDARG;
  198.     // ignore the data, but we could examine it or put it somewhere
  199.     if (pcbWritten)
  200.         *pcbWritten = cb;
  201.     return S_OK;
  202. }  // CSimpleObject::Write
  203.  
  204. // ---------------------------------------------------------------------------
  205. // %%Function: CClassFactory::QueryInterface
  206. // ---------------------------------------------------------------------------
  207.  STDMETHODIMP
  208. CClassFactory::QueryInterface(REFIID riid, void** ppv)
  209. {
  210.     if (ppv == NULL)
  211.         return E_INVALIDARG;
  212.     if (riid == IID_IClassFactory || riid == IID_IUnknown)
  213.         {
  214.         *ppv = (IClassFactory *) this;
  215.         AddRef();
  216.         return S_OK;
  217.         }
  218.     *ppv = NULL;
  219.     return E_NOINTERFACE;
  220. }  // CClassFactory::QueryInterface
  221.  
  222. // ---------------------------------------------------------------------------
  223. // %%Function: CClassFactory::CreateInstance
  224. // ---------------------------------------------------------------------------
  225.  STDMETHODIMP
  226. CClassFactory::CreateInstance(LPUNKNOWN punkOuter, REFIID riid, void** ppv)
  227. {
  228.     LPUNKNOWN   punk;
  229.     HRESULT     hr;
  230.  
  231.     *ppv = NULL;
  232.  
  233.     if (punkOuter != NULL)
  234.         return CLASS_E_NOAGGREGATION;
  235.  
  236.     Message(TEXT("Server: IClassFactory:CreateInstance"), S_OK);
  237.  
  238.     punk = new CSimpleObject;
  239.  
  240.     if (punk == NULL)
  241.         return E_OUTOFMEMORY;
  242.  
  243.     hr = punk->QueryInterface(riid, ppv);
  244.     punk->Release();
  245.     return hr;
  246. }  // CClassFactory::CreateInstance
  247.  
  248. // ---------------------------------------------------------------------------
  249. // %%Function: main
  250. // ---------------------------------------------------------------------------
  251.  void __cdecl
  252. main()
  253. {
  254.     HRESULT hr;
  255.     DWORD   dwRegister;
  256.  
  257.     // create the thread which is signaled when the instance is deleted
  258.     hevtDone = CreateEvent(NULL, FALSE, FALSE, NULL);
  259.     if (hevtDone == NULL)
  260.         {
  261.         hr = HRESULT_FROM_WIN32(GetLastError());
  262.         Message(TEXT("Server: CreateEvent"), hr);
  263.         exit(hr);
  264.         }
  265.  
  266.     // initialize COM for free-threading
  267.     hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  268.     if (FAILED(hr))
  269.         {
  270.         Message(TEXT("Server: CoInitializeEx"), hr);
  271.         exit(hr);
  272.         }
  273.  
  274.     // register the class-object with OLE
  275.     hr = CoRegisterClassObject(CLSID_SimpleObject, &g_ClassFactory,
  276.         CLSCTX_SERVER, REGCLS_SINGLEUSE, &dwRegister);
  277.     if (FAILED(hr))
  278.         {
  279.         Message(TEXT("Server: CoRegisterClassObject"), hr);
  280.         exit(hr);
  281.         }
  282.  
  283.     Message(TEXT("Server: Waiting"), S_OK);
  284.  
  285.     // wait until an object is created and deleted.
  286.     WaitForSingleObject(hevtDone, INFINITE);
  287.  
  288.     CloseHandle(hevtDone);
  289.  
  290.     CoUninitialize();
  291.     Message(TEXT("Server: Done"), S_OK);
  292. }  // main
  293.  
  294. // EOF =======================================================================
  295.  
  296.