home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 2.ddi / OLESRVR.ZIP / SERVER.CPP < prev   
Encoding:
C/C++ Source or Header  |  1992-06-10  |  15.4 KB  |  492 lines

  1. // ObjectWindows - (C) Copyright 1992 by Borland International
  2.  
  3. /* implementation of class TOLEServer */
  4.  
  5. #include <owl.h>
  6.  
  7. #define SERVERONLY
  8. #include <ole.h>
  9. #include "shellapi.h"  // registration database
  10.  
  11. #include "olesrvr.h"
  12.  
  13. OLESERVERVTBL  TOLEServer::_vtbl;
  14.  
  15. /*
  16.     WantsToRegister
  17.     ---------------
  18.  
  19.     displays an action message prompting the user to see if they want to
  20.     register szAppName with the system registration database
  21.  
  22.     return TRUE if user says YES and FALSE is users says NO
  23.  
  24.     if user says NO we terminate the app
  25. */
  26. BOOL
  27. TOLEServer::WantsToRegister ()
  28. {
  29.   char  buf[128];
  30.  
  31.   wsprintf (buf,
  32.             "\"%s\" is not registered as an OLE server in the system registration \
  33. database. Do you want to register it?",
  34.             (LPSTR) szAppName);
  35.  
  36.   if (MessageBox (0, buf, szAppName, MB_YESNO | MB_ICONQUESTION) == IDYES)
  37.     return TRUE;
  38.  
  39.   else {
  40.     //
  41.     // terminate the app
  42.     //
  43.     PostAppMessage (GetCurrentTask(), WM_QUIT, 0, 0);
  44.  
  45.     //
  46.     // we also need to make sure that the main window doesn't get displayed
  47.     //
  48.     // we have a couple of choices: set "nCmdShow" to SW_HIDE or set "Status"
  49.     // to non-zero. since the user electing not to register isn't really an
  50.     // error, let's set "nCmdShow"
  51.     //
  52.     GetApplicationObject()->nCmdShow = SW_HIDE;
  53.     return FALSE;
  54.   }
  55. }
  56.  
  57.  
  58. /*
  59.     RegisterWithDatabase
  60.     --------------------
  61.  
  62.     register ourselves as an OLE server with the system registration database
  63.  
  64.     this would typically be done during *installation* of the app and not when
  65.     the app runs...
  66.  
  67.     NOTE: we first prompt the user to see if they want us to register. if so we
  68.           register and if not we terminate the app
  69. */
  70. BOOL
  71. TOLEServer::RegisterWithDatabase ()
  72. {
  73.   char  buf[128];
  74.   char  path[MAXPATHLENGTH];
  75.   int   pathLen;
  76.  
  77.   if (!WantsToRegister())
  78.     return FALSE;
  79.  
  80.   else {
  81.     wsprintf (buf, ".%s", (LPSTR) szFileExt);
  82.     RegSetValue (HKEY_CLASSES_ROOT,
  83.                  buf, REG_SZ,
  84.                  szClassKey, sizeof (szClassKey) - 1);
  85.  
  86.     RegSetValue (HKEY_CLASSES_ROOT,
  87.                  szClassKey, REG_SZ,
  88.                  szClassValue, sizeof (szClassValue) - 1);
  89.  
  90.     //
  91.     // register verb actions EDIT and PLAY with EDIT being the primary verb
  92.     //
  93.     wsprintf (buf, "%s\\protocol\\StdFileEditing\\verb\\0", (LPSTR) szClassKey);
  94.     RegSetValue (HKEY_CLASSES_ROOT, buf, REG_SZ, "Edit", 4);
  95.  
  96.     wsprintf (buf, "%s\\protocol\\StdFileEditing\\verb\\1", (LPSTR) szClassKey);
  97.     RegSetValue (HKEY_CLASSES_ROOT, buf, REG_SZ, "Play", 4);
  98.  
  99.     //
  100.     // register a full pathname to the executable with the database
  101.     //
  102.     pathLen = GetModuleFileName (GetModuleHandle (szExeName), path, sizeof (path));
  103.     wsprintf (buf, "%s\\protocol\\StdFileEditing\\server", (LPSTR) szClassKey);
  104.     RegSetValue (HKEY_CLASSES_ROOT, buf, REG_SZ, path, pathLen);
  105.  
  106.     //
  107.     // inform the user that we have registered as an OLE server by displaying
  108.     // an information message
  109.     //
  110.     wsprintf (buf,
  111.               "\"%s\" successfully registered as an OLE server with the system registration database.",
  112.               (LPSTR) szAppName);
  113.  
  114.     MessageBox (0, buf, szAppName, MB_OK | MB_ICONINFORMATION);
  115.     return TRUE;
  116.   }
  117. }
  118.  
  119.  
  120. /*
  121.     Init
  122.     ----
  123. */
  124. BOOL
  125. TOLEServer::Init (TOLEApp &app)
  126. {
  127.   OLESTATUS   status;
  128.  
  129.   lpvtbl = &_vtbl;
  130.   fRelease = FALSE;
  131.   app.pServer = this;
  132.  
  133.   //
  134.   // since we can't handle multiple documents (MDI), request that we use
  135.   // multiple instances to support multiple objects
  136.   //
  137.     status = OleRegisterServer (szClassKey,
  138.                                           this,
  139.                                           &lhServer,
  140.                                           app.hInstance,
  141.                                           OLE_SERVER_MULTI);
  142.  
  143.   if (status == OLE_ERROR_CLASS) {
  144.     if (RegisterWithDatabase())
  145.         OleRegisterServer (szClassKey,
  146.                                      this,
  147.                                      &lhServer,
  148.                                      app.hInstance,
  149.                                      OLE_SERVER_MULTI);
  150.  
  151.     else
  152.       return FALSE;
  153.   }
  154.  
  155.   return TRUE;
  156. }
  157.  
  158.  
  159. /*
  160.     constructor
  161.     -----------
  162.  
  163.     creates an untitled OLE document
  164. */
  165. TOLEServer::TOLEServer (TOLEApp &app, BOOL embedded)
  166. {
  167.   if (Init (app) && !embedded)
  168.     pDocument = new TOLEDocument (*this);
  169. }
  170.  
  171.  
  172. /*
  173.     constructor
  174.     -----------
  175.  
  176.     creates an OLE document and initializes it from file "szPath"
  177. */
  178. TOLEServer::TOLEServer (TOLEApp &app, LPSTR szPath)
  179. {
  180.   if (Init (app))
  181.     pDocument = new TOLEDocument (*this, 0, szPath);
  182. }
  183.  
  184.  
  185. /*
  186.     callback Create
  187.     -------- ------
  188.  
  189.     called by the server library when a client application has created a
  190.     new embedded object by calling OleCreate()
  191.  
  192.     WHAT TO DO:
  193.       - create an *untitled* TOLEDocument of class "lpszClassName" (since we
  194.         only have one class we can ignore the class name) and mark it as dirty
  195.       - associate handle "lhDoc" with the document
  196.       - store the pointer to the TOLEDocument in "lplpOleDoc"
  197.       - return OLE_OK if successful, OLE_ERROR_NEW otherwise
  198.  
  199.     if your app is an MDI application then you would also allocate a window
  200.     here, but since this app isn't the window is already created...
  201.  
  202.     "lpszDoc" is the name of the document as it appears in the client
  203.     class. DON'T use this to change the title bar, use what you get when
  204.     the document is sent message "SetHostNames"
  205.  
  206.     NOTE: since we only have one document we could have created it during
  207.           initialization
  208. */
  209. OLESTATUS FAR PASCAL _export
  210. TOLEServer::Create (LPOLESERVER         lpOleSvr,
  211.                       LHSERVERDOC         lhDoc,
  212.                       LPSTR               /* lpszClassName */,
  213.                       LPSTR               /* lpszDoc */,
  214.                       LPOLESERVERDOC FAR *lplpOleDoc)
  215. {
  216.   TOLEServer    *pServer = (TOLEServer *) lpOleSvr;
  217.     TOLEDocument  *pDoc = new TOLEDocument (*pServer, lhDoc, 0, TRUE);
  218.  
  219.     if (pDoc == NULL)
  220.         return OLE_ERROR_NEW;
  221.  
  222.   else {
  223.       *lplpOleDoc = pDoc;
  224.     ((TWindowServer *) GetApplicationObject()->MainWindow)->BeginEmbedding();
  225.       return OLE_OK;
  226.   }
  227. }
  228.  
  229.  
  230. /*
  231.     callback CreateFromTemplate
  232.     -------- ------------------
  233.  
  234.     called by the server library when a client application has created a
  235.     new linked object specifying a template by calling OleCreateFromTemplate()
  236.  
  237.     what this really means is that we need to create a document and initialize
  238.     it with the contents of a file...
  239.  
  240.     "lpszDoc" is the name of the document as it appears in the client
  241.     class. DON'T use this to change the title bar, use what you get when
  242.     the document is sent message "SetHostNames"
  243.  
  244.     WHAT TO DO:
  245.       - create a TOLEDocument of class "lpszClassName" (since we only have one
  246.         class we can ignore the class name)
  247.       - initialize the document with the contents of file "lpszTemplate"
  248.       - associate handle "lhDoc" with the document
  249.       - store the pointer to the TOLEDocument in "lplpOleDoc"
  250.       - return OLE_OK if successful, OLE_ERROR_TEMPLATE otherwise
  251.  
  252.     if your app is an MDI application then you would also allocate a window
  253.     here, but since this app isn't the window is already created...
  254.  
  255.     NOTE: since we only have one document we could have created it during
  256.           initialization
  257. */
  258. OLESTATUS FAR PASCAL _export
  259. TOLEServer::CreateFromTemplate (LPOLESERVER         lpOleSvr,
  260.                                 LHSERVERDOC         lhDoc,
  261.                                 LPSTR               /* lpszClassName */,
  262.                                 LPSTR               /* lpszDoc */,
  263.                                 LPSTR               lpszTemplate,
  264.                                 LPOLESERVERDOC FAR *lplpOleDoc)
  265. {
  266.   TOLEServer    *pServer = (TOLEServer *) lpOleSvr;
  267.     TOLEDocument  *pDoc = new TOLEDocument (*pServer, lhDoc, lpszTemplate);
  268.  
  269.     if (pDoc == NULL)
  270.         return OLE_ERROR_NEW;
  271.  
  272.   else {
  273.       *lplpOleDoc = pDoc;
  274.     ((TWindowServer *) GetApplicationObject()->MainWindow)->BeginEmbedding();
  275.       return OLE_OK;
  276.   }
  277. }
  278.  
  279.  
  280. /*
  281.     callback Edit
  282.     -------- ----
  283.  
  284.     called by the server library when a client application has activated
  285.     an embedded object for editing
  286.  
  287.     this is exactly like "Create" except that the document will receive a
  288.     "GetData" message to create the object and the object will receive a
  289.     "SetData" message to initialize itself
  290.  
  291.     "lpszDoc" is the name of the document as it appears in the client
  292.     class. DON'T use this to change the title bar, use what you get when
  293.     the document is sent message "SetHostNames"
  294.  
  295.     WHAT TO DO:
  296.       - create a TOLEDocument of class "lpszClassName" (since we only have one
  297.         class we can ignore the class name)
  298.       - associate handle "lhDoc" with the document
  299.       - store the pointer to the TOLEDocument in "lplpOleDoc"
  300.       - return OLE_OK if successful, OLE_ERROR_EDIT otherwise
  301. */
  302. OLESTATUS FAR PASCAL _export
  303. TOLEServer::Edit (LPOLESERVER         lpOleSvr,
  304.                     LHSERVERDOC         lhDoc,
  305.                     LPSTR               /* lpszClassName */,
  306.                     LPSTR               /* lpszDoc */,
  307.                     LPOLESERVERDOC FAR *lplpOleDoc)
  308. {
  309.   TOLEServer    *pServer = (TOLEServer *) lpOleSvr;
  310.   TOLEDocument  *pDoc = new TOLEDocument (*pServer, lhDoc);
  311.  
  312.   if (pDoc == NULL)
  313.     return OLE_ERROR_EDIT;
  314.  
  315.   else {
  316.       *lplpOleDoc = pDoc;
  317.     ((TWindowServer *) GetApplicationObject()->MainWindow)->BeginEmbedding();
  318.     return OLE_OK;
  319.   }
  320. }
  321.  
  322.  
  323. /*
  324.     callback Exit
  325.     -------- ----
  326.  
  327.     we have been instructed by the library to exit immediately because of a
  328.     fatal error
  329.  
  330.     WHAT TO DO:
  331.       - hide the window to prevent user interaction
  332.       - call OleRevokeServer() and ignore a return of OLE_WAIT_FOR_RELEASE
  333.       - terminate the application immediately
  334.       - return OLE_OK if successful, OLE_ERROR_GENERIC otherwise
  335. */
  336. OLESTATUS FAR PASCAL _export
  337. TOLEServer::Exit (LPOLESERVER lpOleSvr)
  338. {
  339.   GetApplicationObject()->MainWindow->Show (SW_HIDE);
  340.     OleRevokeServer (((TOLEServer *) lpOleSvr)->lhServer);
  341.   PostAppMessage (GetCurrentTask(), WM_QUIT, 0, 0);
  342.   return OLE_OK;
  343. }
  344.  
  345.  
  346. /*
  347.     callback Open
  348.     -------- ----
  349.  
  350.     user has activated a linked object in an OLE client by calling OleActivate()
  351.  
  352.     similar to CreateFromTemplate in that we need to create a document,
  353.     initialize it with the contents of file "lpszDoc", and save the file name
  354.     for later use...
  355.  
  356.     WHAT TO DO:
  357.       - create a TOLEDocument of class "lpszClassName" (since we only have one
  358.         class we can ignore the class name)
  359.       - initialize the document with the contents of file "lpszDoc"
  360.       - associate handle "lhDoc" with the document
  361.       - store the pointer to the TOLEDocument in "lplpOleDoc"
  362.       - save file name "lpszDoc"
  363.       - return OLE_OK if successful, OLE_ERROR_OPEN otherwise
  364. */
  365. OLESTATUS FAR PASCAL _export
  366. TOLEServer::Open (LPOLESERVER         lpOleSvr,
  367.                     LHSERVERDOC         lhDoc,
  368.                     LPSTR               lpszDoc,
  369.                     LPOLESERVERDOC FAR *lplpOleDoc)
  370. {
  371.   TOLEServer    *pServer = (TOLEServer *) lpOleSvr;
  372.   TOLEDocument  *pDoc = new TOLEDocument (*pServer, lhDoc, lpszDoc);
  373.  
  374.   if (pDoc == NULL)
  375.     return OLE_ERROR_EDIT;
  376.  
  377.   else {
  378.     *lplpOleDoc = pDoc;
  379.     return OLE_OK;
  380.   }
  381. }
  382.  
  383.  
  384. /*
  385.     callback Release
  386.     -------- -------
  387.  
  388.     this routine gets called by the server library after the server has
  389.     called OleRevokeServer() and when the DDE conversation with the client has
  390.     been successfully closed
  391.  
  392.     this tells us that there are no connections to the server, its documents,
  393.     or their objects and that we are free to terminate
  394.  
  395.     WHAT TO DO:
  396.       - set a flag to indicate that "Release" has been called
  397.       - if the application is hidden and we *haven't* called OleRevokeServer()
  398.         then we *must* terminate by posting a WM_CLOSE message
  399.       - free any resources allocated including documents, but *not* the
  400.         OLESERVER structure
  401.       - return OLE_OK if successful, OLE_ERROR_GENERIC otherwise
  402.  
  403.     NOTE: this routine is tricky because it is invoked under different
  404.           circumstances
  405.  
  406.       - user brought up the server and then closes it, which causes us
  407.         to call OleRevokeServer() which means the server will eventually
  408.         receive a "Release" message
  409.  
  410.       - the server was started to perform an invisible update for a client (i.e.
  411.         the server has always been hidden). in this case the server will receive
  412.         a "Release" message and we must tell ourselves to close because there
  413.         is no user interaction...
  414. */
  415. OLESTATUS FAR PASCAL _export
  416. TOLEServer::Release (LPOLESERVER lpOleSvr)
  417. {
  418.   //
  419.   // if we haven't been sent a "Release" message yet and our main window is
  420.   // hidden then we post a quit message
  421.   //
  422.   // NOTE: call PostMessage (hWnd, WM_CLOSE, 0, 0) and not PostQuitMessage (0)
  423.   //       because PostQuitMessage() might bypass your application's necessary
  424.   //       cleanup procedures
  425.   //
  426.   TOLEApp     *pApp = (TOLEApp *) GetApplicationObject();
  427.   TOLEServer  *pServer = (TOLEServer *) lpOleSvr;
  428.   BOOL         embedded = pServer->pDocument->type == doctypeEmbedded;
  429.  
  430.   if (!pServer->fRelease &&
  431.       (embedded || !IsWindowVisible (pApp->MainWindow->HWindow)))
  432.     PostMessage (pApp->MainWindow->HWindow, WM_CLOSE, 0, 0);
  433.  
  434.   pServer->fRelease = TRUE;
  435.     return OLE_OK;
  436. }
  437.  
  438.  
  439. /*
  440.     callback Execute
  441.     -------- -------
  442.  
  443.     if your app supports DDE execution commands then you would handle this
  444.     event
  445.  
  446.     since we don't we return OLE_ERROR_COMMAND
  447. */
  448. OLESTATUS FAR PASCAL _export
  449. TOLEServer::Execute (LPOLESERVER /*lpOleSvr */,
  450.                        HANDLE      /* hCommands */)
  451. {
  452.     return OLE_ERROR_COMMAND;
  453. }
  454.  
  455.  
  456.  
  457. typedef OLESTATUS FAR PASCAL _export (FAR *LPSRVRCREATE)(LPOLESERVER, LHSERVERDOC, const char far *, const char far *, LPOLESERVERDOC FAR *);
  458. typedef OLESTATUS FAR PASCAL _export (FAR *LPSRVRCREATEFROMTEMPL)(LPOLESERVER,LHSERVERDOC,const char far *, const char far *, const char far *, LPOLESERVERDOC FAR *);
  459. typedef OLESTATUS FAR PASCAL _export (FAR *LPSRVREDIT)(LPOLESERVER,LHSERVERDOC,const char far *, const char far *, LPOLESERVERDOC FAR *);
  460. typedef OLESTATUS FAR PASCAL _export (FAR *LPSRVROPEN)(LPOLESERVER,LHSERVERDOC, const char far *, LPOLESERVERDOC FAR *);
  461. typedef OLESTATUS FAR PASCAL _export (FAR *LPSRVREXECUTE)(LPOLESERVER, HANDLE);
  462. typedef OLESTATUS FAR PASCAL _export (FAR *LPSRVREXIT)(LPOLESERVER);
  463. typedef OLESTATUS FAR PASCAL _export (FAR *LPSRVRRELEASE)(LPOLESERVER);
  464.  
  465.  
  466. /*
  467.     InitVTBL
  468.     --------
  469.  
  470.     create thunks for OLESERVER method callback tables
  471. */
  472. BOOL
  473. TOLEServer::InitVTBL (HINSTANCE hInstance)
  474. {
  475.     _vtbl.Create = (LPSRVRCREATE) MakeProcInstance ((FARPROC) Create, hInstance);
  476.     _vtbl.CreateFromTemplate = (LPSRVRCREATEFROMTEMPL) MakeProcInstance ((FARPROC) CreateFromTemplate,
  477.                                                                        hInstance);
  478.     _vtbl.Edit = (LPSRVREDIT) MakeProcInstance ((FARPROC) Edit, hInstance);
  479.     _vtbl.Exit = (LPSRVREXIT) MakeProcInstance ((FARPROC) Exit, hInstance);
  480.     _vtbl.Execute = (LPSRVREXECUTE) MakeProcInstance ((FARPROC) Execute, hInstance);
  481.     _vtbl.Open = (LPSRVROPEN) MakeProcInstance ((FARPROC) Open, hInstance);
  482.     _vtbl.Release = (LPSRVRRELEASE) MakeProcInstance ((FARPROC) Release, hInstance);
  483.  
  484.   return _vtbl.Create != NULL &&
  485.          _vtbl.CreateFromTemplate != NULL &&
  486.          _vtbl.Edit != NULL &&
  487.          _vtbl.Execute != NULL &&
  488.          _vtbl.Open != NULL &&
  489.          _vtbl.Release != NULL;
  490. }
  491.  
  492.