6.4.1 Starting a Server Application

When a server application starts, it should follow these steps:

1.Register window classes and window procedures for the main window, documents, and objects.

2.Initialize the function tables for the OLESERVERVTBL, OLESERVERDOCVTBL, and OLEOBJECTVTBL structures.

3.Register the clipboard formats.

4.Allocate memory for the OLESERVER structure.

5.Register the server with the library by calling the OleRegisterServer function.

6.Check for the /Embedding and /Embedding filename options on the command line and act according to the following guidelines. (Applications should also check for -Embedding whenever they check for these options.)

If neither /Embedding nor /Embedding filename is present, call the OleRegisterServerDoc function, specifying an untitled document.

If the /Embedding option is present, do not register a document or display a window. (In this case, the server takes actions only in response to calls from the server library.)

If the /Embedding filename option is present, do not display a window. Process the filename string and call the OleRegisterServerDoc function.

The OLESERVERVTBL, OLESERVERDOCVTBL, and OLEOBJECTVTBL structures are tables of function pointers. The server library uses these structures to route requests from the client application to the server. The server application should create the function pointers in these structures by using the MakeProcInstance function. The functions should also be exported in the application's module-definition file.

The OLESERVER structure contains a pointer to an OLESERVERVTBL structure. The OLESERVERVTBL structure contains pointers to functions that control such fundamental server tasks as opening files, creating objects, and terminating after an editing session. Several of the functions pointed to by the OLESERVERVTBL structure cause the server to allocate and initialize an OLESERVERDOC structure.

The OLESERVERDOC structure contains a pointer to an OLESERVERDOCVTBL structure. The OLESERVERDOCVTBL structure contains pointers to functions that control such tasks as saving or closing documents or setting document dimensions. The OLESERVERDOCVTBL structure also contains a function that causes the server to allocate and initialize an OLEOBJECT structure.

The OLEOBJECT structure contains a pointer to an OLEOBJECTVTBL structure. The OLEOBJECTVTBL structure contains pointers to functions that operate on objects. After the server application creates an OLEOBJECT structure, the server library gives information about the structure to the client library. The client library then creates a parallel OLEOBJECT structure (including internal information identifying the server application, the document, and the item for the object) and passes a pointer to that structure to the client application.

This hierarchy of structures—OLESERVER, OLESERVERDOC, and OLEOBJECT—makes it possible for a server to open as many documents as the library requests and for each document to contain as many objects as necessary.

A server application can register the clipboard formats by calling the RegisterClipboardFormat function for each format, specifying Native, OwnerLink, ObjectLink, and any other formats it requires.

When the server application starts, it creates an OLESERVER structure and then registers it with the library by calling the OleRegisterServer function. When this function returns, one of its parameters points to a server handle. The library uses this handle of refer to the server, and the server uses it in calls to the server-specific OLE functions.

If an OLE server application is also a DDE server, the class name specified in the call to the OleRegisterServer function cannot be the same as the name of the executable file for the application.

When a client working with a compound document opens a linked or embedded object for editing, the client library starts the server using the /Embedding command-line option. The server uses this option to determine whether the object has been opened directly by a user or as part of an editing session for linked and embedded objects. (If the object is a linked object, the /Embedding option is followed by a filename.) When a server is started for an embedded object with the /Embedding option, the server should not create a document or show a window. Instead, it should call the OleRegisterServer function and then enter a message-dispatch loop. (If the server is started with the /Embedding filename option, it should also call the OleRegisterServerDoc function.) The server then takes actions in response to calls from the library. The server should not make itself visible until the library calls the Show or DoVerb function in the OLEOBJECTVTBL structure. (Server applications should check for both –Embedding and /Embedding.)

By calling the OleBlockServer function, a server application can cause requests from the client library to be saved in a queue. When the server is ready for the server library to process the requests, it can call the OleUnblockServer function. It is best to use the OleUnblockServer function prior to the GetMessage function in a message loop, so that all blocked requests are unblocked before getting the next message. (Often a server returns OLE_BUSY instead of calling OleBlockServer. Returning OLE_BUSY has two advantages: It allows the client to decide whether to retry the message or discontinue the operation, and it allows the server to choose which requests to process.)

When an error occurs in a server-supplied function, the server should return the OLESTATUS error value that best describes the error. The OLE libraries use these error values to help determine the appropriate behavior in error situations. However, the client application does not necessarily receive the error values the server returns; the OLE libraries may change error values before passing them to the client application.