• multi-tasking or multi-threading of a single application, which 14. Advanced Windows Concepts allow parts of an application to still move ahead with useful This section will survey some advanced concepts used in MS- computations even though other parts of the same application Windows programming. First, we will look at a number of are blocked. forms of Inter-Process Communication (IPC). IPC is the generic Optional Readings: the rest of the chapters from [Shildt95] term used for passing data between different processes, programs, or threads: • The clipboard can be used to cut and paste not only within one application, but between applications. • Drag-And-Drop is a feature for dragging a file to an application window or icon, and having the destination application know what to do with it (and if not running, to be started to deal with it). • Dynamic Data Exchange (DDE) is a simple way for a data server process to allow access by client processes. • Object Linking and Embedding (OLE) has developed past simple embedding another application’s objects (e.g. diagrams or tables) in a document. • Component Object Model (COM) is the underlying mechanism by which the sophisticated features of OLE can work; in fact COM has recently been extended to provide inter- communication between application running on different computers (‘Distributed COM’). We will also briefly look into Dynamic Link Libraries, which allow run-time linking to application or system procedure libraries. Finally, if time permits, we may discuss: • how some of the complications of Windows programming can be abstracted and simplified using a ++ OO class library of various window and control types.

14-1 14-2 14.1 The Clipboard TABLE OF CONTENTS: The clipboard is commonly used to cut and paste data from one 14. Advanced Windows Concepts...... 14-1 window to another. This works well between windows of the 14.1 The Clipboard...... 14-4 14.1.1 What Is The Clipboard? ...... 14-4 same application because they use the same format to represent 14.2 File Drag And Drop...... 14-6 the data. Think, for instance, of a word processor which must 14.3 Dynamic Data Exchange...... 14-8 transfer bold, italicized, underlined, colored text of various fonts 14.3.1 Client/Server Architecture ...... 14-8 from one portion of a document to another (or from one 14.3.2 Connections...... 14-8 document to another in the same application, or from one 14.3.3 DDE Scenarios...... 14-10 program instance of an application to another instance of the 14.4 Object Linking and Embedding...... 14-13 14.4.1 OLE 1.0...... 14-13 same application). The representation which communicates the 14.5 Dynamic Link Libraries ...... 14-15 text and formatting must be understood by the destination 14.6 OLE 2 and COM ...... 14-18 window, otherwise the clipboard data transfer result would be 14.6.1 Component Object Model...... 14-19 garbage. 14.6.2 GUIDs ...... 14-20 14.6.3 Component Interfaces ...... 14-21 Windows also facilitates cutting from one application’s window 14.6.4 Interface = Pointer to Table of Pointers to Functions ...... 14-23 and then pasting the data into another application’s window. 14.6.5 Remote Procedure Calls...... 14-26 14.6.6 COM Classes/Objects ...... 14-27 This works as long as the destination window’s application can 14.6.7 Other Elements of OLE 2...... 14-28 properly interpret the data representation. Even plain 14.7 Multiple Document Interface ...... 14-31 unformatted text can be difficult, because foreign language 14.8 GUI Class Libraries ...... 14-32 applications often use a multibyte (16 bit per character) 14.8.1 Object Windows Library (OWL) ...... 14-32 representation to store special characters which have accent 14.8.2 Microsoft Foundation Classes (MFC)...... 14-34 marks. 14.9 References ...... 14-39 14.1.1 What Is The Clipboard? The clipboard is region of shared global memory managed by the GUI OS for cut and paste purposes. There are about 16 functions in the clipboard API. Before writing to the clipboard, an application must: 1) First, obtain rights to a hunk of shared global memory. 2) Then ‘lock’ that region, so that no other application can read or write to it while your application is writing to it. If another application were to read it when it was only half written by your application, it might read half an integer that was written and the other half garbage from what was previously in 14-3 14-4 the memory. As discussed in any operating systems course, two 14.2 File Drag And Drop applications both writing to shared memory at the same time is a recipe for problems. File drag-and-drop is a feature which allows a user to drag a file using the mouse, and drop it on (i.e. release the mouse button When finished with the clipboard, your application must unlock, over) some other application icon. and give up your pointer/rights to it before closing the application, so that other applications can subsequently use the When an application implements the drag-drop feature, a user clipboard memory. can select one or more files in File Manager, drag them to a non- running application’s icon or running application’s window Any number of clipboard viewers can be monitoring and (whether it is fully visible, or minimized to an icon), and drop displaying the contents of the clipboard memory at the same them there. The application in which the files were dropped is, if time (cf. MVC - model and multiple viewers), though this is necessary started and receives a WM_DROPFILES message. feature is seldom used. This allows the target application to obtain the file name(s) and the coordinates of the point at which the files were dropped. The file drag-and-drop API contains 4 functions. Before an application can accept dropped files, it must first call the DragAcceptFiles() function to register its interest in receiving WM_DROPFILES messages in a particular window(s). The WM_DROPFILES message contains the handle of an internal data structure which the application can query, using DragQueryFile(), to find out the number and name(s) of the files that were dropped. The DragQueryPoint() function returns the window coordinates of the cursor when the user released the mouse button, in case it is important to the destination application whether the file was dropped, say, in the left or right portion of the window. To free the memory allocated by the system for the WM_DROPFILES messages, an application should call the DragFinish() function when it is no longer interested in accepting drops. Here is a simple example. Recall that a window is sent a WM_CREATE message by Windows right after being created, and a WM_DESTROY message when it is being closed. This allows a window to prepare itself in many ways (registering

14-5 14-6 interest in accepting drops is only one), and to gracefully wind 14.3 Dynamic Data Exchange its life up: DDE was the first, and is the simplest way for programs/ processes/threads to exchange data without user intervention case WM_CREATE: DragAcceptFiles(hwnd, TRUE); (recall that the clipboard and drag-and-drop required the user to break; perform some action). DDE is thus an excellent example of IPC. DDE is simpler than OLE, so we will look at it first. case WM_DROPFILES: //handle dropped file(s). There is also a new API called DDE Management LIbrary break; (DDEML) that makes DDE even simpler. We will not study case WM_DESTROY: DDEML so as to concentrate on the fundamentals. DragFinish(hwnd, FALSE); break; 14.3.1 Client/Server Architecture DDE is based on a client/server architecture. A server is a program/process/thread that provides services to clients. In the You should know that there is another, more advanced form of case of DDE, a server is the process with data that some other drag-and-drop available with Object Linking and Embedding. It process wants. It is clients which initiate a connection. allows you to drag an object (e.g. wordprocessor paragraph, drawing tool drawing, spreadsheet table) and place it on any It is possible for a server to handle connections from several window that is ‘OLE drag and drop enabled’ (e.g. place it on a clients at once. Similarly, it is possible for a client to call several compound document which can ‘contain’ several objects, or on a servers to get the various data the client needs. OLE-enabled listbox, etc). DDE only allows one way data movement: from the server to the client process (though it is possible to ‘poke’ short control messages the other way). This does not mean that the server can’t also start a second connection, to set up a reverse communication path. In this case, both processes are acting as both clients and servers. DDE uses, as its underlying mechanism, the messaging system built into MS-Windows that we have previously studied. 14.3.2 Connections A connection is initiated by a client broadcasting WM_DDE_INITIATE to all Windows programs indicating what data it needs. What data is needed is specified by three strings: the application, the topic, and an item within a topic.

14-7 14-8 The application is the name of the server program that is to be 14.3.3 DDE Scenarios called. There are 3 types of links that are possible using DDE: The topic is one of several topics that a server could provide. 1) Cold links - wherein a client simply requests one time data For instance a census server could have topics like population from the server. distribution by postal code areas, population distribution by income, population by religion, etc. The client must specify 2) Warm Links - wherein a client requests data, and also which topic of data it is interested in. requests to be informed if that data is updated (e.g. biology simulation where population grows by the minute). Finally, there is item within a topic. For instance, British Columbia Population by postal code areas. 3) Hot Links -wherein the client requests data, and requests that updated data be sent to it when the data changes. Note that any of the above three strings could be NULL, Here is a time-space diagram showing the connection scenario indicating you wanted data from any willing server program, or all topics of population data (say regarding BC), or all for a cold link. Note that the time axis is down the page. province’s data. Client Server To make the capabilities of DDE very clear, in an Excel spreadsheet, you could have a cell whose formula was: WM_DDE_INITIATE(which data?)

=myServer|population|BC WM_DDE_ACK(ack (or nack)) This will cause Windows to actually start a program called myServer.exe if it is not already running. (Note: myServer.exe WM_DDE_REQUEST(item spec.) must be located on the search path of the OS). This is an amazingly powerful capability! WM_DDE_DATA(item spec. and value) Generally a connection is attached to a server window which is hidden (never ‘shown’ to the user). The callback function of this WM_DDE_REQUEST(item2 spec.) class of window acts as the server process. Windows calls it anytime it wants to send that server a message. In particular, it WM_DDE_ACK(nack) sends this callback function the WM_DDE_INITIATE message. This server process will respond by sending back a WM_DDE_ACK message to acknowledge that it is willing to WM_DDE_TERMINATE accept the connection. There is another very interesting type of message, WM_DDE_TERMINATE WM_DDE_EXECUTE, which allows client to send the server process a command string to be ‘run’.

14-9 14-10 Cold Link Notes: Note in particular, that after getting some data, the client • The server can be programmed to request acknowledgments expresses its desire to be advised of any changes to the data it from the client, to make sure the data got to the client and got just obtained. The advisory is sent as a valueless data message there correctly. to the client. At that point, the client must decide whether it actually wants a copy of the revised data, and if so, requests it. • Either process can start the termination process. The above scenario illustrates the client starting the termination. In contrast, here is a time-space diagram of a hot link: • Most importantly, when using a cold link, the client is not Client informed of any changes that happen to the server’s data Server during the duration of the connection. The client is in essence, WM_DDE_INITIATE(which data?) just polling the server for item values when it feels like it. WM_DDE_ACK(ack (or nack)) WM_DDE_REQUEST(item spec.) Now let us look at a time-space diagram for a warm link: WM_DDE_DATA(item spec and value) Client Server WM_DDE_INITIATE(which data?) WM_DDE_ADVISE(item spec. ) WM_DDE_ACK(ack (or nack)) WM_DDE_REQUEST(item spec.) WM_DDE_DATA(spec. and value) WM_DDE_DATA(item spec and value)

WM_DDE_ADVISE(item spec., notify only) WM_DDE_TERMINATE WM_DDE_TERMINATE

WM_DDE_DATA(spec. , no value) Here you see that a hot link presumes the client always wants the actual updated value of the data item of interest, not just WM_DDE_REQUEST(item spec.) notification of a change. Instead of just notifying the client, it WM_DDE_DATA(item spec and value) fires the updated value down the connection immediately upon any change WM_DDE_TERMINATE Not shown in the above warm and hot link scenarios is the WM_DDE_TERMINATE WM_DDE_UNADVISE message. Its purpose is to inform the server of ceased interest in changes of a particular data item. 14-11 14-12 14.4 Object Linking and Embedding - disadvantage: larger compound document. And may have several compound document that wastefully contain the same OLE stands for Object Linking and Embedding. But Microsoft component is discouraging the use of the full name, because with OLE 2.0, • When including by reference, the compound document simply it has become much more than that. So they just want you to contains a link to the actual component. This may simply take call it (like the Mexican) “ole”. the form of a path and filename. - advantage: smaller compound documents, and no redundancy if 14.4.1 OLE 1.0 multiply included in several compound documents. OLE 1.0 was originally built on top of DDE. This foundation - advantage: if component file is updated, then all compound was found to not to be sophisticated enough for OLE 2.0, so 2.0 documents that include that component are automatically was built on top of the Component Object Model (COM). updated upon opening/re-opening of the compound document. - advantage: can even use ‘hot’ links. In this case, the compound In this section I will briefly describe the original features of OLE document registers its interest in being advised of changes in the 1.0 (which still exist in OLE 2). component. Any changes in the component can be programmed to immediately propagate to all compound documents that The idea is that certain computer applications can create include it and have registered for hot updates. compound documents. Compound documents are ones that include components (such as diagrams, tables, spreadsheets) Not only does it appear that authors of the compound document created by other applications. Compound documents are are able to update the component, but in addition, authors of the sometimes called containers. component diagram/spreadsheet are able to update the compound document. i.e. there seems to be two way data If the user double clicks on the component within a compound movement possible. document, the application that created the component is automatically launched (e.g. a diagram editor, or a spreadsheet program). The user can make changes to the diagram or spreadsheet, and then exit that application. There are generally two ways that a component can be included in a container: by reference or by embedding. The viewer of the container/compound document cannot tell the difference; they just see a component in a document. • When including by embedding, the actual component is contained in the compound document, along with it’s type and which application to launch for it. - advantages: the component is stored locally, and can be copied/ transferred with the container to anywhere.

14-13 14-14 14.5 Dynamic Link Libraries • All OS’s that support a DLL feature allow a program to not link to the DLL at program start up, but only if the user Before we discuss OLE 2 and COM, you must understand the executes a part of the application that requires it. A good concept of dynamic linking. example might be the spell checker code for a word processor. A library is a file of object code from one or several modules Why take up RAM with this if you are not going to spell check (i.e. from one or several .obj files originally compiled from one that session? So DLLs can be brought in on demand using a or several source files). Of course each module typically exports call to LoadLibrary(). A reference count of the number of several functions. A library is thus a kind of reactive software running applications that use that DLL is maintained. When an component, possibly originally written in several pieces. Most application that uses a DLL ends, it decrements the reference programs statically link all kinds of libraries into their code in count. When the reference count reaches zero, the DLL is order to make the application work. Examples are I/O functions, removed from RAM (i.e. can be overwritten). math functions, memory managers, thread managers, etc. Each process using a DLL uses it own stack to pass the DLL its There are many reasons not to ‘statically’ link libraries into an call parameters. A DLL function invocation (thread) receives its application: parameters on the caller’s stack, and any local variables it declares for that call are on the caller’s stack. But, a DLL’s • You shouldn’t statically link OS functions into an application, global variables and heap are shared by all calling programs because when the OS is upgraded to a new version, you must (suggesting the occasional need for semaphores to protect recompile your application and distribute it to all your critical sections - cf. Cmpt 300). customers. This is silly. All operating systems have a run- time method of calling OS services. In MS-DOS, it was to The functions that a DLL exports are advertized in an interface/ invoke a software interrupt, INT 21h. Some brands of header file. Sometimes types and constants are also exported. processors even have a special machine/assembly language Usually, variables are not. instruction for accessing the OS executive (it is usually named When you link a program that may call to a DLL, the application EXEC). MS-Windows uses the concept of a dynamic link is actually statically linked to an ‘import library’ of proxy library (DLL). functions for that DLL. (Import libraries are easy to make. • Another reason is that most programs simultaneously running Most development environments contain a command that will on a multi-tasking OS need access to the same I/O function read a .DLL file and automatically create an import .LIB file libraries, etc. Why should we needlessly link this library code which corresponds to it.) The import library identifies the name into each application, thus wasting valuable RAM, if two of the .DLL file which contains the called functions, and the applications are running at once. Why not just have one DLL proxy functions are programmed to call either the 1st or 2nd or loaded (whose functions are re-entrant) and have both 3rd ... function in the DLL. The proxy functions call the actual applications use it. In fact, these are called shared libraries in function in the DLL indirectly, via some kind of table of the OS. function pointers (like a vtable) which is at a known location inside the DLL.

14-15 14-16 The table ensures that changing the length of a function 14.6 OLE 2 and COM implementation in a later version of the DLL does not mess things up for a client. You must be careful when shipping an You have probably used compound documents and OLE updated version of a DLL to customers, in that the functions in already. Whenever you invoke the draw tools in Microsoft the new version must be in the same order in the table, and have Word, you are probably launching Microsoft Paint. The draw the same parameters as in the earlier version. The updated tools appear to be part of Word, but in all likelihood they just use version can have revised function implementations and more OLE to integrate painting seemlessly into Word. functions, but not less or different. This might seem easy since Microsoft makes both products. But Note that DLLs must export two functions: OLE 2.0 provides the infrastructure so that client applications 1) LibMain() which allows the DLL to initialize any static (be they compound documents or plain applications), and variables, open files, or whatever preparation is needed reactive component libraries, can be programmed to interact. In before any calls are allowed to it. For Win32, this function addition, this is done without the need for each other to know has been renamed DllEntryPoint(). proprietary details of the other company’s software. This is basically hidden/abstracted behind publicly-registered 2) WEP() which is an exit procedure, that Windows calls ‘interfaces’. before unloading the DLL after all clients are finished. This allows the DLL to free any dynamic memory, close files, Before an application can be involved in OLE 2 cooperation, it etc. If your DLL does not have any of these to clean up, must link to either the OLE libraries or the COM libraries by you needn’t program a WEP() function as most calling either OleInitialize() or CoInitialize(). This prepares the development environments will supply one by default. ’s internal component interaction infrastructure for use. Then a container or application can find out what component services are available from other reactive software components (i.e. from currently running programs, from other not running programs mentioned in a registry, and even from other computers (Distributed COM)). Though originally designed for communication between software components running in different address spaces of the same machine, you can actually use OLE to allow components in the same address space (i.e. same program or thread) to interact, and to allow components that are not even in the same country to interact. And from the ’s point of view, these three cases are basically interchangeable so the same code works for all three.

14-17 14-18 14.6.1 Component Object Model 2) Sometimes several applications use the same DLL, so instead of putting one copy in each application’s directory, The component object model (COM) is a specification for they are best put in /Windows/System. dynamically-linkable, binary reactive software components. It is binary in that you can call functions in these DLL-like 3) Generally, the name of the DLL file is hard coded into an libraries in any computer language. And these components can application. But if you want several different spellcheckers be written in any language. available (e.g. for different spoken languages, some with accented characters), they can’t all have the same name if Do not let Microsoft’s use of the term ‘object’ confuse you. they are in the same directory! They do NOT mean ‘classes’ and ‘instances’, even though 4) Also, if you ship a new version of the wordprocessor, you Microsoft sometimes also uses those terms to when describing would like the user to still be able to use his old special, COM. Instead, they use both the terms ‘object’ and ‘class’ to foreign language spellchecker component! mean a reactive software component (i.e. module or program). And they use the term ‘instance’ to mean a handle which can be This leads to the need to identify components by some other used to invoke the functions of that component, (kind of like a means than a path and file name. pointer to a vtable). 14.6.2 GUIDs It is a binary interface since it specifies how these components should interact at the bit, byte, and communication packet level. The scheme adopted anticipated the difficultly of avoiding You can program to this specification in any language. Though identifier conflicts among software vendors on a worldwide in Microsoft’s world ‘any language’ usually means either C or basis. COM libraries are purely functional; they do not export C++, in fact they have made it very general (COBOL?). To be global variables. The interface specification that the client more exact, any language that supports pointers. programmer needs is thus just a set of function prototype signatures (and possibly types and constants used to call the There are a number of problems that led to the creation of COM functions). The server programmer who first defines the component interaction infrastructure: interface assigns to it a Globally Unique IDentifier (GUID). 1) Often there is a need to supply enhancements to software This identifier is supposed to be unique in space and time! By after the user has purchased and installed the software. I this, I mean: don’t mean later versions here, but instead added features. • No two working for the same company should In fact, I mean features that can be added by a different pick the same GUID. This can be satisfied if they use only one component vendor than the one who wrote the application. machine which maintains a list of which ones have already One way to do this is to use Dynamic Link Libraries been allocated to an interface specification. (DLLs). They allow the linking of some components of an application at application load time, or even later only when • When the interface is changed, it should get a new GUID. the user selects some feature (e.g. spell checking). This means the GUID ‘could’ be composed of a checksum of all the characters of the interface. But such a strategy is confused by changing the comments in an interface, and also doesn’t work when dealing with world uniqueness. 14-19 14-20 • Different vendors anywhere in the world must not be allowed much like a module when programmed in a non-OO language to use the same GUID. This either means there must be some like Modula-2 or C. central registry, or you must rely on random numbers. Note that a component can export via several interfaces. The solution had already been found by the Open Systems Consider even a mathematical function library. It could Foundation (OSF) Distributed Computing Environment (DCE) advertise the trigonometric functions in and the specification. The idea was to use the 48 bit identifiers burned exponential/log functions in . These are each defined into Ethernet network boards. These are unique so that two interfaces to the one math function library. This is what is meant computers can be connected to a computer network without fear above when I said that a component can expose more than one of having the same network address. They are centrally interface! managed by Xerox (who was a co-developer of Ethernet) to be An interface specification can be written in any language. globally unique. Network board manufacturers are give non- Generally it looks like a header file with functions and types for overlapping ranges of numbers to burn into the boards they are manufacturing, and promise not to manufacture any two boards parameters. I do not believe it can export constants or variables. the same. If an interface is going to be called from another language or So GUIDs used in COM are 128 bit (16 byte) numbers machine, it is best to write the interfaces in an ‘interface computed using the 48 bit network board number, and that definition language’. An interface definition language is one in computer’s current date and current time. As long as you are which you can very carefully express a function call. In careful of time zone or daylight savings time changes (or particular, it is necessary to specify which parameters are alternatively, always use Greenwich Mean Time), the generated feeding data to the function, which are feeding data back out to the caller, and which are doing both. The reason this is GUIDs will be unique in space and time. The only investment important is that if the implementation is called from another needed by a company is a hundred dollar circuit board which computer, the parameters must be passed to the implementation they probably have anyway for their inhouse network. via a data communication network, and the results must be 14.6.3 Component Interfaces passed back (I call this ‘pass by value, return by value’). Since OLE and COM are designed to allow processes running in A COM binary is a dynamic link library or an executable different address spaces to call each other, pass by reference just program that exposes one or more interfaces to other windows doesn’t work. (Note: The language ADA developed way back in programs. Again note that Microsoft often calls these ‘83 has always forced programmers to define parameters as ‘component objects’, or just ‘objects’, but they are NOT like either IN, OUT, or INOUT). C++ objects. What’s worse, Microsoft starts referring to instances of component objects, but again, these are not C++ As a result of the OSF’s Distributed Computing Environment object instances. (DCE) project, and the Common Object Request Broker Architecture (CORBA) project, a common interface definition The interface for a component is a set of callable functions. language has been defined called, not surprisingly, IDL. That’s it. That’s all that is exported. That’s all a client process Microsoft has made minor extensions of it and calls their flavor, gets access to through that interface. In essence, a component is not surprisingly, MIDL. Note that IDL looks a lot like a C 14-21 14-22 header file, but it is not C! It is a subset of C (without any space (or even on a separate CPU), but one of COM’s executable statements), but which has also been extended to responsibility is to make this transparent (to quote Star Trek define the exact direction of parameters (in, out, or in/out), and TNG “Make it so!”). Actually, COM returns to the client a to allow the interface to be identified by a GUID. Finally, you pointer to a pointer to the table. The first pointer is in the can specify whether a char* is a pointer to a character, or a client’s address space and is passed into CoCreateInstance() so pointer to a null terminated string stored in a character array. that it can be set by CoCreateInstance(). It is set to point to the second pointer which is in system shared memory along with the IDL translators (also called ) have been written to table the second points to (the application is not allowed to translate IDL to various languages. You can use an IDL declare pointers in system shared memory). translator to translate the IDL to an actual C header file, to a C++ header file, or to other language’s natural module definition system’s system’s server’s files. The implementation module associated with that header client’s pointer table file can include it, and be written to appropriately implement it. pointer functions Similarly, a client can include it to declare prototypes of the functions before they are called. If the client is written in a different language than the implementation, the IDL will have to be translated into that language before being used by the client! 14.6.4 Interface = Pointer to Table of Pointers to Functions Since COM is a binary (i.e. language independent), run-time (i.e. dynamically linkable) standard, it specifies in exact detail how a In client’s In OS system’s In server’s client calls a function provided by an interface. In particular, a address client must first call a function (usually CoCreateInstance()) to address shared global prepare the interface to be called (it doesn’t really create a C++ space address space space instance, because you needn’t even be programming in an OO language!). CoCreateInstance() in fact returns a pointer to a Interestingly, the client’s pointer seems exactly like a pointer to table of pointers to the functions that implement that interface. a dynamically polymorphic C++ object instance. IDL in fact (You might want to think of this as loading into RAM and translates interfaces into C++ header files as C++ classes which starting a program instance or DLL which exports those have no data members and only virtual functions! If you are functions). The caller specifies the GUID of the interface it programming in C++ (rather and C or Modula-2), a COM object wants, and COM finds a program or DLL which implements that seems like a C++ class instance whose only field is a pointer to interface in the operating system’s registry. It then loads that the vtable! But it is just a handle that points to a DLL or program/DLL, starts it, and constructs the table of pointers (to program that can react (i.e. has functions). the functions) in shared global memory (memory mappable into The C++ class constructed is derived from the class IUnknown. both the client’s and server’s address space). Note the function Note that class IUnknown is defined as: bodies themselves may be in the server component’s memory

14-23 14-24 class IUnknown { (**ppvtable)->SetMyComponentState(ppvtable, 13); virtual HRESULT QueryInterface( REFIID iid, void** ppvtable); 14.6.5 Remote Procedure Calls virtual ULONG AddRef(); virtual Release(); When the function you are calling resides on another machine, }; the vtable at the client end points at a set of local ‘proxy’ Here is an example of how a C++ programmer creates his own functions whose job it is to ‘marshal’ the IN parameters into a reactive component interface definition: data packet to send over the computer network to the other machine. And in that other machine, there is a COM receiver class myServerComponent: public IUnknown { always listening that takes those incoming data packets, unpacks virtual void setMyComponentState(int i); them into variables in a ‘stub’ procedure local to the server virtual int getMyComponentState(); }; machine, and then calls the actual function. When the actual function returns, the stub marshals the values that must be Notice that there are no member data attributes. All data returned into a packet to be sent back over the network to the retained by a COM component must be accessed through get/set client machine. The COM receiver dispatches these to the functions. Remember it is like a library module; it can have appropriate proxy function which then returns to the client hidden module variables and arrays, pointers to linked lists, and program. files. But they are not directly exported, a component must supply a set of functions for accessing them. Client App. Remote OS So if I have obtained a ppvtable from COM, then I can call COM receiver reactive COM component functions in C++ as: ptr ppvtable->SetMyComponentState(13); Local OS stub2 This dereferences the client’s pointer to get the dataless component instance, then invokes the instance’s virtual function proxy1 (which in C++ causes two more indirection dereferences). vtable function2 In C, you have to program the two extra dereferences manually. proxy2 I also believe that in some circumstances in C you must pass a pointer to ‘this’ if the COM component was written as a C++ class. If you think about it, a server class instance written in Note: Most calls to OLE and COM facilitated components are C++ has only one hidden data member, a pointer to the vtable. blocking. This is because most PC software was not meant to be And a pointer to that pointer is like a pointer to ‘this’. e.g. reentrant, and you wouldn’t want a client calling a server again before it had finished processing the first request. The new Distributed COM supplied with Window NT 4.0 allows optional non-blocking calls using a feature called ‘freethreading’. This is 14-25 14-26 appropriate as you often don’t want a client to wait for a call that 14.6.7 Other Elements of OLE 2 must traverse the internet. (Of course Unix has had this kind of • OLE defines the architecture for a special kind of structured capability for decades.) storage. In particular, it provides for storing and receiving 14.6.6 COM Classes/Objects components (like spreadsheets or diagrams) that reside inside containers (like wordprocessor documents). Often a reactive component/server exports several different • OLE Automation is the ability for an application to expose a interfaces. Once you have access to the server via one interface, way for other programs or tools to programmatically say from CoCreateInstance(), you can easily use the function manipulate components created and stored by the first (i.e. it QueryInterface() find out if it supports others, without calling automates the controlling of another application, without user CoCreateInstance() (after all, the server is now already running intervention). Thus the first does not have to reveal its and we don’t need another copy of the server program running). proprietary component implementations and data In particular, a server might support both an older version of an representations, yet allows other applications to use that interface, and also a newer one (with more function signatures). component. A good example is an analysis CASE tool which Each version is identified by a unique GUID. stores Object Relationship Diagrams, Object Communication In fact, a number of interfaces that provide roughly similar Diagrams, and Finite State Machine Diagrams. Often you services are often grouped together in what is called a COM want another program which goes in and finds out all about the ‘class’ (also called a COM ‘object’), again neither term being underlying diagrams and prints out a report on each object, its related to C++ objects. This is a set of functions (possibly for attributes, its member functions, its states, etc. Exposing several interfaces) implemented in a single DLL or program. access to the underlying model in the CASE tool without The family has a family ID called a CLSID. A CLSID is a actually allowing the report generator access to the model files, GUID, and is also listed in the OS’s registry. When a program allows the CASE tool vendor to later enhance or change the wants say a spelling checker, it can see if the CLSID file format without breaking the report generator (which may corresponding to a spelling checker is listed in the registry. If not even be provided by the CASE tool vendor, but by another so, that registry entry will contain yet another list of interface company). GUIDs (IIDs) which contain all the installed spell checker • Such a report generator is called an OLE Automation interfaces. And each one of those specifies which server Controller, because it controls (in this case, accesses) aspects program or DLL needs to be run to use it. Some might be from of an OLE Automation component like the diagram models. Microsoft, others might be from Germany, or Japan, etc. Not only that, the word processor vendor did not even have plan that • This is not to be confused with OLE Controls, which are specific other components would work with his software, only to special components you can put in a container, whose job is to have his client ask to connect to one. Later, the user can add selectively expose and provide access to the interfaces of the various other components in the container. updated components from the vendor of the application, or from some different company which sells ‘components’. Here is a rough ORD which tries to explain the various elements in the COM architecture.

14-27 14-28 You can see from the above diagram that an OLE Control is a subclass of an OLE Automation Server, which is a subclass of a Binary Object Component. A component (which is also called a COM object (i.e. reactive s/w or COM class) has a GUID and one or more associated component) Interfaces (which also have their own GUIDs). A number of IsA Components can be available from a binary object. InProcess binary objects are typically implemented in .dlls. OutOfProcess binary objects are often implemented by proxy processes which InProcess OutOfProcess send messages to a different address space (possibly in a Binary Object Binary Object completely different computer). [Petzold96] has one chapter on OLE and COM. Petzold also Is Implemented recommends “Inside OLE” by Kraig Brockschmidt Has Has [Brockschmidt95]. And there is a new book out by Microsoft Is Imple- by mented by Press on ‘ActiveX’, which is just a new name for what is, for the most part, just the 1997 version of OLE/COM. DLL proxy.exe In summary, COM allows application programmers from a company other than Microsoft to ‘call’ a function interface exported by such COM-enabled binary executables such as Word, Excel, or DLLs, and to have these binaries loaded from COM Object Interface (fnc. prototypes) disk and started if they are not already running. These binary Has library files export component objects such as spreadsheets, * GUID *GUID spreadsheet cells and ranges, paragraphs, spellcheckers, and other kinds of widgets. As a result, a big application system can now be built by cobbling together a bunch of these already -must support Interface IUnknown. written (but not linked) reactive software components. Each component might have been written by a different company. IsA Some can be small and some, like Word, very large. Such an application implements its command scenarios using OLE Automation Server dynamically-linked function calls between the various -must support Interfaces IUnknown component objects. (Note that this has even created a new IsA and IDispatch. market for useful components that other software developers can use (i.e. ‘componentware’).). OLE Control -must support Interfaces IUnknown, Note: The new Java ‘Beans’ technology may privide - IDispatch, and several more. considerable new market competition to COM/ActiveX.

14-29 14-30 14.7 Multiple Document Interface 14.8 GUI Class Libraries Many Windows programs allow you to open multiple documents Windows was written before OO programming became popular. at once, each in a separate child window. There are several It is thus mainly based on simple function calls. This also made interesting things about MDI child windows: it language-neutral, as an OS should be. Windows tries to be • One thing about these children is that they have no menus; you object-oriented, as it provide a way to classify window instances use the parent window’s menu. You can do this because both by the particular callback function they use, and because it is the parent and the child windows share focus (both of their title based on a message passing architecture. Being based on bars are highlighted). Also, the parent menu changes messages is not really OO, but the Smalltalk language uses the depending on which kind of child window is active (e.g. In the term message for function calls, and it has wrongly become Excel spreadsheet application, depending on whether a associated with OO. worksheet or a graph is the active child). 14.8.1 Borland Object Windows Library (OWL) • You can minimize the child window and it shrinks to an icon at the bottom of the parent’s canvas. In order to provide C++, , and other OO languages with a more powerful, natural, and more abstracted and simple • The parent menu has a top level item called Window, which programming model, class libraries have been written in these allows you to Cascade, Tile, or select from a list of child languages which hide some of the messy details that we have windows. studied. For instance, all windows are derived from a base class, MDI is the Windows API functions that help you program which in Borland’s Object Windows Library (OWL) is called multiple document applications. class TWindow. Many subclasses of TWindow are provided: TControl, TDialog, TFrameWindow, TMDIClient, Note that MDI uses the Model/View/Controller (MVC) TGadgetWindow. And TControl has further subclasses like architecture. It is just that the views are of possibly different TButton, TScrollBar, TEdit. Default callback functions are models/documents (which of course is allowed by the MVC provided. Often you want to override them, but that is ok as you architecture). MDI is just a set of API functions that make it only program what changes you want and then chain back to the easy for application programmers to program applications to parent’s functionality for the rest. handle child windows in the above described way. In fact, often the whole application is programmed as class that is derived from a vendor supplied base application class. To write a basic Windows program, all you do it subclass it and override a very few functions. Here is an example of a minimum Borland OWL application:

14-31 14-32 #include back to the inherited TApplication::Run() to get some default #include behavior which has been pre-programmed for all applications. #include This illustrates the simplified and quite different architecture of a class MyApp : public TApplication { //Create a class for this application, the bulk of OO-language-based Windows program. With these libraries of //the code of which we can inherit from useful, Windows-oriented classes for input control classes and //class TApplication provided by Borland. other stuff, programming MS-Windows can, in the end, seem public: very C++ object-oriented. MyApp() : TApplication(){ //constructor //Note simply chains to base’s constructor. 14.8.2 Microsoft Foundation Classes (MFC) } /*virtual*/ void InitMainWindow(){ Microsoft has a similar set of C++ classes which also provide a //Override inherited main window details. SetMainWindow(new TFrameWindow( similar, true ‘C++’ object interface on the Windows API. The 0, "Russ’s ObjectWindows Program")); Microsoft Foundation Classes (MFC) provides facilities like } those in Borland’s OWL library, though I gather it is a thinner }; veil over the raw C . //------int OwlMain(int argc, char* argv[]) For more information on MFC, see [Prosise96] or [Schildt96] or { return MyApp().Run(); most Visual C++ programming books. You might find it //Default construct an app instance, interesting that in [Schildt96], there is a program written in MFC //invoke its Run() member function, that is similar to his raw API program on Page 50 of [Schildt95]. //and when that returns, end the program. This program uses the WM_PAINT architecture and basically }; writes “Left button is down.” and “Right button is down” where Your main is not called WinMain() but OwlMain(). I’m sure ever you mouse click on the screen. The program from the MFC Microsoft Foundation Class library would require a different book is copyrighted, so I can’t give you a copy, but it on the name ;<). Borland automatically supplies a WinMain() which publisher’s web site www.osborne.com, and I will put a copy in initializes things and then calls your OwlMain(). All your the Cmpt 212 Extra Reading Binder. OwlMain() has to do it call the Run() member function of your application class. Your application class must be derived from The program is broken into two parts: message4.h and class TApplication to make sure it has a Run() member function. message4.cp (though this is not necessary). In the .h file, a main Notice how I supplied a constructor that does nothing but chain window class is derived by you from a base class provided by back to the base classes’ constructor using an initialization list. I Microsoft. And an application class is also derived by you from also supplied an override for the InitMainWindow member one provided. In message.cpp, you write bodies for the main function of the base class which makes my program uniquely window class virtual callback functions, a is written to indicate which Windows messages you are going to handle (the mine. Finally, if I want my application to be behaviorally- rest will be sent to DefWindowProc()). Finally, an instance of interesting, I would have to define my own version of the application class is defined. The base class constructor MyApp::Run(){}. In my Run(), I might want to manually chain (provided by Microsoft) which is chained to runs the program.

14-33 14-34 14-35 14-36 Notice that this is not much shorter than the C program from [Schildt95]. But GUI class libraries do provide a lot of automatic built in functionality, and in general are shorter. They are also more abstracted, organized, and truly object-oriented. You might find it interesting to note that to handle all the different WM_COMMAND messages from child windows like menu leafs and boxes, you need to associate a different callback function with each child ID that might send the owning window class callback function (which is hidden inside MFC) a message. This is done in the message map like this:

BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd) ON_WM_LBUTTONDOWN() ON_WM_CHAR() ON_COMMAND(IDM_ADDMENULEAF, OnAdd) ON_COMMAND(IDM_DELMENULEAF, OnDel) ON_COMMAND(IDM_CLOSEMENULEAF, OnClose) END_MESSAGE_MAP() To indicate your program will accept a regular message like WM_CHAR, you declare it in your message map with the prefix “ON_” and suffix “()”. Then you must provide a virtual callback function called OnChar() with appropriate parameters. On the other hand, there are dozens of WM_COMMAND messages you can receive from different child windows. These are specified with the syntax above. The uppercase parameter is the symbolic name for the child ID from your childid.h file. And the mixed case parameter is the name of the virtual function that you want called when that childid sends a WM_COMMAND message.

14-37 14-38 14.9 References 14.10 Rest Of Course [Brockschmidt95] “Inside Ole” by Kraig Brockschmidt, Microsoft Press, 1995. 14.10.1 Stream I/O (here )? [Petzold96] “Programming ” by Charles Petzold, a stream is an object. Microsoft Press, 1996. iostreams are better because stdio.h because it is safer and [Prosise96] “Programming Windows 95 with MFC” by Jeff extensible. Prosise, Microsoft Press, 1996. Prata has old C++ and standard C++ differences [Schildt95] “Windows 95 Programming in C and C++” by intro to extra string i/o functions Prata p. 102-108 Herbert Schildt, McGraw-Hill, 1995. random I/O [Schildt96] “MFC Programming from the Ground Up” by Binary I/O Herbert Schildt, McGraw-Hill, 1966. 14.10.2 namespaces if time permits prata has 4 pages. 14.10.3 Assert and misc. as time permits 14.10.4 History of versions V.2 of C++ added virtual functions, MI, and virtual inheritance V2.1 has semi-nested classes and delete [] V3 had fully nested classes and templates V4 has exceptions eliminating double construction (see video tapes)

14-39 14-40 14.11 References [Nelson95] “C++ Programmers Guide to the Standard Template Library” by Mark Nelson, IDG Books, 1995, ISBN 1-56884- [Brockschmidt95] “Inside Ole” by Kraig Brockschmidt, 314-3. Microsoft Press, 1995. [Nye90] “X Windows Systems Series, Volume One: [Carrol95] “Designing and Coding Re-usable C++” by Martin Programming Manual” by Adrian Nye, O’Reilly & Associates, Carrol and Margaret Ellis, Addison-Wesley, 1995. 1990. [Coad 91] “Object-Oriented Analysis”, 2nd ed., by Peter Coad [Petzold96] “Programming Windows 95” by Charles Petzold, and Edward Yourdon, Prentice-Hall, 1991 Microsoft Press, 1996. [Comer79] “The Ubiquitous B-Tree” by Douglas Comer, in [Prata95] "C++ Primer Plus" 2nd ed., by Stephen Prata, Waite Computing Surveys, Vol. 11(2), June 1979. Group Press, 1995. [Date 86] “An Introduction to Database Systems” 4th ed., by [Pressman 92] “Software Engineering, A Practitioner’s C.J. Date, Addison-Wesley, 1986 (or later editions) Approach” 3rd ed., by Roger Pressman, McGraw-Hill, 1992. [Deitel94] “C++: How to Program” by H. Deitel and P Deitel, [Rumbaugh96] “To Form a More Perfect Union: Unifying the Prentice Hall, 1994. OMT and Booch Methods” by James Rumbaugh, Journal of [Eckel95] “Thinking in C++” by Bruce Eckel, Prentice Hall, Object-Oriented Programming, January , 1996. 1995 [Satir95] "C++: The Core Language" by Gregory Satir and Doug [Fertuck 92] “Systems Analysis and Design with CASE Tools” Brown, O’Reilly & Associates Inc., 1995. by Len Fertuck, Wm.C. Brown Publishers, 1992. [Schildt95] “Windows 95 Programming in C and C++” by [Korth 91] “Database System Concepts”, 2nd ed., by Henry F. Herbert Schildt, McGraw-Hill, 1995. Korth et al, McGraw-Hill, 1991. [Shlaer88] “Object-Oriented Systems Analysis: Modelling the [Lippman96] “Inside the C++ Object Model” by Stanley World in Data” by Sally Shlaer and Stephen Mellor, Prentice- Lippman, Addison-Wesley, 1996. Hall, 1988. [McCracken87] “A Second Course in Computer Science with [Shlaer 92] “Object Lifecycles: Modelling the World in States” Modula-2” by Daniel McCracken, Wiley, 1987. by Sally Shlaer and Stephen Mellor, Prentice-Hall, 1992. [Meyers88] “Object-Oriented Software Construction” by [Simsion 94] “Data Modelling Essentials” by Graeme Simsion, Bertrand Meyers, Prentice Hall, 1988. Van Nostrand Reinhold, 1994 [Musser96] “STL Tutorial and Reference Guide” by David [Stroustrup91] “The C++ , 2nd ed.” by Musser and Atul Saini, Addison-Wesley, 1996, ISBN 0-201- Bjarne Stroustrup, Addison-Wesley, 1991. 63398-1. [Stroustrup94] “The Design and Evolution of C++” by Bjarne Stroustrup, Addison-Wesley, 1994. 14-41 14-42